diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile deleted file mode 100644 index d59927b1..00000000 --- a/.devcontainer/Dockerfile +++ /dev/null @@ -1,14 +0,0 @@ -# [Choice] Node.js version (use -bullseye variants on local arm64/Apple Silicon): 18, 16, 14, 18-bullseye, 16-bullseye, 14-bullseye, 18-buster, 16-buster, 14-buster -ARG VARIANT=16-bullseye -FROM mcr.microsoft.com/vscode/devcontainers/typescript-node:0-${VARIANT} - -# [Optional] Uncomment this section to install additional OS packages. -# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ -# && apt-get -y install --no-install-recommends - -# [Optional] Uncomment if you want to install an additional version of node using nvm -# ARG EXTRA_NODE_VERSION=10 -# RUN su node -c "source /usr/local/share/nvm/nvm.sh && nvm install ${EXTRA_NODE_VERSION}" - -# [Optional] Uncomment if you want to install more global node packages -# RUN su node -c "npm install -g " diff --git a/.devcontainer/base.Dockerfile b/.devcontainer/base.Dockerfile deleted file mode 100644 index 35b6654f..00000000 --- a/.devcontainer/base.Dockerfile +++ /dev/null @@ -1,17 +0,0 @@ -# [Choice] Node.js version (use -bullseye variants on local arm64/Apple Silicon): 18, 16, 14, 18-bullseye, 16-bullseye, 14-bullseye, 18-buster, 16-buster, 14-buster -ARG VARIANT=16-bullseye -FROM mcr.microsoft.com/vscode/devcontainers/javascript-node:0-${VARIANT} - -# Install tslint, typescript. eslint is installed by javascript image -ARG NODE_MODULES="tslint-to-eslint-config typescript" -COPY library-scripts/meta.env /usr/local/etc/vscode-dev-containers -RUN su node -c "umask 0002 && npm install -g ${NODE_MODULES}" \ - && npm cache clean --force > /dev/null 2>&1 - -# [Optional] Uncomment this section to install additional OS packages. -# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ -# && apt-get -y install --no-install-recommends - -# [Optional] Uncomment if you want to install an additional version of node using nvm -# ARG EXTRA_NODE_VERSION=10 -# RUN su node -c "source /usr/local/share/nvm/nvm.sh && nvm install ${EXTRA_NODE_VERSION}" diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 5aefc161..560b74a3 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,42 +1,25 @@ -// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: -// https://github.com/microsoft/vscode-dev-containers/tree/v0.245.2/containers/typescript-node +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/typescript-node { "name": "Node.js & TypeScript", - "build": { - "dockerfile": "Dockerfile", - // Update 'VARIANT' to pick a Node version: 18, 16, 14. - // Append -bullseye or -buster to pin to an OS version. - // Use -bullseye variants on local on arm64/Apple Silicon. - "args": { - "VARIANT": "18" - } - }, + // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile + "image": "mcr.microsoft.com/devcontainers/typescript-node:0-20", + "features": { + "ghcr.io/devcontainers/features/git:1": {} + } - // Configure tool-specific properties. - "customizations": { - // Configure properties specific to VS Code. - "vscode": { - // Add the IDs of extensions you want installed when the container is created. - "extensions": [ - "dbaeumer.vscode-eslint" - ] - } - }, + // Features to add to the dev container. More info: https://containers.dev/features. + // "features": {}, // Use 'forwardPorts' to make a list of ports inside the container available locally. // "forwardPorts": [], // Use 'postCreateCommand' to run commands after the container is created. - // "postCreateCommand": "npm install", + // "postCreateCommand": "yarn install", - // Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. - "remoteUser": "node", - "features": { - "git": "os-provided" - }, + // Configure tool-specific properties. + // "customizations": {}, - "containerEnv": { - "browserstack_user": "${localEnv:browserstack_user}", - "browserstack_key": "${localEnv:browserstack_key}" - } + // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "root" } diff --git a/.github/workflows/build-test-pull-requests.yml b/.github/workflows/build-test-pull-requests.yml index 190ba59f..5818e469 100644 --- a/.github/workflows/build-test-pull-requests.yml +++ b/.github/workflows/build-test-pull-requests.yml @@ -24,7 +24,7 @@ jobs: # only run functional tests on internal PRs if: github.repository == 'bicarbon8/automated-functional-testing' id: functionaltest - run: npm run test-examples + run: npm run test:examples env: browserstack_user: ${{ secrets.BROWSERSTACK_USER }} browserstack_key: ${{ secrets.BROWSERSTACK_KEY }} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 81485f5a..76befe79 100644 --- a/.gitignore +++ b/.gitignore @@ -30,4 +30,5 @@ coverage/ .nyc_output/ FileSystemMap/ testresults.html -logs/ \ No newline at end of file +logs/ +.env \ No newline at end of file diff --git a/.npmrc b/.npmrc new file mode 100644 index 00000000..214c29d1 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +registry=https://registry.npmjs.org/ diff --git a/README.md b/README.md index 93759f89..4218e273 100644 --- a/README.md +++ b/README.md @@ -5,59 +5,55 @@ library providing a framework for creating Functional Test Automation supporting ### Example Jasmine Test: ```typescript describe('Sample Test', () => { - it('can perform a demonstration of AFT', async () => { - let feature: FeatureObj = new FeatureObj(); + it('[C1234] can perform a demonstration of AFT', async () => { + const aft = new AftTest(); + const feature: FeatureObj = new FeatureObj(); /** * the `verify(assertion).returns(expectation)` function - * checks any specified `AbstractTestCasePlugin` - * and `AbstractDefectPlugin` implementations + * checks any specified `TestExecutionPolicyPlugin` implementations * to ensure the test should be run. It will then - * report to any `AbstractLoggingPlugin` implementations - * with an `ITestResult` indicating the success, + * report to any `ReportingPlugin` implementations + * with an `TestResult` indicating the success, * failure or skipped status */ - await verify(async () => await feature.performAction()) - .withTestId('C1234') - .and.withKnownDefectId('DEFECT-123') - .and.withDescription('expect that performAction will return \'result of action\'') - .returns('result of action'); + await aft.verify(async () => await feature.performAction()) + .returns('result of action'); }); }); ``` the above results in the following console output if the expectation does not return false or throw an exception: ``` -5:29:55 PM - expect that performAction will return 'result of action' - PASS - C1234 +5:29:55 PM - [[C1234] can perform a demonstration of AFT] - PASS - C1234 ``` in more complex scenarios you can perform multiple actions inside the _expectation_ like in the following example: ```typescript describe('Sample Test', () => { - it('can perform a more complex demonstration of AFT', async () => { + it('[C2345][C3344] can perform a more complex demonstration of AFT', async () => { + const aft = new AftTest(); /** * the passed in expectation can accept a `Verifier` which can be used * during more complex actions */ - await verify(async (v: Verifier) => { - await v.logMgr.step('creating instance of FeatureObj'); + await aft.verify(async (v: Verifier) => { + await v.reporter.step('creating instance of FeatureObj'); let feature: FeatureObj = new FeatureObj(); - await v.logMgr.step('about to call performAction'); + await v.reporter.step('about to call performAction'); let result: string = await feature.performAction(); - await v.logMgr.info(`result of performAction was '${result}'`); - await v.logMgr.trace('successfully executed expectation'); + await v.reporter.info(`result of performAction was '${result}'`); + await v.reporter.trace('successfully executed expectation'); return result; - }).withTestId('C2345').and.withTestId('C3344') - .and.withDescription('more complex expectation actions') - .returns(containing('result of action')); + }).returns(containing('result of action')); }); }); ``` which would output the following logs: ``` -5:29:54 PM - more complex expectation actions - STEP - 1: creating instance of FeatureObj -5:29:55 PM - more complex expectation actions - STEP - 2: about to call performAction -5:29:55 PM - more complex expectation actions - INFO - result of performAction was 'result of action' -5:29:56 PM - more complex expectation actions - TRACE - successfully executed expectation -5:29:56 PM - more complex expectation actions - PASS - C2345 -5:29:56 PM - more complex expectation actions - PASS - C3344 +5:29:54 PM - [[C2345][C3344] can perform a more complex demonstration of AFT] - STEP - 1: creating instance of FeatureObj +5:29:55 PM - [[C2345][C3344] can perform a more complex demonstration of AFT] - STEP - 2: about to call performAction +5:29:55 PM - [[C2345][C3344] can perform a more complex demonstration of AFT] - INFO - result of performAction was 'result of action' +5:29:56 PM - [[C2345][C3344] can perform a more complex demonstration of AFT] - TRACE - successfully executed expectation +5:29:56 PM - [[C2345][C3344] can perform a more complex demonstration of AFT] - PASS - C2345 +5:29:56 PM - [[C2345][C3344] can perform a more complex demonstration of AFT] - PASS - C3344 ``` > WARNING: Jasmine's _expect_ calls do not return a boolean as their type definitions would make you think and failed `expect` calls will only throw exceptions if the stop on failure option is enabled: ```typescript @@ -72,61 +68,55 @@ verify(() => {throw new Error('failure');}) // AFT will report as 'failed' - [`aft-core`](./packages/aft-core/README.md) - base library containing helpers and configuration and plugin managers - [`aft-examples`](./packages/aft-examples/README.md) - provides real-world examples of how the AFT libraries can be used in functional tests - [`aft-jasmine-reporter`](./packages/aft-jasmine-reporter/README.md) - a Jasmine Reporter Plugin that integrates with AFT to simplify logging and test execution via AFT -- [`aft-logging-awskinesis`](./packages/aft-logging-awskinesis/README.md) - logging plugin supporting logging to AWS Kinesis Firehose -- [`aft-logging-filesystem`](./packages/aft-logging-filesystem/README.md) - logging plugin supporting logging to .log files for all log output -- [`aft-logging-html`](./packages/aft-logging-html/README.md) - logging plugin supporting logging to a HTML results file +- [`aft-reporting-aws-kinesis-firehose`](./packages/aft-reporting-aws-kinesis-firehose/README.md) - reporting plugin supporting logging to AWS Kinesis Firehose +- [`aft-reporting-filesystem`](./packages/aft-reporting-filesystem/README.md) - reporting plugin supporting logging to .log files for all log output +- [`aft-reporting-html`](./packages/aft-reporting-html/README.md) - reporting plugin supporting logging to a HTML results file - [`aft-mocha-reporter`](./packages/aft-mocha-reporter/README.md) - provides Mocha Reporter Plugin that integrates with AFT to simplify logging and test execution via AFT -- [`aft-testrail`](./packages/aft-testrail/README.md) - logging and test case management plugins supporting logging test results and filtering test execution based on TestRail Projects, Suites and Plans +- [`aft-testrail`](./packages/aft-testrail/README.md) - reporting and test execution policy plugins supporting logging test results and filtering test execution based on TestRail Projects, Suites and Plans - [`aft-ui`](./packages/aft-ui/README.md) - base library supporting development of UI testing packages -- [`aft-ui-browsers`](./packages/aft-ui-browsers/README.md) - adds support for Selenium-based UI testing using BrowserStack, Sauce Labs or your own Selenium Grid -- [`aft-ui-mobile-apps`](./packages/aft-ui-mobile-apps/README.md) - adds support for Appium-based UI testing using BrowserStack, Sauce Labs or your own Appium Grid +- [`aft-ui-selenium`](./packages/aft-ui-selenium/README.md) - adds support for Selenium-based UI testing +- [`aft-ui-webdriverio`](./packages/aft-ui-webdriverio/README.md) - adds support for WebdriverIO-based UI testing - [`aft-web-services`](./packages/aft-web-services/README.md) - adds support for testing REST-based services ## Plugins -the primary benefit of using AFT comes from the plugins and the `Verifier`. Because logging using AFT's `LogManager` will also send to any registered logging plugins, it is easy to create logging plugins that send to any external system such as TestRail or to log results to Elasticsearch. Additionally, before running any _assertion_ passed to a `verify(assertion)` function, AFT will confirm if the _assertion_ should actually be run based on the results of queries to any supplied `TestCasePlugin` implementations and a subsequent queries to any supplied `DefectPlugin` implementations. +the primary benefit of using AFT comes from the plugins and the `Verifier`. Because logging using AFT's `Reporter` will also send to any registered logging plugins, it is easy to create logging plugins that send to any external system such as TestRail or to log results to Elasticsearch. Additionally, before running any _assertion_ passed to a `verify(assertion)` function, AFT will confirm if the _assertion_ should actually be run based on the results of queries to any supplied `TestExecutionPolicyPlugin` implementations. -### Logging Plugins -`aft-core` provides a `LoggingPlugin` abstract class which can be extended to create custom loggers which are then loaded by adding their filenames to the `plugins` array under the `logmanager` section of your `aftconfig.json` +### ReportingPlugin +`aft-core` provides a `ReportingPlugin` class which can be extended from to create custom loggers which are then loaded by adding their filenames to the `pluginNames` array under in your `aftconfig.json` ```json +// aftconfig.json { - "LogManager": { - "plugins": [ - { - "name": "testrail-logging-plugin", - "searchDirectory": "../node_modules", - "options": { - "level": "info", - "enabled": false - } - }, - "html-logging-plugin" - ] + "pluginsSearchDir": "../node_modules", + "pluginNames": [ + "testrail-reporting-plugin", + "html-reporting-plugin" + ], + "TestRailConfig": { + "url": "https://your.testrail.io", + "user": "you@your.domain", + "accessKey": "yourTestRailApiKey", + "projectId": 123, + "suiteIds": [1234, 5678], + "planId": 123456, + "policyEngineEnabled": true, + "logLevel": "error" + }, + "HtmlReportingPluginConfig": { + "outputDir": "../Results", + "logLevel": "debug" } } ``` -> NOTE: you can either specify a `string` containing the plugin filename or an `object` containing the `name`, `searchDirectory` and `options` fields within the `plugins` array configuration to specify a root directory to use when searching for logging plugin implementations -### Test Case Plugin -the purpose of a `TestCasePlugin` implementation is to provide execution control over any expectations by way of supplied _Test IDs_. to specify an implementation of the plugin to load you can add the following to your `aftconfig.json` (where plugins `testrail-test-case-plugin.js` is contained within the test execution directory or a subdirectory of it): +### TestExecutionPolicyPlugin +the purpose of a `TestExecutionPolicyPlugin` implementation is to provide execution control over any expectations by way of supplied _Test IDs_. to specify an implementation of the plugin to load you can add the following to your `aftconfig.json` (where plugin `testrail-test-execution-policy-plugin.js` is contained within the test execution directory or a subdirectory of it): ```json +// aftconfig.json { - "TestCaseManager": { - "plugins": ["testrail-test-case-plugin"] - } -} -``` -> NOTE: if no plugin is specified then external Test Case Management integration will be disabled and _assertions_ will be executed without checking their status before execution - -### Defect Plugin -the purpose of a `DefectPlugin` implementation is to provide execution control over any expectations by way of supplied _Test IDs_ referenced in an external ticket tracking system like Bugzilla or Jira. to specify an implementation of the plugin to load you can add the following to your `aftconfig.json` (where plugins `defect-plugin.js` is contained within the test execution directory or a subdirectory of it): -```json -{ - "DefectManager": { - "plugins": ["defect-plugin"] - } + "pluginNames": ["testrail-test-execution-policy-plugin"] } ``` -> NOTE: if no plugin is specified then external Defect Management integration will be disabled and _assertions_ will be executed without checking their status before execution, however if a Defect Management plugin is specified, the execution of any _assertions_ passed into a `verify(assertion)` function will be halted if any non-closed defects are found when searching for defects that contain reference to the values passed in via `withTestId(caseId)` or via direct reference to defect using `withKnownDefectId(defectId)` +> NOTE: if no plugin is specified then external Policy Engine integration will be disabled and _assertions_ will be executed without first checking that they should be run based on associated Test IDs ## Example Test Project - [`aft-examples`](./packages/aft-examples/README.md) - a demonstration of how to develop UI and REST based functional test automation using AFT is located under `./packages/aft-examples` @@ -148,4 +138,4 @@ the purpose of a `DefectPlugin` implementation is to provide execution control o > use `npx lerna version` to automatically update the version of all projects at once (all changes must be committed first) -> generate documentation using `npx typedoc --entryPointStrategy packages ./packages/* --out ./docs` \ No newline at end of file +> generate documentation `npm run docs` \ No newline at end of file diff --git a/docs/assets/highlight.css b/docs/assets/highlight.css index e0ad998b..a0a505c5 100644 --- a/docs/assets/highlight.css +++ b/docs/assets/highlight.css @@ -7,30 +7,28 @@ --dark-hl-2: #CE9178; --light-hl-3: #0000FF; --dark-hl-3: #569CD6; - --light-hl-4: #001080; - --dark-hl-4: #9CDCFE; + --light-hl-4: #0070C1; + --dark-hl-4: #4FC1FF; --light-hl-5: #267F99; --dark-hl-5: #4EC9B0; --light-hl-6: #008000; --dark-hl-6: #6A9955; --light-hl-7: #AF00DB; --dark-hl-7: #C586C0; - --light-hl-8: #EE0000; - --dark-hl-8: #D7BA7D; + --light-hl-8: #001080; + --dark-hl-8: #9CDCFE; --light-hl-9: #098658; --dark-hl-9: #B5CEA8; - --light-hl-10: #0070C1; - --dark-hl-10: #4FC1FF; - --light-hl-11: #0451A5; - --dark-hl-11: #9CDCFE; - --light-hl-12: #CD3131; - --dark-hl-12: #F44747; - --light-hl-13: #811F3F; - --dark-hl-13: #D16969; - --light-hl-14: #D16969; - --dark-hl-14: #CE9178; - --light-hl-15: #000000; - --dark-hl-15: #D7BA7D; + --light-hl-10: #0451A5; + --dark-hl-10: #9CDCFE; + --light-hl-11: #CD3131; + --dark-hl-11: #F44747; + --light-hl-12: #811F3F; + --dark-hl-12: #D16969; + --light-hl-13: #D16969; + --dark-hl-13: #CE9178; + --light-hl-14: #000000; + --dark-hl-14: #D7BA7D; --light-code-background: #FFFFFF; --dark-code-background: #1E1E1E; } @@ -51,7 +49,6 @@ --hl-12: var(--light-hl-12); --hl-13: var(--light-hl-13); --hl-14: var(--light-hl-14); - --hl-15: var(--light-hl-15); --code-background: var(--light-code-background); } } @@ -71,7 +68,6 @@ --hl-12: var(--dark-hl-12); --hl-13: var(--dark-hl-13); --hl-14: var(--dark-hl-14); - --hl-15: var(--dark-hl-15); --code-background: var(--dark-code-background); } } @@ -91,7 +87,6 @@ --hl-12: var(--light-hl-12); --hl-13: var(--light-hl-13); --hl-14: var(--light-hl-14); - --hl-15: var(--light-hl-15); --code-background: var(--light-code-background); } @@ -111,7 +106,6 @@ --hl-12: var(--dark-hl-12); --hl-13: var(--dark-hl-13); --hl-14: var(--dark-hl-14); - --hl-15: var(--dark-hl-15); --code-background: var(--dark-code-background); } @@ -130,5 +124,4 @@ .hl-12 { color: var(--hl-12); } .hl-13 { color: var(--hl-13); } .hl-14 { color: var(--hl-14); } -.hl-15 { color: var(--hl-15); } pre, code { background: var(--code-background); } diff --git a/docs/assets/search.js b/docs/assets/search.js index bd520b3f..788586e5 100644 --- a/docs/assets/search.js +++ b/docs/assets/search.js @@ -1 +1 @@ -window.searchData = JSON.parse("{\"kinds\":{\"2\":\"Module\",\"4\":\"Namespace\",\"32\":\"Variable\",\"64\":\"Function\",\"128\":\"Class\",\"256\":\"Interface\",\"512\":\"Constructor\",\"1024\":\"Property\",\"2048\":\"Method\",\"65536\":\"Type literal\",\"262144\":\"Accessor\",\"4194304\":\"Type alias\"},\"rows\":[{\"kind\":2,\"name\":\"aft-core\",\"url\":\"modules/aft_core.html\",\"classes\":\"tsd-kind-module\"},{\"kind\":2,\"name\":\"aft-jasmine-reporter\",\"url\":\"modules/aft_jasmine_reporter.html\",\"classes\":\"tsd-kind-module\"},{\"kind\":2,\"name\":\"aft-logging-awskinesis\",\"url\":\"modules/aft_logging_awskinesis.html\",\"classes\":\"tsd-kind-module\"},{\"kind\":2,\"name\":\"aft-logging-filesystem\",\"url\":\"modules/aft_logging_filesystem.html\",\"classes\":\"tsd-kind-module\"},{\"kind\":2,\"name\":\"aft-logging-html\",\"url\":\"modules/aft_logging_html.html\",\"classes\":\"tsd-kind-module\"},{\"kind\":2,\"name\":\"aft-mocha-reporter\",\"url\":\"modules/aft_mocha_reporter.html\",\"classes\":\"tsd-kind-module\"},{\"kind\":2,\"name\":\"aft-testrail\",\"url\":\"modules/aft_testrail.html\",\"classes\":\"tsd-kind-module\"},{\"kind\":2,\"name\":\"aft-ui\",\"url\":\"modules/aft_ui.html\",\"classes\":\"tsd-kind-module\"},{\"kind\":2,\"name\":\"aft-ui-browsers\",\"url\":\"modules/aft_ui_browsers.html\",\"classes\":\"tsd-kind-module\"},{\"kind\":2,\"name\":\"aft-ui-mobile-apps\",\"url\":\"modules/aft_ui_mobile_apps.html\",\"classes\":\"tsd-kind-module\"},{\"kind\":2,\"name\":\"aft-web-services\",\"url\":\"modules/aft_web_services.html\",\"classes\":\"tsd-kind-module\"},{\"kind\":128,\"name\":\"AftConfigProvider\",\"url\":\"classes/aft_core.AftConfigProvider.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_core.AftConfigProvider.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-core.AftConfigProvider\"},{\"kind\":1024,\"name\":\"_aftConfig\",\"url\":\"classes/aft_core.AftConfigProvider.html#_aftConfig\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.AftConfigProvider\"},{\"kind\":1024,\"name\":\"_optsProvider\",\"url\":\"classes/aft_core.AftConfigProvider.html#_optsProvider\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.AftConfigProvider\"},{\"kind\":1024,\"name\":\"configKey\",\"url\":\"classes/aft_core.AftConfigProvider.html#configKey\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-core.AftConfigProvider\"},{\"kind\":262144,\"name\":\"aftConfig\",\"url\":\"classes/aft_core.AftConfigProvider.html#aftConfig\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.AftConfigProvider\"},{\"kind\":262144,\"name\":\"options\",\"url\":\"classes/aft_core.AftConfigProvider.html#options\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.AftConfigProvider\"},{\"kind\":2048,\"name\":\"get\",\"url\":\"classes/aft_core.AftConfigProvider.html#get\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.AftConfigProvider\"},{\"kind\":128,\"name\":\"ChainedProvider\",\"url\":\"classes/aft_core.ChainedProvider.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_core.ChainedProvider.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-core.ChainedProvider\"},{\"kind\":1024,\"name\":\"_providers\",\"url\":\"classes/aft_core.ChainedProvider.html#_providers\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.ChainedProvider\"},{\"kind\":2048,\"name\":\"get\",\"url\":\"classes/aft_core.ChainedProvider.html#get\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.ChainedProvider\"},{\"kind\":32,\"name\":\"cfgmgr\",\"url\":\"variables/aft_core.cfgmgr.html\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":128,\"name\":\"EnvVarProvider\",\"url\":\"classes/aft_core.EnvVarProvider.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_core.EnvVarProvider.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-core.EnvVarProvider\"},{\"kind\":1024,\"name\":\"varPrefix\",\"url\":\"classes/aft_core.EnvVarProvider.html#varPrefix\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-core.EnvVarProvider\"},{\"kind\":2048,\"name\":\"get\",\"url\":\"classes/aft_core.EnvVarProvider.html#get\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.EnvVarProvider\"},{\"kind\":256,\"name\":\"IConfigProvider\",\"url\":\"interfaces/aft_core.IConfigProvider.html\",\"classes\":\"tsd-kind-interface tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":2048,\"name\":\"get\",\"url\":\"interfaces/aft_core.IConfigProvider.html#get\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"aft-core.IConfigProvider\"},{\"kind\":256,\"name\":\"IHasConfig\",\"url\":\"interfaces/aft_core.IHasConfig.html\",\"classes\":\"tsd-kind-interface tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":2048,\"name\":\"config\",\"url\":\"interfaces/aft_core.IHasConfig.html#config\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"aft-core.IHasConfig\"},{\"kind\":256,\"name\":\"IHasOptions\",\"url\":\"interfaces/aft_core.IHasOptions.html\",\"classes\":\"tsd-kind-interface tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":2048,\"name\":\"option\",\"url\":\"interfaces/aft_core.IHasOptions.html#option\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"aft-core.IHasOptions\"},{\"kind\":32,\"name\":\"optmgr\",\"url\":\"variables/aft_core.optmgr.html\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":128,\"name\":\"OptionsProvider\",\"url\":\"classes/aft_core.OptionsProvider.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_core.OptionsProvider.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-core.OptionsProvider\"},{\"kind\":1024,\"name\":\"_options\",\"url\":\"classes/aft_core.OptionsProvider.html#_options\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.OptionsProvider\"},{\"kind\":2048,\"name\":\"get\",\"url\":\"classes/aft_core.OptionsProvider.html#get\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.OptionsProvider\"},{\"kind\":128,\"name\":\"CacheMap\",\"url\":\"classes/aft_core.CacheMap.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_core.CacheMap.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-core.CacheMap\"},{\"kind\":1024,\"name\":\"_internalMap\",\"url\":\"classes/aft_core.CacheMap.html#_internalMap\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.CacheMap\"},{\"kind\":1024,\"name\":\"_cacheDuration\",\"url\":\"classes/aft_core.CacheMap.html#_cacheDuration\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.CacheMap\"},{\"kind\":2048,\"name\":\"clear\",\"url\":\"classes/aft_core.CacheMap.html#clear\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.CacheMap\"},{\"kind\":2048,\"name\":\"delete\",\"url\":\"classes/aft_core.CacheMap.html#delete\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.CacheMap\"},{\"kind\":2048,\"name\":\"forEach\",\"url\":\"classes/aft_core.CacheMap.html#forEach\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.CacheMap\"},{\"kind\":2048,\"name\":\"get\",\"url\":\"classes/aft_core.CacheMap.html#get\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.CacheMap\"},{\"kind\":2048,\"name\":\"has\",\"url\":\"classes/aft_core.CacheMap.html#has\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.CacheMap\"},{\"kind\":2048,\"name\":\"set\",\"url\":\"classes/aft_core.CacheMap.html#set\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.CacheMap\"},{\"kind\":262144,\"name\":\"size\",\"url\":\"classes/aft_core.CacheMap.html#size\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.CacheMap\"},{\"kind\":2048,\"name\":\"entries\",\"url\":\"classes/aft_core.CacheMap.html#entries\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.CacheMap\"},{\"kind\":2048,\"name\":\"keys\",\"url\":\"classes/aft_core.CacheMap.html#keys\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.CacheMap\"},{\"kind\":2048,\"name\":\"values\",\"url\":\"classes/aft_core.CacheMap.html#values\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.CacheMap\"},{\"kind\":2048,\"name\":\"_isStillValid\",\"url\":\"classes/aft_core.CacheMap.html#_isStillValid\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.CacheMap\"},{\"kind\":2048,\"name\":\"[iterator]\",\"url\":\"classes/aft_core.CacheMap.html#_iterator_\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.CacheMap\"},{\"kind\":262144,\"name\":\"[toStringTag]\",\"url\":\"classes/aft_core.CacheMap.html#_toStringTag_\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.CacheMap\"},{\"kind\":4194304,\"name\":\"Action\",\"url\":\"types/aft_core.Action.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_core.Action.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-core.Action\"},{\"kind\":4194304,\"name\":\"Class\",\"url\":\"types/aft_core.Class.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_core.Class.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-core.Class\"},{\"kind\":1024,\"name\":\"prototype\",\"url\":\"types/aft_core.Class.html#__type.prototype\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.Class.__type\"},{\"kind\":4194304,\"name\":\"Func\",\"url\":\"types/aft_core.Func.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_core.Func.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-core.Func\"},{\"kind\":4194304,\"name\":\"JsonKey\",\"url\":\"types/aft_core.JsonKey.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":4194304,\"name\":\"JsonValue\",\"url\":\"types/aft_core.JsonValue.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":4194304,\"name\":\"JsonObject\",\"url\":\"types/aft_core.JsonObject.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":4194304,\"name\":\"ProcessingResult\",\"url\":\"types/aft_core.ProcessingResult.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_core.ProcessingResult.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-core.ProcessingResult\"},{\"kind\":1024,\"name\":\"obj\",\"url\":\"types/aft_core.ProcessingResult.html#__type.obj\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.ProcessingResult.__type\"},{\"kind\":1024,\"name\":\"success\",\"url\":\"types/aft_core.ProcessingResult.html#__type.success\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.ProcessingResult.__type\"},{\"kind\":1024,\"name\":\"message\",\"url\":\"types/aft_core.ProcessingResult.html#__type.message\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.ProcessingResult.__type\"},{\"kind\":4194304,\"name\":\"CacheObject\",\"url\":\"types/aft_core.CacheObject.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_core.CacheObject.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-core.CacheObject\"},{\"kind\":1024,\"name\":\"validUntil\",\"url\":\"types/aft_core.CacheObject.html#__type.validUntil\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.CacheObject.__type\"},{\"kind\":1024,\"name\":\"data\",\"url\":\"types/aft_core.CacheObject.html#__type.data\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.CacheObject.__type\"},{\"kind\":4194304,\"name\":\"Merge\",\"url\":\"types/aft_core.Merge.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":4194304,\"name\":\"RetryBackOffType\",\"url\":\"types/aft_core.RetryBackOffType.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":4194304,\"name\":\"SafeStringOption\",\"url\":\"types/aft_core.SafeStringOption-1.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_core.SafeStringOption-1.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-core.SafeStringOption\"},{\"kind\":1024,\"name\":\"exclude\",\"url\":\"types/aft_core.SafeStringOption-1.html#__type.exclude\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.SafeStringOption.__type\"},{\"kind\":1024,\"name\":\"replaceWith\",\"url\":\"types/aft_core.SafeStringOption-1.html#__type.replaceWith\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.SafeStringOption.__type\"},{\"kind\":4,\"name\":\"SafeStringOption\",\"url\":\"modules/aft_core.SafeStringOption.html\",\"classes\":\"tsd-kind-namespace tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":32,\"name\":\"defaults\",\"url\":\"variables/aft_core.SafeStringOption.defaults.html\",\"classes\":\"tsd-kind-variable tsd-parent-kind-namespace\",\"parent\":\"aft-core.SafeStringOption\"},{\"kind\":32,\"name\":\"convert\",\"url\":\"variables/aft_core.convert.html\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":4194304,\"name\":\"EllipsisLocation\",\"url\":\"types/aft_core.EllipsisLocation.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":64,\"name\":\"ellide\",\"url\":\"functions/aft_core.ellide.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":4194304,\"name\":\"ErrVerbosity\",\"url\":\"types/aft_core.ErrVerbosity.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":4194304,\"name\":\"ErrOptions\",\"url\":\"types/aft_core.ErrOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_core.ErrOptions.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-core.ErrOptions\"},{\"kind\":1024,\"name\":\"logMgr\",\"url\":\"types/aft_core.ErrOptions.html#__type.logMgr\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.ErrOptions.__type\"},{\"kind\":1024,\"name\":\"errLevel\",\"url\":\"types/aft_core.ErrOptions.html#__type.errLevel\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.ErrOptions.__type\"},{\"kind\":1024,\"name\":\"verbosity\",\"url\":\"types/aft_core.ErrOptions.html#__type.verbosity\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.ErrOptions.__type\"},{\"kind\":128,\"name\":\"Err\",\"url\":\"classes/aft_core.Err-1.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_core.Err-1.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-core.Err\"},{\"kind\":1024,\"name\":\"err\",\"url\":\"classes/aft_core.Err-1.html#err\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-core.Err\"},{\"kind\":1024,\"name\":\"_verbosity\",\"url\":\"classes/aft_core.Err-1.html#_verbosity\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Err\"},{\"kind\":262144,\"name\":\"verbosity\",\"url\":\"classes/aft_core.Err-1.html#verbosity\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Err\"},{\"kind\":2048,\"name\":\"setVerbosity\",\"url\":\"classes/aft_core.Err-1.html#setVerbosity\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Err\"},{\"kind\":262144,\"name\":\"type\",\"url\":\"classes/aft_core.Err-1.html#type\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Err\"},{\"kind\":262144,\"name\":\"message\",\"url\":\"classes/aft_core.Err-1.html#message\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Err\"},{\"kind\":262144,\"name\":\"stack\",\"url\":\"classes/aft_core.Err-1.html#stack\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Err\"},{\"kind\":2048,\"name\":\"toString\",\"url\":\"classes/aft_core.Err-1.html#toString\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Err\"},{\"kind\":2048,\"name\":\"_isError\",\"url\":\"classes/aft_core.Err-1.html#_isError\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Err\"},{\"kind\":2048,\"name\":\"_processMessage\",\"url\":\"classes/aft_core.Err-1.html#_processMessage\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Err\"},{\"kind\":2048,\"name\":\"_processStack\",\"url\":\"classes/aft_core.Err-1.html#_processStack\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Err\"},{\"kind\":2048,\"name\":\"_removeInternalStackLines\",\"url\":\"classes/aft_core.Err-1.html#_removeInternalStackLines\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Err\"},{\"kind\":2048,\"name\":\"_removeNewlinesAndExtraWhitespace\",\"url\":\"classes/aft_core.Err-1.html#_removeNewlinesAndExtraWhitespace\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Err\"},{\"kind\":4,\"name\":\"Err\",\"url\":\"modules/aft_core.Err.html\",\"classes\":\"tsd-kind-namespace tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":64,\"name\":\"short\",\"url\":\"functions/aft_core.Err.short.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-namespace\",\"parent\":\"aft-core.Err\"},{\"kind\":64,\"name\":\"full\",\"url\":\"functions/aft_core.Err.full.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-namespace\",\"parent\":\"aft-core.Err\"},{\"kind\":64,\"name\":\"handle\",\"url\":\"functions/aft_core.Err.handle.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-namespace\",\"parent\":\"aft-core.Err\"},{\"kind\":128,\"name\":\"ExpiringFileLock\",\"url\":\"classes/aft_core.ExpiringFileLock.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_core.ExpiringFileLock.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-core.ExpiringFileLock\"},{\"kind\":1024,\"name\":\"lockName\",\"url\":\"classes/aft_core.ExpiringFileLock.html#lockName\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-core.ExpiringFileLock\"},{\"kind\":1024,\"name\":\"lockDuration\",\"url\":\"classes/aft_core.ExpiringFileLock.html#lockDuration\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-core.ExpiringFileLock\"},{\"kind\":1024,\"name\":\"waitDuration\",\"url\":\"classes/aft_core.ExpiringFileLock.html#waitDuration\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-core.ExpiringFileLock\"},{\"kind\":1024,\"name\":\"_lockFileDescriptor\",\"url\":\"classes/aft_core.ExpiringFileLock.html#_lockFileDescriptor\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.ExpiringFileLock\"},{\"kind\":1024,\"name\":\"_timeout\",\"url\":\"classes/aft_core.ExpiringFileLock.html#_timeout\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.ExpiringFileLock\"},{\"kind\":2048,\"name\":\"unlock\",\"url\":\"classes/aft_core.ExpiringFileLock.html#unlock\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.ExpiringFileLock\"},{\"kind\":2048,\"name\":\"_waitForLock\",\"url\":\"classes/aft_core.ExpiringFileLock.html#_waitForLock\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.ExpiringFileLock\"},{\"kind\":32,\"name\":\"fileio\",\"url\":\"variables/aft_core.fileio.html\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":128,\"name\":\"FileSystemMap\",\"url\":\"classes/aft_core.FileSystemMap.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_core.FileSystemMap.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-core.FileSystemMap\"},{\"kind\":1024,\"name\":\"filename\",\"url\":\"classes/aft_core.FileSystemMap.html#filename\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-core.FileSystemMap\"},{\"kind\":1024,\"name\":\"_memoryMap\",\"url\":\"classes/aft_core.FileSystemMap.html#_memoryMap\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.FileSystemMap\"},{\"kind\":2048,\"name\":\"clear\",\"url\":\"classes/aft_core.FileSystemMap.html#clear\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.FileSystemMap\"},{\"kind\":2048,\"name\":\"delete\",\"url\":\"classes/aft_core.FileSystemMap.html#delete\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.FileSystemMap\"},{\"kind\":2048,\"name\":\"forEach\",\"url\":\"classes/aft_core.FileSystemMap.html#forEach\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.FileSystemMap\"},{\"kind\":2048,\"name\":\"get\",\"url\":\"classes/aft_core.FileSystemMap.html#get\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.FileSystemMap\"},{\"kind\":2048,\"name\":\"has\",\"url\":\"classes/aft_core.FileSystemMap.html#has\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.FileSystemMap\"},{\"kind\":2048,\"name\":\"set\",\"url\":\"classes/aft_core.FileSystemMap.html#set\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.FileSystemMap\"},{\"kind\":262144,\"name\":\"size\",\"url\":\"classes/aft_core.FileSystemMap.html#size\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.FileSystemMap\"},{\"kind\":2048,\"name\":\"entries\",\"url\":\"classes/aft_core.FileSystemMap.html#entries\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.FileSystemMap\"},{\"kind\":2048,\"name\":\"keys\",\"url\":\"classes/aft_core.FileSystemMap.html#keys\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.FileSystemMap\"},{\"kind\":2048,\"name\":\"values\",\"url\":\"classes/aft_core.FileSystemMap.html#values\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.FileSystemMap\"},{\"kind\":2048,\"name\":\"_writeToFile\",\"url\":\"classes/aft_core.FileSystemMap.html#_writeToFile\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.FileSystemMap\"},{\"kind\":2048,\"name\":\"_updateMemoryMap\",\"url\":\"classes/aft_core.FileSystemMap.html#_updateMemoryMap\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.FileSystemMap\"},{\"kind\":2048,\"name\":\"[iterator]\",\"url\":\"classes/aft_core.FileSystemMap.html#_iterator_\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.FileSystemMap\"},{\"kind\":262144,\"name\":\"[toStringTag]\",\"url\":\"classes/aft_core.FileSystemMap.html#_toStringTag_\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.FileSystemMap\"},{\"kind\":256,\"name\":\"Disposable\",\"url\":\"interfaces/aft_core.Disposable.html\",\"classes\":\"tsd-kind-interface tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":2048,\"name\":\"dispose\",\"url\":\"interfaces/aft_core.Disposable.html#dispose\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"aft-core.Disposable\"},{\"kind\":4194304,\"name\":\"MachineInfoData\",\"url\":\"types/aft_core.MachineInfoData.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_core.MachineInfoData.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-core.MachineInfoData\"},{\"kind\":1024,\"name\":\"ip\",\"url\":\"types/aft_core.MachineInfoData.html#__type.ip\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.MachineInfoData.__type\"},{\"kind\":1024,\"name\":\"hostname\",\"url\":\"types/aft_core.MachineInfoData.html#__type.hostname\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.MachineInfoData.__type\"},{\"kind\":1024,\"name\":\"user\",\"url\":\"types/aft_core.MachineInfoData.html#__type.user\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.MachineInfoData.__type\"},{\"kind\":32,\"name\":\"machineInfo\",\"url\":\"variables/aft_core.machineInfo.html\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":32,\"name\":\"rand\",\"url\":\"variables/aft_core.rand.html\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":128,\"name\":\"Retry\",\"url\":\"classes/aft_core.Retry.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":2048,\"name\":\"calculateBackOffDelay\",\"url\":\"classes/aft_core.Retry.html#calculateBackOffDelay\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_core.Retry.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":1024,\"name\":\"#retryable\",\"url\":\"classes/aft_core.Retry.html#_retryable\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Retry\"},{\"kind\":1024,\"name\":\"#result\",\"url\":\"classes/aft_core.Retry.html#_result\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Retry\"},{\"kind\":1024,\"name\":\"#delay\",\"url\":\"classes/aft_core.Retry.html#_delay\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Retry\"},{\"kind\":1024,\"name\":\"#currentDelay\",\"url\":\"classes/aft_core.Retry.html#_currentDelay\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Retry\"},{\"kind\":1024,\"name\":\"#backOffType\",\"url\":\"classes/aft_core.Retry.html#_backOffType\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Retry\"},{\"kind\":1024,\"name\":\"#condition\",\"url\":\"classes/aft_core.Retry.html#_condition\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Retry\"},{\"kind\":1024,\"name\":\"#maxAttempts\",\"url\":\"classes/aft_core.Retry.html#_maxAttempts\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Retry\"},{\"kind\":1024,\"name\":\"#totalAttempts\",\"url\":\"classes/aft_core.Retry.html#_totalAttempts\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Retry\"},{\"kind\":1024,\"name\":\"#failAction\",\"url\":\"classes/aft_core.Retry.html#_failAction\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Retry\"},{\"kind\":1024,\"name\":\"#err\",\"url\":\"classes/aft_core.Retry.html#_err\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Retry\"},{\"kind\":1024,\"name\":\"#maxDuration\",\"url\":\"classes/aft_core.Retry.html#_maxDuration\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Retry\"},{\"kind\":1024,\"name\":\"#totalDuration\",\"url\":\"classes/aft_core.Retry.html#_totalDuration\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Retry\"},{\"kind\":1024,\"name\":\"#success\",\"url\":\"classes/aft_core.Retry.html#_success\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Retry\"},{\"kind\":1024,\"name\":\"#reject\",\"url\":\"classes/aft_core.Retry.html#_reject\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Retry\"},{\"kind\":262144,\"name\":\"retryable\",\"url\":\"classes/aft_core.Retry.html#retryable\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":262144,\"name\":\"result\",\"url\":\"classes/aft_core.Retry.html#result\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":262144,\"name\":\"startDelay\",\"url\":\"classes/aft_core.Retry.html#startDelay\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":262144,\"name\":\"currentDelay\",\"url\":\"classes/aft_core.Retry.html#currentDelay\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":262144,\"name\":\"backOffType\",\"url\":\"classes/aft_core.Retry.html#backOffType\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":262144,\"name\":\"condition\",\"url\":\"classes/aft_core.Retry.html#condition\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":262144,\"name\":\"maxAttempts\",\"url\":\"classes/aft_core.Retry.html#maxAttempts\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":262144,\"name\":\"totalAttempts\",\"url\":\"classes/aft_core.Retry.html#totalAttempts\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":262144,\"name\":\"failAction\",\"url\":\"classes/aft_core.Retry.html#failAction\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":262144,\"name\":\"lastError\",\"url\":\"classes/aft_core.Retry.html#lastError\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":262144,\"name\":\"maxDuration\",\"url\":\"classes/aft_core.Retry.html#maxDuration\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":262144,\"name\":\"totalDuration\",\"url\":\"classes/aft_core.Retry.html#totalDuration\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":262144,\"name\":\"isSuccessful\",\"url\":\"classes/aft_core.Retry.html#isSuccessful\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":262144,\"name\":\"reject\",\"url\":\"classes/aft_core.Retry.html#reject\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":2048,\"name\":\"withStartDelayBetweenAttempts\",\"url\":\"classes/aft_core.Retry.html#withStartDelayBetweenAttempts\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":2048,\"name\":\"withBackOff\",\"url\":\"classes/aft_core.Retry.html#withBackOff\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":2048,\"name\":\"until\",\"url\":\"classes/aft_core.Retry.html#until\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":2048,\"name\":\"withMaxAttempts\",\"url\":\"classes/aft_core.Retry.html#withMaxAttempts\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":2048,\"name\":\"withFailAction\",\"url\":\"classes/aft_core.Retry.html#withFailAction\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":2048,\"name\":\"withMaxDuration\",\"url\":\"classes/aft_core.Retry.html#withMaxDuration\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":2048,\"name\":\"rejectIfUnsuccessful\",\"url\":\"classes/aft_core.Retry.html#rejectIfUnsuccessful\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":2048,\"name\":\"isConditionMet\",\"url\":\"classes/aft_core.Retry.html#isConditionMet\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":2048,\"name\":\"then\",\"url\":\"classes/aft_core.Retry.html#then\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":2048,\"name\":\"_getInnerPromise\",\"url\":\"classes/aft_core.Retry.html#_getInnerPromise\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Retry\"},{\"kind\":64,\"name\":\"retry\",\"url\":\"functions/aft_core.retry-1.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":64,\"name\":\"using\",\"url\":\"functions/aft_core.using.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":128,\"name\":\"Verifier\",\"url\":\"classes/aft_core.Verifier.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_core.Verifier.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-core.Verifier\"},{\"kind\":1024,\"name\":\"_assertion\",\"url\":\"classes/aft_core.Verifier.html#_assertion\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-core.Verifier\"},{\"kind\":1024,\"name\":\"_matcher\",\"url\":\"classes/aft_core.Verifier.html#_matcher\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-core.Verifier\"},{\"kind\":1024,\"name\":\"_description\",\"url\":\"classes/aft_core.Verifier.html#_description\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-core.Verifier\"},{\"kind\":1024,\"name\":\"_startTime\",\"url\":\"classes/aft_core.Verifier.html#_startTime\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-core.Verifier\"},{\"kind\":1024,\"name\":\"_innerPromise\",\"url\":\"classes/aft_core.Verifier.html#_innerPromise\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-core.Verifier\"},{\"kind\":1024,\"name\":\"_tests\",\"url\":\"classes/aft_core.Verifier.html#_tests\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-core.Verifier\"},{\"kind\":1024,\"name\":\"_defects\",\"url\":\"classes/aft_core.Verifier.html#_defects\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-core.Verifier\"},{\"kind\":1024,\"name\":\"_logMgr\",\"url\":\"classes/aft_core.Verifier.html#_logMgr\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-core.Verifier\"},{\"kind\":1024,\"name\":\"_testMgr\",\"url\":\"classes/aft_core.Verifier.html#_testMgr\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-core.Verifier\"},{\"kind\":1024,\"name\":\"_defectMgr\",\"url\":\"classes/aft_core.Verifier.html#_defectMgr\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-core.Verifier\"},{\"kind\":1024,\"name\":\"_buildMgr\",\"url\":\"classes/aft_core.Verifier.html#_buildMgr\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-core.Verifier\"},{\"kind\":262144,\"name\":\"logMgr\",\"url\":\"classes/aft_core.Verifier.html#logMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Verifier\"},{\"kind\":262144,\"name\":\"testMgr\",\"url\":\"classes/aft_core.Verifier.html#testMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Verifier\"},{\"kind\":262144,\"name\":\"defectMgr\",\"url\":\"classes/aft_core.Verifier.html#defectMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Verifier\"},{\"kind\":262144,\"name\":\"buildMgr\",\"url\":\"classes/aft_core.Verifier.html#buildMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Verifier\"},{\"kind\":2048,\"name\":\"then\",\"url\":\"classes/aft_core.Verifier.html#then\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Verifier\"},{\"kind\":2048,\"name\":\"_getInnerPromise\",\"url\":\"classes/aft_core.Verifier.html#_getInnerPromise\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-core.Verifier\"},{\"kind\":2048,\"name\":\"_resolveAssertion\",\"url\":\"classes/aft_core.Verifier.html#_resolveAssertion\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-core.Verifier\"},{\"kind\":262144,\"name\":\"and\",\"url\":\"classes/aft_core.Verifier.html#and\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Verifier\"},{\"kind\":2048,\"name\":\"verify\",\"url\":\"classes/aft_core.Verifier.html#verify\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Verifier\"},{\"kind\":2048,\"name\":\"withDescription\",\"url\":\"classes/aft_core.Verifier.html#withDescription\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Verifier\"},{\"kind\":2048,\"name\":\"withTestIds\",\"url\":\"classes/aft_core.Verifier.html#withTestIds\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Verifier\"},{\"kind\":2048,\"name\":\"withKnownDefectIds\",\"url\":\"classes/aft_core.Verifier.html#withKnownDefectIds\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Verifier\"},{\"kind\":2048,\"name\":\"returns\",\"url\":\"classes/aft_core.Verifier.html#returns\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Verifier\"},{\"kind\":2048,\"name\":\"withLogManager\",\"url\":\"classes/aft_core.Verifier.html#withLogManager\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Verifier\"},{\"kind\":2048,\"name\":\"withTestCaseManager\",\"url\":\"classes/aft_core.Verifier.html#withTestCaseManager\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Verifier\"},{\"kind\":2048,\"name\":\"withDefectManager\",\"url\":\"classes/aft_core.Verifier.html#withDefectManager\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Verifier\"},{\"kind\":2048,\"name\":\"withBuildInfoManager\",\"url\":\"classes/aft_core.Verifier.html#withBuildInfoManager\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Verifier\"},{\"kind\":2048,\"name\":\"_shouldRun_tests\",\"url\":\"classes/aft_core.Verifier.html#_shouldRun_tests\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-core.Verifier\"},{\"kind\":2048,\"name\":\"_shouldRun_defects\",\"url\":\"classes/aft_core.Verifier.html#_shouldRun_defects\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-core.Verifier\"},{\"kind\":2048,\"name\":\"_logResult\",\"url\":\"classes/aft_core.Verifier.html#_logResult\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-core.Verifier\"},{\"kind\":2048,\"name\":\"_logMessage\",\"url\":\"classes/aft_core.Verifier.html#_logMessage\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-core.Verifier\"},{\"kind\":2048,\"name\":\"_generateTestResults\",\"url\":\"classes/aft_core.Verifier.html#_generateTestResults\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-core.Verifier\"},{\"kind\":2048,\"name\":\"_generateTestResult\",\"url\":\"classes/aft_core.Verifier.html#_generateTestResult\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-core.Verifier\"},{\"kind\":64,\"name\":\"verify\",\"url\":\"functions/aft_core.verify.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":256,\"name\":\"VerifierMatcher\",\"url\":\"interfaces/aft_core.VerifierMatcher.html\",\"classes\":\"tsd-kind-interface tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":1024,\"name\":\"expected\",\"url\":\"interfaces/aft_core.VerifierMatcher.html#expected\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"aft-core.VerifierMatcher\"},{\"kind\":2048,\"name\":\"setActual\",\"url\":\"interfaces/aft_core.VerifierMatcher.html#setActual\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"aft-core.VerifierMatcher\"},{\"kind\":2048,\"name\":\"compare\",\"url\":\"interfaces/aft_core.VerifierMatcher.html#compare\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"aft-core.VerifierMatcher\"},{\"kind\":2048,\"name\":\"failureString\",\"url\":\"interfaces/aft_core.VerifierMatcher.html#failureString\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"aft-core.VerifierMatcher\"},{\"kind\":64,\"name\":\"equaling\",\"url\":\"functions/aft_core.equaling.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":64,\"name\":\"exactly\",\"url\":\"functions/aft_core.exactly.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":64,\"name\":\"between\",\"url\":\"functions/aft_core.between.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":64,\"name\":\"containing\",\"url\":\"functions/aft_core.containing.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":64,\"name\":\"havingValue\",\"url\":\"functions/aft_core.havingValue.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":64,\"name\":\"greaterThan\",\"url\":\"functions/aft_core.greaterThan.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":64,\"name\":\"lessThan\",\"url\":\"functions/aft_core.lessThan.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":64,\"name\":\"not\",\"url\":\"functions/aft_core.not.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":32,\"name\":\"wait\",\"url\":\"variables/aft_core.wait.html\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":4194304,\"name\":\"PluginOptions\",\"url\":\"types/aft_core.PluginOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_core.PluginOptions.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-core.PluginOptions\"},{\"kind\":1024,\"name\":\"enabled\",\"url\":\"types/aft_core.PluginOptions.html#__type.enabled\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.PluginOptions.__type\"},{\"kind\":128,\"name\":\"Plugin\",\"url\":\"classes/aft_core.Plugin.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_core.Plugin.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-core.Plugin\"},{\"kind\":1024,\"name\":\"_opts\",\"url\":\"classes/aft_core.Plugin.html#_opts\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Plugin\"},{\"kind\":1024,\"name\":\"_enabled\",\"url\":\"classes/aft_core.Plugin.html#_enabled\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Plugin\"},{\"kind\":2048,\"name\":\"option\",\"url\":\"classes/aft_core.Plugin.html#option\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Plugin\"},{\"kind\":262144,\"name\":\"enabled\",\"url\":\"classes/aft_core.Plugin.html#enabled\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Plugin\"},{\"kind\":4194304,\"name\":\"PluginConfig\",\"url\":\"types/aft_core.PluginConfig.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_core.PluginConfig.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-core.PluginConfig\"},{\"kind\":1024,\"name\":\"name\",\"url\":\"types/aft_core.PluginConfig.html#__type.name\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.PluginConfig.__type\"},{\"kind\":1024,\"name\":\"searchDirectory\",\"url\":\"types/aft_core.PluginConfig.html#__type.searchDirectory\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.PluginConfig.__type\"},{\"kind\":1024,\"name\":\"options\",\"url\":\"types/aft_core.PluginConfig.html#__type.options\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.PluginConfig.__type\"},{\"kind\":32,\"name\":\"pluginloader\",\"url\":\"variables/aft_core.pluginloader.html\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":4194304,\"name\":\"PluginManagerOptions\",\"url\":\"types/aft_core.PluginManagerOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_core.PluginManagerOptions.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-core.PluginManagerOptions\"},{\"kind\":1024,\"name\":\"plugins\",\"url\":\"types/aft_core.PluginManagerOptions.html#__type.plugins\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.PluginManagerOptions.__type\"},{\"kind\":128,\"name\":\"PluginManager\",\"url\":\"classes/aft_core.PluginManager.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_core.PluginManager.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-core.PluginManager\"},{\"kind\":1024,\"name\":\"_plugins\",\"url\":\"classes/aft_core.PluginManager.html#_plugins\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.PluginManager\"},{\"kind\":1024,\"name\":\"_config\",\"url\":\"classes/aft_core.PluginManager.html#_config\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.PluginManager\"},{\"kind\":1024,\"name\":\"_options\",\"url\":\"classes/aft_core.PluginManager.html#_options\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.PluginManager\"},{\"kind\":2048,\"name\":\"config\",\"url\":\"classes/aft_core.PluginManager.html#config\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.PluginManager\"},{\"kind\":2048,\"name\":\"option\",\"url\":\"classes/aft_core.PluginManager.html#option\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.PluginManager\"},{\"kind\":2048,\"name\":\"pluginConfigs\",\"url\":\"classes/aft_core.PluginManager.html#pluginConfigs\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.PluginManager\"},{\"kind\":2048,\"name\":\"plugins\",\"url\":\"classes/aft_core.PluginManager.html#plugins\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.PluginManager\"},{\"kind\":2048,\"name\":\"first\",\"url\":\"classes/aft_core.PluginManager.html#first\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.PluginManager\"},{\"kind\":2048,\"name\":\"enabled\",\"url\":\"classes/aft_core.PluginManager.html#enabled\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.PluginManager\"},{\"kind\":2048,\"name\":\"named\",\"url\":\"classes/aft_core.PluginManager.html#named\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.PluginManager\"},{\"kind\":2048,\"name\":\"load\",\"url\":\"classes/aft_core.PluginManager.html#load\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.PluginManager\"},{\"kind\":4194304,\"name\":\"PluginManagerWithLoggingOptions\",\"url\":\"types/aft_core.PluginManagerWithLoggingOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":128,\"name\":\"PluginManagerWithLogging\",\"url\":\"classes/aft_core.PluginManagerWithLogging.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_core.PluginManagerWithLogging.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-core.PluginManagerWithLogging\"},{\"kind\":1024,\"name\":\"_logMgr\",\"url\":\"classes/aft_core.PluginManagerWithLogging.html#_logMgr\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.PluginManagerWithLogging\"},{\"kind\":2048,\"name\":\"config\",\"url\":\"classes/aft_core.PluginManagerWithLogging.html#config\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.PluginManagerWithLogging\"},{\"kind\":2048,\"name\":\"logMgr\",\"url\":\"classes/aft_core.PluginManagerWithLogging.html#logMgr\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.PluginManagerWithLogging\"},{\"kind\":2048,\"name\":\"option\",\"url\":\"classes/aft_core.PluginManagerWithLogging.html#option\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.PluginManagerWithLogging\"},{\"kind\":2048,\"name\":\"pluginConfigs\",\"url\":\"classes/aft_core.PluginManagerWithLogging.html#pluginConfigs\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.PluginManagerWithLogging\"},{\"kind\":2048,\"name\":\"plugins\",\"url\":\"classes/aft_core.PluginManagerWithLogging.html#plugins\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.PluginManagerWithLogging\"},{\"kind\":2048,\"name\":\"first\",\"url\":\"classes/aft_core.PluginManagerWithLogging.html#first\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.PluginManagerWithLogging\"},{\"kind\":2048,\"name\":\"enabled\",\"url\":\"classes/aft_core.PluginManagerWithLogging.html#enabled\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.PluginManagerWithLogging\"},{\"kind\":2048,\"name\":\"named\",\"url\":\"classes/aft_core.PluginManagerWithLogging.html#named\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.PluginManagerWithLogging\"},{\"kind\":2048,\"name\":\"load\",\"url\":\"classes/aft_core.PluginManagerWithLogging.html#load\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.PluginManagerWithLogging\"},{\"kind\":4194304,\"name\":\"BuildInfoPluginOptions\",\"url\":\"types/aft_core.BuildInfoPluginOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":128,\"name\":\"BuildInfoPlugin\",\"url\":\"classes/aft_core.BuildInfoPlugin.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_core.BuildInfoPlugin.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.BuildInfoPlugin\"},{\"kind\":2048,\"name\":\"buildName\",\"url\":\"classes/aft_core.BuildInfoPlugin.html#buildName\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.BuildInfoPlugin\"},{\"kind\":2048,\"name\":\"buildNumber\",\"url\":\"classes/aft_core.BuildInfoPlugin.html#buildNumber\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.BuildInfoPlugin\"},{\"kind\":2048,\"name\":\"option\",\"url\":\"classes/aft_core.BuildInfoPlugin.html#option\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.BuildInfoPlugin\"},{\"kind\":262144,\"name\":\"enabled\",\"url\":\"classes/aft_core.BuildInfoPlugin.html#enabled\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.BuildInfoPlugin\"},{\"kind\":4194304,\"name\":\"BuildInfoManagerOptions\",\"url\":\"types/aft_core.BuildInfoManagerOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":128,\"name\":\"BuildInfoManager\",\"url\":\"classes/aft_core.BuildInfoManager.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_core.BuildInfoManager.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.BuildInfoManager\"},{\"kind\":1024,\"name\":\"safeStrOpt\",\"url\":\"classes/aft_core.BuildInfoManager.html#safeStrOpt\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.BuildInfoManager\"},{\"kind\":2048,\"name\":\"buildName\",\"url\":\"classes/aft_core.BuildInfoManager.html#buildName\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.BuildInfoManager\"},{\"kind\":2048,\"name\":\"buildNumber\",\"url\":\"classes/aft_core.BuildInfoManager.html#buildNumber\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.BuildInfoManager\"},{\"kind\":2048,\"name\":\"get\",\"url\":\"classes/aft_core.BuildInfoManager.html#get\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.BuildInfoManager\"},{\"kind\":2048,\"name\":\"config\",\"url\":\"classes/aft_core.BuildInfoManager.html#config\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.BuildInfoManager\"},{\"kind\":2048,\"name\":\"logMgr\",\"url\":\"classes/aft_core.BuildInfoManager.html#logMgr\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.BuildInfoManager\"},{\"kind\":2048,\"name\":\"option\",\"url\":\"classes/aft_core.BuildInfoManager.html#option\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.BuildInfoManager\"},{\"kind\":2048,\"name\":\"pluginConfigs\",\"url\":\"classes/aft_core.BuildInfoManager.html#pluginConfigs\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.BuildInfoManager\"},{\"kind\":2048,\"name\":\"plugins\",\"url\":\"classes/aft_core.BuildInfoManager.html#plugins\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.BuildInfoManager\"},{\"kind\":2048,\"name\":\"first\",\"url\":\"classes/aft_core.BuildInfoManager.html#first\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.BuildInfoManager\"},{\"kind\":2048,\"name\":\"enabled\",\"url\":\"classes/aft_core.BuildInfoManager.html#enabled\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.BuildInfoManager\"},{\"kind\":2048,\"name\":\"named\",\"url\":\"classes/aft_core.BuildInfoManager.html#named\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.BuildInfoManager\"},{\"kind\":2048,\"name\":\"load\",\"url\":\"classes/aft_core.BuildInfoManager.html#load\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.BuildInfoManager\"},{\"kind\":32,\"name\":\"buildinfo\",\"url\":\"variables/aft_core.buildinfo.html\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":4194304,\"name\":\"DefectStatus\",\"url\":\"types/aft_core.DefectStatus.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":4194304,\"name\":\"Defect\",\"url\":\"types/aft_core.Defect.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_core.Defect.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-core.Defect\"},{\"kind\":1024,\"name\":\"id\",\"url\":\"types/aft_core.Defect.html#__type.id\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.Defect.__type\"},{\"kind\":1024,\"name\":\"title\",\"url\":\"types/aft_core.Defect.html#__type.title\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.Defect.__type\"},{\"kind\":1024,\"name\":\"description\",\"url\":\"types/aft_core.Defect.html#__type.description\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.Defect.__type\"},{\"kind\":1024,\"name\":\"status\",\"url\":\"types/aft_core.Defect.html#__type.status\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.Defect.__type\"},{\"kind\":4194304,\"name\":\"DefectPluginOptions\",\"url\":\"types/aft_core.DefectPluginOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":128,\"name\":\"DefectPlugin\",\"url\":\"classes/aft_core.DefectPlugin.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_core.DefectPlugin.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.DefectPlugin\"},{\"kind\":2048,\"name\":\"getDefect\",\"url\":\"classes/aft_core.DefectPlugin.html#getDefect\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.DefectPlugin\"},{\"kind\":2048,\"name\":\"findDefects\",\"url\":\"classes/aft_core.DefectPlugin.html#findDefects\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.DefectPlugin\"},{\"kind\":2048,\"name\":\"option\",\"url\":\"classes/aft_core.DefectPlugin.html#option\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.DefectPlugin\"},{\"kind\":262144,\"name\":\"enabled\",\"url\":\"classes/aft_core.DefectPlugin.html#enabled\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.DefectPlugin\"},{\"kind\":128,\"name\":\"DefectManager\",\"url\":\"classes/aft_core.DefectManager.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_core.DefectManager.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.DefectManager\"},{\"kind\":2048,\"name\":\"getDefect\",\"url\":\"classes/aft_core.DefectManager.html#getDefect\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.DefectManager\"},{\"kind\":2048,\"name\":\"findDefects\",\"url\":\"classes/aft_core.DefectManager.html#findDefects\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.DefectManager\"},{\"kind\":2048,\"name\":\"config\",\"url\":\"classes/aft_core.DefectManager.html#config\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.DefectManager\"},{\"kind\":2048,\"name\":\"logMgr\",\"url\":\"classes/aft_core.DefectManager.html#logMgr\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.DefectManager\"},{\"kind\":2048,\"name\":\"option\",\"url\":\"classes/aft_core.DefectManager.html#option\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.DefectManager\"},{\"kind\":2048,\"name\":\"pluginConfigs\",\"url\":\"classes/aft_core.DefectManager.html#pluginConfigs\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.DefectManager\"},{\"kind\":2048,\"name\":\"plugins\",\"url\":\"classes/aft_core.DefectManager.html#plugins\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.DefectManager\"},{\"kind\":2048,\"name\":\"first\",\"url\":\"classes/aft_core.DefectManager.html#first\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.DefectManager\"},{\"kind\":2048,\"name\":\"enabled\",\"url\":\"classes/aft_core.DefectManager.html#enabled\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.DefectManager\"},{\"kind\":2048,\"name\":\"named\",\"url\":\"classes/aft_core.DefectManager.html#named\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.DefectManager\"},{\"kind\":2048,\"name\":\"load\",\"url\":\"classes/aft_core.DefectManager.html#load\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.DefectManager\"},{\"kind\":32,\"name\":\"defects\",\"url\":\"variables/aft_core.defects.html\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":4194304,\"name\":\"LogMessageData\",\"url\":\"types/aft_core.LogMessageData.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_core.LogMessageData.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-core.LogMessageData\"},{\"kind\":1024,\"name\":\"name\",\"url\":\"types/aft_core.LogMessageData.html#__type.name\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.LogMessageData.__type\"},{\"kind\":1024,\"name\":\"level\",\"url\":\"types/aft_core.LogMessageData.html#__type.level\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.LogMessageData.__type\"},{\"kind\":1024,\"name\":\"message\",\"url\":\"types/aft_core.LogMessageData.html#__type.message\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.LogMessageData.__type\"},{\"kind\":4194304,\"name\":\"LogManagerOptions\",\"url\":\"types/aft_core.LogManagerOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":128,\"name\":\"LogManager\",\"url\":\"classes/aft_core.LogManager-1.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_core.LogManager-1.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-core.LogManager\"},{\"kind\":1024,\"name\":\"_stepCount\",\"url\":\"classes/aft_core.LogManager-1.html#_stepCount\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.LogManager\"},{\"kind\":262144,\"name\":\"logName\",\"url\":\"classes/aft_core.LogManager-1.html#logName\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.LogManager\"},{\"kind\":2048,\"name\":\"level\",\"url\":\"classes/aft_core.LogManager-1.html#level\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.LogManager\"},{\"kind\":2048,\"name\":\"trace\",\"url\":\"classes/aft_core.LogManager-1.html#trace\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.LogManager\"},{\"kind\":2048,\"name\":\"debug\",\"url\":\"classes/aft_core.LogManager-1.html#debug\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.LogManager\"},{\"kind\":2048,\"name\":\"info\",\"url\":\"classes/aft_core.LogManager-1.html#info\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.LogManager\"},{\"kind\":2048,\"name\":\"step\",\"url\":\"classes/aft_core.LogManager-1.html#step\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.LogManager\"},{\"kind\":2048,\"name\":\"warn\",\"url\":\"classes/aft_core.LogManager-1.html#warn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.LogManager\"},{\"kind\":2048,\"name\":\"pass\",\"url\":\"classes/aft_core.LogManager-1.html#pass\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.LogManager\"},{\"kind\":2048,\"name\":\"fail\",\"url\":\"classes/aft_core.LogManager-1.html#fail\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.LogManager\"},{\"kind\":2048,\"name\":\"error\",\"url\":\"classes/aft_core.LogManager-1.html#error\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.LogManager\"},{\"kind\":2048,\"name\":\"log\",\"url\":\"classes/aft_core.LogManager-1.html#log\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.LogManager\"},{\"kind\":2048,\"name\":\"logResult\",\"url\":\"classes/aft_core.LogManager-1.html#logResult\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.LogManager\"},{\"kind\":2048,\"name\":\"dispose\",\"url\":\"classes/aft_core.LogManager-1.html#dispose\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.LogManager\"},{\"kind\":2048,\"name\":\"pluginConfigs\",\"url\":\"classes/aft_core.LogManager-1.html#pluginConfigs\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.LogManager\"},{\"kind\":2048,\"name\":\"config\",\"url\":\"classes/aft_core.LogManager-1.html#config\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.LogManager\"},{\"kind\":2048,\"name\":\"option\",\"url\":\"classes/aft_core.LogManager-1.html#option\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.LogManager\"},{\"kind\":2048,\"name\":\"plugins\",\"url\":\"classes/aft_core.LogManager-1.html#plugins\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.LogManager\"},{\"kind\":2048,\"name\":\"first\",\"url\":\"classes/aft_core.LogManager-1.html#first\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.LogManager\"},{\"kind\":2048,\"name\":\"enabled\",\"url\":\"classes/aft_core.LogManager-1.html#enabled\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.LogManager\"},{\"kind\":2048,\"name\":\"named\",\"url\":\"classes/aft_core.LogManager-1.html#named\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.LogManager\"},{\"kind\":2048,\"name\":\"load\",\"url\":\"classes/aft_core.LogManager-1.html#load\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.LogManager\"},{\"kind\":4,\"name\":\"LogManager\",\"url\":\"modules/aft_core.LogManager.html\",\"classes\":\"tsd-kind-namespace tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":64,\"name\":\"format\",\"url\":\"functions/aft_core.LogManager.format.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-namespace\",\"parent\":\"aft-core.LogManager\"},{\"kind\":64,\"name\":\"toConsole\",\"url\":\"functions/aft_core.LogManager.toConsole.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-namespace\",\"parent\":\"aft-core.LogManager\"},{\"kind\":4194304,\"name\":\"LogLevel\",\"url\":\"types/aft_core.LogLevel-1.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":4,\"name\":\"LogLevel\",\"url\":\"modules/aft_core.LogLevel.html\",\"classes\":\"tsd-kind-namespace tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":64,\"name\":\"isType\",\"url\":\"functions/aft_core.LogLevel.isType.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-namespace\",\"parent\":\"aft-core.LogLevel\"},{\"kind\":64,\"name\":\"toValue\",\"url\":\"functions/aft_core.LogLevel.toValue.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-namespace\",\"parent\":\"aft-core.LogLevel\"},{\"kind\":4194304,\"name\":\"LoggingPluginOptions\",\"url\":\"types/aft_core.LoggingPluginOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":128,\"name\":\"LoggingPlugin\",\"url\":\"classes/aft_core.LoggingPlugin.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_core.LoggingPlugin.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.LoggingPlugin\"},{\"kind\":1024,\"name\":\"_level\",\"url\":\"classes/aft_core.LoggingPlugin.html#_level\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.LoggingPlugin\"},{\"kind\":262144,\"name\":\"level\",\"url\":\"classes/aft_core.LoggingPlugin.html#level\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.LoggingPlugin\"},{\"kind\":2048,\"name\":\"log\",\"url\":\"classes/aft_core.LoggingPlugin.html#log\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.LoggingPlugin\"},{\"kind\":2048,\"name\":\"logResult\",\"url\":\"classes/aft_core.LoggingPlugin.html#logResult\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.LoggingPlugin\"},{\"kind\":2048,\"name\":\"dispose\",\"url\":\"classes/aft_core.LoggingPlugin.html#dispose\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.LoggingPlugin\"},{\"kind\":2048,\"name\":\"option\",\"url\":\"classes/aft_core.LoggingPlugin.html#option\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.LoggingPlugin\"},{\"kind\":262144,\"name\":\"enabled\",\"url\":\"classes/aft_core.LoggingPlugin.html#enabled\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.LoggingPlugin\"},{\"kind\":4194304,\"name\":\"TestCasePluginOptions\",\"url\":\"types/aft_core.TestCasePluginOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":128,\"name\":\"TestCasePlugin\",\"url\":\"classes/aft_core.TestCasePlugin.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_core.TestCasePlugin.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.TestCasePlugin\"},{\"kind\":2048,\"name\":\"getTestCase\",\"url\":\"classes/aft_core.TestCasePlugin.html#getTestCase\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.TestCasePlugin\"},{\"kind\":2048,\"name\":\"findTestCases\",\"url\":\"classes/aft_core.TestCasePlugin.html#findTestCases\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.TestCasePlugin\"},{\"kind\":2048,\"name\":\"shouldRun\",\"url\":\"classes/aft_core.TestCasePlugin.html#shouldRun\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.TestCasePlugin\"},{\"kind\":2048,\"name\":\"option\",\"url\":\"classes/aft_core.TestCasePlugin.html#option\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.TestCasePlugin\"},{\"kind\":262144,\"name\":\"enabled\",\"url\":\"classes/aft_core.TestCasePlugin.html#enabled\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.TestCasePlugin\"},{\"kind\":4194304,\"name\":\"TestCaseManagerOptions\",\"url\":\"types/aft_core.TestCaseManagerOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":128,\"name\":\"TestCaseManager\",\"url\":\"classes/aft_core.TestCaseManager.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_core.TestCaseManager.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.TestCaseManager\"},{\"kind\":2048,\"name\":\"getTestCase\",\"url\":\"classes/aft_core.TestCaseManager.html#getTestCase\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.TestCaseManager\"},{\"kind\":2048,\"name\":\"findTestCases\",\"url\":\"classes/aft_core.TestCaseManager.html#findTestCases\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.TestCaseManager\"},{\"kind\":2048,\"name\":\"shouldRun\",\"url\":\"classes/aft_core.TestCaseManager.html#shouldRun\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.TestCaseManager\"},{\"kind\":2048,\"name\":\"config\",\"url\":\"classes/aft_core.TestCaseManager.html#config\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.TestCaseManager\"},{\"kind\":2048,\"name\":\"logMgr\",\"url\":\"classes/aft_core.TestCaseManager.html#logMgr\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.TestCaseManager\"},{\"kind\":2048,\"name\":\"option\",\"url\":\"classes/aft_core.TestCaseManager.html#option\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.TestCaseManager\"},{\"kind\":2048,\"name\":\"pluginConfigs\",\"url\":\"classes/aft_core.TestCaseManager.html#pluginConfigs\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.TestCaseManager\"},{\"kind\":2048,\"name\":\"plugins\",\"url\":\"classes/aft_core.TestCaseManager.html#plugins\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.TestCaseManager\"},{\"kind\":2048,\"name\":\"first\",\"url\":\"classes/aft_core.TestCaseManager.html#first\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.TestCaseManager\"},{\"kind\":2048,\"name\":\"enabled\",\"url\":\"classes/aft_core.TestCaseManager.html#enabled\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.TestCaseManager\"},{\"kind\":2048,\"name\":\"named\",\"url\":\"classes/aft_core.TestCaseManager.html#named\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.TestCaseManager\"},{\"kind\":2048,\"name\":\"load\",\"url\":\"classes/aft_core.TestCaseManager.html#load\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.TestCaseManager\"},{\"kind\":32,\"name\":\"testcases\",\"url\":\"variables/aft_core.testcases.html\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":4194304,\"name\":\"TestCase\",\"url\":\"types/aft_core.TestCase.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_core.TestCase.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-core.TestCase\"},{\"kind\":1024,\"name\":\"id\",\"url\":\"types/aft_core.TestCase.html#__type.id\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.TestCase.__type\"},{\"kind\":1024,\"name\":\"created\",\"url\":\"types/aft_core.TestCase.html#__type.created\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.TestCase.__type\"},{\"kind\":1024,\"name\":\"title\",\"url\":\"types/aft_core.TestCase.html#__type.title\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.TestCase.__type\"},{\"kind\":1024,\"name\":\"description\",\"url\":\"types/aft_core.TestCase.html#__type.description\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.TestCase.__type\"},{\"kind\":1024,\"name\":\"status\",\"url\":\"types/aft_core.TestCase.html#__type.status\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.TestCase.__type\"},{\"kind\":1024,\"name\":\"result\",\"url\":\"types/aft_core.TestCase.html#__type.result\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.TestCase.__type\"},{\"kind\":4194304,\"name\":\"TestResult\",\"url\":\"types/aft_core.TestResult.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_core.TestResult.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-core.TestResult\"},{\"kind\":1024,\"name\":\"testId\",\"url\":\"types/aft_core.TestResult.html#__type.testId\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.TestResult.__type\"},{\"kind\":1024,\"name\":\"resultMessage\",\"url\":\"types/aft_core.TestResult.html#__type.resultMessage\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.TestResult.__type\"},{\"kind\":1024,\"name\":\"status\",\"url\":\"types/aft_core.TestResult.html#__type.status\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.TestResult.__type\"},{\"kind\":1024,\"name\":\"resultId\",\"url\":\"types/aft_core.TestResult.html#__type.resultId\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.TestResult.__type\"},{\"kind\":1024,\"name\":\"created\",\"url\":\"types/aft_core.TestResult.html#__type.created\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.TestResult.__type\"},{\"kind\":1024,\"name\":\"defects\",\"url\":\"types/aft_core.TestResult.html#__type.defects\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.TestResult.__type\"},{\"kind\":1024,\"name\":\"metadata\",\"url\":\"types/aft_core.TestResult.html#__type.metadata\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.TestResult.__type\"},{\"kind\":4194304,\"name\":\"TestStatus\",\"url\":\"types/aft_core.TestStatus.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":128,\"name\":\"AftJasmineReporter\",\"url\":\"classes/aft_jasmine_reporter.AftJasmineReporter.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-jasmine-reporter\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_jasmine_reporter.AftJasmineReporter.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-jasmine-reporter.AftJasmineReporter\"},{\"kind\":1024,\"name\":\"_async2Sync\",\"url\":\"classes/aft_jasmine_reporter.AftJasmineReporter.html#_async2Sync\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-jasmine-reporter.AftJasmineReporter\"},{\"kind\":1024,\"name\":\"_testNames\",\"url\":\"classes/aft_jasmine_reporter.AftJasmineReporter.html#_testNames\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-jasmine-reporter.AftJasmineReporter\"},{\"kind\":2048,\"name\":\"jasmineStarted\",\"url\":\"classes/aft_jasmine_reporter.AftJasmineReporter.html#jasmineStarted\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-jasmine-reporter.AftJasmineReporter\"},{\"kind\":2048,\"name\":\"specStarted\",\"url\":\"classes/aft_jasmine_reporter.AftJasmineReporter.html#specStarted\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-jasmine-reporter.AftJasmineReporter\"},{\"kind\":2048,\"name\":\"specDone\",\"url\":\"classes/aft_jasmine_reporter.AftJasmineReporter.html#specDone\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-jasmine-reporter.AftJasmineReporter\"},{\"kind\":2048,\"name\":\"_asyncSpecDone\",\"url\":\"classes/aft_jasmine_reporter.AftJasmineReporter.html#_asyncSpecDone\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-jasmine-reporter.AftJasmineReporter\"},{\"kind\":128,\"name\":\"AftLog\",\"url\":\"classes/aft_jasmine_reporter.AftLog.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-jasmine-reporter\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_jasmine_reporter.AftLog.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-jasmine-reporter.AftLog\"},{\"kind\":1024,\"name\":\"_logMgr\",\"url\":\"classes/aft_jasmine_reporter.AftLog.html#_logMgr\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-jasmine-reporter.AftLog\"},{\"kind\":1024,\"name\":\"_testNames\",\"url\":\"classes/aft_jasmine_reporter.AftLog.html#_testNames\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-jasmine-reporter.AftLog\"},{\"kind\":1024,\"name\":\"test\",\"url\":\"classes/aft_jasmine_reporter.AftLog.html#test\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-jasmine-reporter.AftLog\"},{\"kind\":262144,\"name\":\"fullName\",\"url\":\"classes/aft_jasmine_reporter.AftLog.html#fullName\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-jasmine-reporter.AftLog\"},{\"kind\":262144,\"name\":\"logMgr\",\"url\":\"classes/aft_jasmine_reporter.AftLog.html#logMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-jasmine-reporter.AftLog\"},{\"kind\":128,\"name\":\"AftTest\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-jasmine-reporter\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-jasmine-reporter.AftTest\"},{\"kind\":1024,\"name\":\"_testcases\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html#_testcases\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-jasmine-reporter.AftTest\"},{\"kind\":1024,\"name\":\"_defects\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html#_defects\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-jasmine-reporter.AftTest\"},{\"kind\":262144,\"name\":\"testcases\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html#testcases\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-jasmine-reporter.AftTest\"},{\"kind\":262144,\"name\":\"defects\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html#defects\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-jasmine-reporter.AftTest\"},{\"kind\":2048,\"name\":\"pass\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html#pass\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-jasmine-reporter.AftTest\"},{\"kind\":2048,\"name\":\"fail\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html#fail\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-jasmine-reporter.AftTest\"},{\"kind\":2048,\"name\":\"pending\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html#pending\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-jasmine-reporter.AftTest\"},{\"kind\":2048,\"name\":\"shouldRun\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html#shouldRun\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-jasmine-reporter.AftTest\"},{\"kind\":2048,\"name\":\"dispose\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html#dispose\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-jasmine-reporter.AftTest\"},{\"kind\":2048,\"name\":\"_logResult\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html#_logResult\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-jasmine-reporter.AftTest\"},{\"kind\":2048,\"name\":\"_logMessage\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html#_logMessage\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-jasmine-reporter.AftTest\"},{\"kind\":2048,\"name\":\"_generateTestResults\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html#_generateTestResults\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-jasmine-reporter.AftTest\"},{\"kind\":2048,\"name\":\"_generateTestResult\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html#_generateTestResult\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-jasmine-reporter.AftTest\"},{\"kind\":1024,\"name\":\"test\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html#test\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-jasmine-reporter.AftTest\"},{\"kind\":262144,\"name\":\"fullName\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html#fullName\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-jasmine-reporter.AftTest\"},{\"kind\":262144,\"name\":\"logMgr\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html#logMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-jasmine-reporter.AftTest\"},{\"kind\":4194304,\"name\":\"KinesisLoggingPluginOptions\",\"url\":\"types/aft_logging_awskinesis.KinesisLoggingPluginOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-logging-awskinesis\"},{\"kind\":128,\"name\":\"KinesisLoggingPlugin\",\"url\":\"classes/aft_logging_awskinesis.KinesisLoggingPlugin.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-logging-awskinesis\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_logging_awskinesis.KinesisLoggingPlugin.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-logging-awskinesis.KinesisLoggingPlugin\"},{\"kind\":1024,\"name\":\"_logs\",\"url\":\"classes/aft_logging_awskinesis.KinesisLoggingPlugin.html#_logs\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-logging-awskinesis.KinesisLoggingPlugin\"},{\"kind\":1024,\"name\":\"_buildInfoMgr\",\"url\":\"classes/aft_logging_awskinesis.KinesisLoggingPlugin.html#_buildInfoMgr\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-logging-awskinesis.KinesisLoggingPlugin\"},{\"kind\":1024,\"name\":\"_client\",\"url\":\"classes/aft_logging_awskinesis.KinesisLoggingPlugin.html#_client\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-logging-awskinesis.KinesisLoggingPlugin\"},{\"kind\":2048,\"name\":\"client\",\"url\":\"classes/aft_logging_awskinesis.KinesisLoggingPlugin.html#client\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-logging-awskinesis.KinesisLoggingPlugin\"},{\"kind\":262144,\"name\":\"accessKeyId\",\"url\":\"classes/aft_logging_awskinesis.KinesisLoggingPlugin.html#accessKeyId\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-logging-awskinesis.KinesisLoggingPlugin\"},{\"kind\":262144,\"name\":\"secretAccessKey\",\"url\":\"classes/aft_logging_awskinesis.KinesisLoggingPlugin.html#secretAccessKey\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-logging-awskinesis.KinesisLoggingPlugin\"},{\"kind\":262144,\"name\":\"sessionToken\",\"url\":\"classes/aft_logging_awskinesis.KinesisLoggingPlugin.html#sessionToken\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-logging-awskinesis.KinesisLoggingPlugin\"},{\"kind\":262144,\"name\":\"region\",\"url\":\"classes/aft_logging_awskinesis.KinesisLoggingPlugin.html#region\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-logging-awskinesis.KinesisLoggingPlugin\"},{\"kind\":262144,\"name\":\"deliveryStream\",\"url\":\"classes/aft_logging_awskinesis.KinesisLoggingPlugin.html#deliveryStream\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-logging-awskinesis.KinesisLoggingPlugin\"},{\"kind\":262144,\"name\":\"batch\",\"url\":\"classes/aft_logging_awskinesis.KinesisLoggingPlugin.html#batch\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-logging-awskinesis.KinesisLoggingPlugin\"},{\"kind\":262144,\"name\":\"batchSize\",\"url\":\"classes/aft_logging_awskinesis.KinesisLoggingPlugin.html#batchSize\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-logging-awskinesis.KinesisLoggingPlugin\"},{\"kind\":2048,\"name\":\"credentials\",\"url\":\"classes/aft_logging_awskinesis.KinesisLoggingPlugin.html#credentials\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-logging-awskinesis.KinesisLoggingPlugin\"},{\"kind\":2048,\"name\":\"logs\",\"url\":\"classes/aft_logging_awskinesis.KinesisLoggingPlugin.html#logs\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-logging-awskinesis.KinesisLoggingPlugin\"},{\"kind\":2048,\"name\":\"log\",\"url\":\"classes/aft_logging_awskinesis.KinesisLoggingPlugin.html#log\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-logging-awskinesis.KinesisLoggingPlugin\"},{\"kind\":2048,\"name\":\"logResult\",\"url\":\"classes/aft_logging_awskinesis.KinesisLoggingPlugin.html#logResult\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-logging-awskinesis.KinesisLoggingPlugin\"},{\"kind\":2048,\"name\":\"dispose\",\"url\":\"classes/aft_logging_awskinesis.KinesisLoggingPlugin.html#dispose\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-logging-awskinesis.KinesisLoggingPlugin\"},{\"kind\":2048,\"name\":\"_createKinesisLogRecord\",\"url\":\"classes/aft_logging_awskinesis.KinesisLoggingPlugin.html#_createKinesisLogRecord\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-logging-awskinesis.KinesisLoggingPlugin\"},{\"kind\":2048,\"name\":\"_checkAndSendLogs\",\"url\":\"classes/aft_logging_awskinesis.KinesisLoggingPlugin.html#_checkAndSendLogs\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-logging-awskinesis.KinesisLoggingPlugin\"},{\"kind\":2048,\"name\":\"_sendBatch\",\"url\":\"classes/aft_logging_awskinesis.KinesisLoggingPlugin.html#_sendBatch\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-logging-awskinesis.KinesisLoggingPlugin\"},{\"kind\":2048,\"name\":\"_send\",\"url\":\"classes/aft_logging_awskinesis.KinesisLoggingPlugin.html#_send\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-logging-awskinesis.KinesisLoggingPlugin\"},{\"kind\":262144,\"name\":\"level\",\"url\":\"classes/aft_logging_awskinesis.KinesisLoggingPlugin.html#level\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-logging-awskinesis.KinesisLoggingPlugin\"},{\"kind\":2048,\"name\":\"option\",\"url\":\"classes/aft_logging_awskinesis.KinesisLoggingPlugin.html#option\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-logging-awskinesis.KinesisLoggingPlugin\"},{\"kind\":262144,\"name\":\"enabled\",\"url\":\"classes/aft_logging_awskinesis.KinesisLoggingPlugin.html#enabled\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-logging-awskinesis.KinesisLoggingPlugin\"},{\"kind\":4194304,\"name\":\"FilesystemLoggingPluginOptions\",\"url\":\"types/aft_logging_filesystem.FilesystemLoggingPluginOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-logging-filesystem\"},{\"kind\":128,\"name\":\"FilesystemLoggingPlugin\",\"url\":\"classes/aft_logging_filesystem.FilesystemLoggingPlugin.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-logging-filesystem\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_logging_filesystem.FilesystemLoggingPlugin.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-logging-filesystem.FilesystemLoggingPlugin\"},{\"kind\":1024,\"name\":\"_outputPath\",\"url\":\"classes/aft_logging_filesystem.FilesystemLoggingPlugin.html#_outputPath\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-logging-filesystem.FilesystemLoggingPlugin\"},{\"kind\":1024,\"name\":\"_includeResults\",\"url\":\"classes/aft_logging_filesystem.FilesystemLoggingPlugin.html#_includeResults\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-logging-filesystem.FilesystemLoggingPlugin\"},{\"kind\":1024,\"name\":\"_dateFormat\",\"url\":\"classes/aft_logging_filesystem.FilesystemLoggingPlugin.html#_dateFormat\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-logging-filesystem.FilesystemLoggingPlugin\"},{\"kind\":262144,\"name\":\"outputPath\",\"url\":\"classes/aft_logging_filesystem.FilesystemLoggingPlugin.html#outputPath\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-logging-filesystem.FilesystemLoggingPlugin\"},{\"kind\":262144,\"name\":\"includeResults\",\"url\":\"classes/aft_logging_filesystem.FilesystemLoggingPlugin.html#includeResults\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-logging-filesystem.FilesystemLoggingPlugin\"},{\"kind\":262144,\"name\":\"dateFormat\",\"url\":\"classes/aft_logging_filesystem.FilesystemLoggingPlugin.html#dateFormat\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-logging-filesystem.FilesystemLoggingPlugin\"},{\"kind\":2048,\"name\":\"log\",\"url\":\"classes/aft_logging_filesystem.FilesystemLoggingPlugin.html#log\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-logging-filesystem.FilesystemLoggingPlugin\"},{\"kind\":2048,\"name\":\"logResult\",\"url\":\"classes/aft_logging_filesystem.FilesystemLoggingPlugin.html#logResult\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-logging-filesystem.FilesystemLoggingPlugin\"},{\"kind\":2048,\"name\":\"dispose\",\"url\":\"classes/aft_logging_filesystem.FilesystemLoggingPlugin.html#dispose\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-logging-filesystem.FilesystemLoggingPlugin\"},{\"kind\":2048,\"name\":\"_appendToFile\",\"url\":\"classes/aft_logging_filesystem.FilesystemLoggingPlugin.html#_appendToFile\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-logging-filesystem.FilesystemLoggingPlugin\"},{\"kind\":2048,\"name\":\"_format\",\"url\":\"classes/aft_logging_filesystem.FilesystemLoggingPlugin.html#_format\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-logging-filesystem.FilesystemLoggingPlugin\"},{\"kind\":262144,\"name\":\"level\",\"url\":\"classes/aft_logging_filesystem.FilesystemLoggingPlugin.html#level\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-logging-filesystem.FilesystemLoggingPlugin\"},{\"kind\":2048,\"name\":\"option\",\"url\":\"classes/aft_logging_filesystem.FilesystemLoggingPlugin.html#option\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-logging-filesystem.FilesystemLoggingPlugin\"},{\"kind\":262144,\"name\":\"enabled\",\"url\":\"classes/aft_logging_filesystem.FilesystemLoggingPlugin.html#enabled\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-logging-filesystem.FilesystemLoggingPlugin\"},{\"kind\":4194304,\"name\":\"HtmlLoggingPluginOptions\",\"url\":\"types/aft_logging_html.HtmlLoggingPluginOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-logging-html\"},{\"kind\":128,\"name\":\"HtmlLoggingPlugin\",\"url\":\"classes/aft_logging_html.HtmlLoggingPlugin.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-logging-html\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_logging_html.HtmlLoggingPlugin.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-logging-html.HtmlLoggingPlugin\"},{\"kind\":1024,\"name\":\"_results\",\"url\":\"classes/aft_logging_html.HtmlLoggingPlugin.html#_results\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-logging-html.HtmlLoggingPlugin\"},{\"kind\":1024,\"name\":\"_logs\",\"url\":\"classes/aft_logging_html.HtmlLoggingPlugin.html#_logs\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-logging-html.HtmlLoggingPlugin\"},{\"kind\":262144,\"name\":\"fileName\",\"url\":\"classes/aft_logging_html.HtmlLoggingPlugin.html#fileName\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-logging-html.HtmlLoggingPlugin\"},{\"kind\":262144,\"name\":\"outputDir\",\"url\":\"classes/aft_logging_html.HtmlLoggingPlugin.html#outputDir\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-logging-html.HtmlLoggingPlugin\"},{\"kind\":262144,\"name\":\"fullPathAndFile\",\"url\":\"classes/aft_logging_html.HtmlLoggingPlugin.html#fullPathAndFile\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-logging-html.HtmlLoggingPlugin\"},{\"kind\":262144,\"name\":\"maxLogLines\",\"url\":\"classes/aft_logging_html.HtmlLoggingPlugin.html#maxLogLines\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-logging-html.HtmlLoggingPlugin\"},{\"kind\":2048,\"name\":\"logs\",\"url\":\"classes/aft_logging_html.HtmlLoggingPlugin.html#logs\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-logging-html.HtmlLoggingPlugin\"},{\"kind\":2048,\"name\":\"testResults\",\"url\":\"classes/aft_logging_html.HtmlLoggingPlugin.html#testResults\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-logging-html.HtmlLoggingPlugin\"},{\"kind\":2048,\"name\":\"log\",\"url\":\"classes/aft_logging_html.HtmlLoggingPlugin.html#log\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-logging-html.HtmlLoggingPlugin\"},{\"kind\":2048,\"name\":\"logResult\",\"url\":\"classes/aft_logging_html.HtmlLoggingPlugin.html#logResult\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-logging-html.HtmlLoggingPlugin\"},{\"kind\":2048,\"name\":\"dispose\",\"url\":\"classes/aft_logging_html.HtmlLoggingPlugin.html#dispose\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-logging-html.HtmlLoggingPlugin\"},{\"kind\":2048,\"name\":\"_regenerateHtmlFile\",\"url\":\"classes/aft_logging_html.HtmlLoggingPlugin.html#_regenerateHtmlFile\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-logging-html.HtmlLoggingPlugin\"},{\"kind\":262144,\"name\":\"level\",\"url\":\"classes/aft_logging_html.HtmlLoggingPlugin.html#level\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-logging-html.HtmlLoggingPlugin\"},{\"kind\":2048,\"name\":\"option\",\"url\":\"classes/aft_logging_html.HtmlLoggingPlugin.html#option\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-logging-html.HtmlLoggingPlugin\"},{\"kind\":262144,\"name\":\"enabled\",\"url\":\"classes/aft_logging_html.HtmlLoggingPlugin.html#enabled\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-logging-html.HtmlLoggingPlugin\"},{\"kind\":128,\"name\":\"AftLog\",\"url\":\"classes/aft_mocha_reporter.AftLog.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-mocha-reporter\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_mocha_reporter.AftLog.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-mocha-reporter.AftLog\"},{\"kind\":1024,\"name\":\"_logMgr\",\"url\":\"classes/aft_mocha_reporter.AftLog.html#_logMgr\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-mocha-reporter.AftLog\"},{\"kind\":1024,\"name\":\"test\",\"url\":\"classes/aft_mocha_reporter.AftLog.html#test\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-mocha-reporter.AftLog\"},{\"kind\":262144,\"name\":\"fullTitle\",\"url\":\"classes/aft_mocha_reporter.AftLog.html#fullTitle\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-mocha-reporter.AftLog\"},{\"kind\":262144,\"name\":\"logMgr\",\"url\":\"classes/aft_mocha_reporter.AftLog.html#logMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-mocha-reporter.AftLog\"},{\"kind\":2048,\"name\":\"dispose\",\"url\":\"classes/aft_mocha_reporter.AftLog.html#dispose\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-mocha-reporter.AftLog\"},{\"kind\":128,\"name\":\"AftTest\",\"url\":\"classes/aft_mocha_reporter.AftTest.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-mocha-reporter\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_mocha_reporter.AftTest.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-mocha-reporter.AftTest\"},{\"kind\":1024,\"name\":\"_testcases\",\"url\":\"classes/aft_mocha_reporter.AftTest.html#_testcases\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-mocha-reporter.AftTest\"},{\"kind\":1024,\"name\":\"_defects\",\"url\":\"classes/aft_mocha_reporter.AftTest.html#_defects\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-mocha-reporter.AftTest\"},{\"kind\":262144,\"name\":\"testcases\",\"url\":\"classes/aft_mocha_reporter.AftTest.html#testcases\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-mocha-reporter.AftTest\"},{\"kind\":262144,\"name\":\"defects\",\"url\":\"classes/aft_mocha_reporter.AftTest.html#defects\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-mocha-reporter.AftTest\"},{\"kind\":2048,\"name\":\"pass\",\"url\":\"classes/aft_mocha_reporter.AftTest.html#pass\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-mocha-reporter.AftTest\"},{\"kind\":2048,\"name\":\"fail\",\"url\":\"classes/aft_mocha_reporter.AftTest.html#fail\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-mocha-reporter.AftTest\"},{\"kind\":2048,\"name\":\"pending\",\"url\":\"classes/aft_mocha_reporter.AftTest.html#pending\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-mocha-reporter.AftTest\"},{\"kind\":2048,\"name\":\"shouldRun\",\"url\":\"classes/aft_mocha_reporter.AftTest.html#shouldRun\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-mocha-reporter.AftTest\"},{\"kind\":2048,\"name\":\"_logResult\",\"url\":\"classes/aft_mocha_reporter.AftTest.html#_logResult\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-mocha-reporter.AftTest\"},{\"kind\":2048,\"name\":\"_logMessage\",\"url\":\"classes/aft_mocha_reporter.AftTest.html#_logMessage\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-mocha-reporter.AftTest\"},{\"kind\":2048,\"name\":\"_generateTestResults\",\"url\":\"classes/aft_mocha_reporter.AftTest.html#_generateTestResults\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-mocha-reporter.AftTest\"},{\"kind\":2048,\"name\":\"_generateTestResult\",\"url\":\"classes/aft_mocha_reporter.AftTest.html#_generateTestResult\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-mocha-reporter.AftTest\"},{\"kind\":1024,\"name\":\"test\",\"url\":\"classes/aft_mocha_reporter.AftTest.html#test\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-mocha-reporter.AftTest\"},{\"kind\":262144,\"name\":\"fullTitle\",\"url\":\"classes/aft_mocha_reporter.AftTest.html#fullTitle\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-mocha-reporter.AftTest\"},{\"kind\":262144,\"name\":\"logMgr\",\"url\":\"classes/aft_mocha_reporter.AftTest.html#logMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-mocha-reporter.AftTest\"},{\"kind\":2048,\"name\":\"dispose\",\"url\":\"classes/aft_mocha_reporter.AftTest.html#dispose\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-mocha-reporter.AftTest\"},{\"kind\":128,\"name\":\"AftMochaReporter\",\"url\":\"classes/aft_mocha_reporter.AftMochaReporter.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-mocha-reporter\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_mocha_reporter.AftMochaReporter.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-mocha-reporter.AftMochaReporter\"},{\"kind\":2048,\"name\":\"addListeners\",\"url\":\"classes/aft_mocha_reporter.AftMochaReporter.html#addListeners\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-mocha-reporter.AftMochaReporter\"},{\"kind\":4194304,\"name\":\"TestRailConfigOptions\",\"url\":\"types/aft_testrail.TestRailConfigOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-testrail\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_testrail.TestRailConfigOptions.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-testrail.TestRailConfigOptions\"},{\"kind\":1024,\"name\":\"url\",\"url\":\"types/aft_testrail.TestRailConfigOptions.html#__type.url\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-testrail.TestRailConfigOptions.__type\"},{\"kind\":1024,\"name\":\"user\",\"url\":\"types/aft_testrail.TestRailConfigOptions.html#__type.user\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-testrail.TestRailConfigOptions.__type\"},{\"kind\":1024,\"name\":\"accesskey\",\"url\":\"types/aft_testrail.TestRailConfigOptions.html#__type.accesskey\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-testrail.TestRailConfigOptions.__type\"},{\"kind\":1024,\"name\":\"projectid\",\"url\":\"types/aft_testrail.TestRailConfigOptions.html#__type.projectid\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-testrail.TestRailConfigOptions.__type\"},{\"kind\":1024,\"name\":\"suiteids\",\"url\":\"types/aft_testrail.TestRailConfigOptions.html#__type.suiteids\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-testrail.TestRailConfigOptions.__type\"},{\"kind\":1024,\"name\":\"planid\",\"url\":\"types/aft_testrail.TestRailConfigOptions.html#__type.planid\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-testrail.TestRailConfigOptions.__type\"},{\"kind\":1024,\"name\":\"cacheDurationMs\",\"url\":\"types/aft_testrail.TestRailConfigOptions.html#__type.cacheDurationMs\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-testrail.TestRailConfigOptions.__type\"},{\"kind\":128,\"name\":\"TestRailConfig\",\"url\":\"classes/aft_testrail.TestRailConfig.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-testrail\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_testrail.TestRailConfig.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailConfig\"},{\"kind\":1024,\"name\":\"_url\",\"url\":\"classes/aft_testrail.TestRailConfig.html#_url\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-testrail.TestRailConfig\"},{\"kind\":1024,\"name\":\"_user\",\"url\":\"classes/aft_testrail.TestRailConfig.html#_user\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-testrail.TestRailConfig\"},{\"kind\":1024,\"name\":\"_accessKey\",\"url\":\"classes/aft_testrail.TestRailConfig.html#_accessKey\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-testrail.TestRailConfig\"},{\"kind\":1024,\"name\":\"_projectId\",\"url\":\"classes/aft_testrail.TestRailConfig.html#_projectId\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-testrail.TestRailConfig\"},{\"kind\":1024,\"name\":\"_suiteIds\",\"url\":\"classes/aft_testrail.TestRailConfig.html#_suiteIds\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-testrail.TestRailConfig\"},{\"kind\":1024,\"name\":\"_planId\",\"url\":\"classes/aft_testrail.TestRailConfig.html#_planId\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-testrail.TestRailConfig\"},{\"kind\":1024,\"name\":\"_cacheDuration\",\"url\":\"classes/aft_testrail.TestRailConfig.html#_cacheDuration\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-testrail.TestRailConfig\"},{\"kind\":1024,\"name\":\"_shared\",\"url\":\"classes/aft_testrail.TestRailConfig.html#_shared\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-testrail.TestRailConfig\"},{\"kind\":1024,\"name\":\"_config\",\"url\":\"classes/aft_testrail.TestRailConfig.html#_config\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-testrail.TestRailConfig\"},{\"kind\":2048,\"name\":\"config\",\"url\":\"classes/aft_testrail.TestRailConfig.html#config\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailConfig\"},{\"kind\":2048,\"name\":\"url\",\"url\":\"classes/aft_testrail.TestRailConfig.html#url\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailConfig\"},{\"kind\":2048,\"name\":\"user\",\"url\":\"classes/aft_testrail.TestRailConfig.html#user\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailConfig\"},{\"kind\":2048,\"name\":\"accessKey\",\"url\":\"classes/aft_testrail.TestRailConfig.html#accessKey\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailConfig\"},{\"kind\":2048,\"name\":\"projectId\",\"url\":\"classes/aft_testrail.TestRailConfig.html#projectId\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailConfig\"},{\"kind\":2048,\"name\":\"suiteIds\",\"url\":\"classes/aft_testrail.TestRailConfig.html#suiteIds\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailConfig\"},{\"kind\":2048,\"name\":\"planId\",\"url\":\"classes/aft_testrail.TestRailConfig.html#planId\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailConfig\"},{\"kind\":2048,\"name\":\"setPlanId\",\"url\":\"classes/aft_testrail.TestRailConfig.html#setPlanId\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailConfig\"},{\"kind\":2048,\"name\":\"cacheDuration\",\"url\":\"classes/aft_testrail.TestRailConfig.html#cacheDuration\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailConfig\"},{\"kind\":32,\"name\":\"trconfig\",\"url\":\"variables/aft_testrail.trconfig.html\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"aft-testrail\"},{\"kind\":4194304,\"name\":\"TestRailTestCasePluginOptions\",\"url\":\"types/aft_testrail.TestRailTestCasePluginOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-testrail\"},{\"kind\":128,\"name\":\"TestRailTestCasePlugin\",\"url\":\"classes/aft_testrail.TestRailTestCasePlugin.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-testrail\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_testrail.TestRailTestCasePlugin.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-testrail.TestRailTestCasePlugin\"},{\"kind\":1024,\"name\":\"_trConfig\",\"url\":\"classes/aft_testrail.TestRailTestCasePlugin.html#_trConfig\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-testrail.TestRailTestCasePlugin\"},{\"kind\":1024,\"name\":\"_api\",\"url\":\"classes/aft_testrail.TestRailTestCasePlugin.html#_api\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-testrail.TestRailTestCasePlugin\"},{\"kind\":1024,\"name\":\"_logMgr\",\"url\":\"classes/aft_testrail.TestRailTestCasePlugin.html#_logMgr\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-testrail.TestRailTestCasePlugin\"},{\"kind\":262144,\"name\":\"config\",\"url\":\"classes/aft_testrail.TestRailTestCasePlugin.html#config\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailTestCasePlugin\"},{\"kind\":262144,\"name\":\"api\",\"url\":\"classes/aft_testrail.TestRailTestCasePlugin.html#api\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailTestCasePlugin\"},{\"kind\":262144,\"name\":\"logMgr\",\"url\":\"classes/aft_testrail.TestRailTestCasePlugin.html#logMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailTestCasePlugin\"},{\"kind\":2048,\"name\":\"getTestCase\",\"url\":\"classes/aft_testrail.TestRailTestCasePlugin.html#getTestCase\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailTestCasePlugin\"},{\"kind\":2048,\"name\":\"findTestCases\",\"url\":\"classes/aft_testrail.TestRailTestCasePlugin.html#findTestCases\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailTestCasePlugin\"},{\"kind\":2048,\"name\":\"shouldRun\",\"url\":\"classes/aft_testrail.TestRailTestCasePlugin.html#shouldRun\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailTestCasePlugin\"},{\"kind\":2048,\"name\":\"dispose\",\"url\":\"classes/aft_testrail.TestRailTestCasePlugin.html#dispose\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailTestCasePlugin\"},{\"kind\":2048,\"name\":\"_findTestsByField\",\"url\":\"classes/aft_testrail.TestRailTestCasePlugin.html#_findTestsByField\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-testrail.TestRailTestCasePlugin\"},{\"kind\":2048,\"name\":\"_createTestCaseFromTest\",\"url\":\"classes/aft_testrail.TestRailTestCasePlugin.html#_createTestCaseFromTest\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-testrail.TestRailTestCasePlugin\"},{\"kind\":2048,\"name\":\"_createTestCaseFromCase\",\"url\":\"classes/aft_testrail.TestRailTestCasePlugin.html#_createTestCaseFromCase\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-testrail.TestRailTestCasePlugin\"},{\"kind\":2048,\"name\":\"option\",\"url\":\"classes/aft_testrail.TestRailTestCasePlugin.html#option\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-testrail.TestRailTestCasePlugin\"},{\"kind\":262144,\"name\":\"enabled\",\"url\":\"classes/aft_testrail.TestRailTestCasePlugin.html#enabled\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-testrail.TestRailTestCasePlugin\"},{\"kind\":4194304,\"name\":\"TestRailLoggingPluginOptions\",\"url\":\"types/aft_testrail.TestRailLoggingPluginOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-testrail\"},{\"kind\":128,\"name\":\"TestRailLoggingPlugin\",\"url\":\"classes/aft_testrail.TestRailLoggingPlugin.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-testrail\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_testrail.TestRailLoggingPlugin.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailLoggingPlugin\"},{\"kind\":1024,\"name\":\"_logs\",\"url\":\"classes/aft_testrail.TestRailLoggingPlugin.html#_logs\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-testrail.TestRailLoggingPlugin\"},{\"kind\":1024,\"name\":\"_trConfig\",\"url\":\"classes/aft_testrail.TestRailLoggingPlugin.html#_trConfig\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-testrail.TestRailLoggingPlugin\"},{\"kind\":1024,\"name\":\"_api\",\"url\":\"classes/aft_testrail.TestRailLoggingPlugin.html#_api\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-testrail.TestRailLoggingPlugin\"},{\"kind\":262144,\"name\":\"config\",\"url\":\"classes/aft_testrail.TestRailLoggingPlugin.html#config\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailLoggingPlugin\"},{\"kind\":262144,\"name\":\"api\",\"url\":\"classes/aft_testrail.TestRailLoggingPlugin.html#api\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailLoggingPlugin\"},{\"kind\":262144,\"name\":\"maxLogCharacters\",\"url\":\"classes/aft_testrail.TestRailLoggingPlugin.html#maxLogCharacters\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailLoggingPlugin\"},{\"kind\":2048,\"name\":\"logs\",\"url\":\"classes/aft_testrail.TestRailLoggingPlugin.html#logs\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailLoggingPlugin\"},{\"kind\":2048,\"name\":\"log\",\"url\":\"classes/aft_testrail.TestRailLoggingPlugin.html#log\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailLoggingPlugin\"},{\"kind\":2048,\"name\":\"logResult\",\"url\":\"classes/aft_testrail.TestRailLoggingPlugin.html#logResult\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailLoggingPlugin\"},{\"kind\":2048,\"name\":\"dispose\",\"url\":\"classes/aft_testrail.TestRailLoggingPlugin.html#dispose\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailLoggingPlugin\"},{\"kind\":2048,\"name\":\"_getTestRailResultForExternalResult\",\"url\":\"classes/aft_testrail.TestRailLoggingPlugin.html#_getTestRailResultForExternalResult\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-testrail.TestRailLoggingPlugin\"},{\"kind\":2048,\"name\":\"_createTestPlanIfNone\",\"url\":\"classes/aft_testrail.TestRailLoggingPlugin.html#_createTestPlanIfNone\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-testrail.TestRailLoggingPlugin\"},{\"kind\":262144,\"name\":\"level\",\"url\":\"classes/aft_testrail.TestRailLoggingPlugin.html#level\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-testrail.TestRailLoggingPlugin\"},{\"kind\":2048,\"name\":\"option\",\"url\":\"classes/aft_testrail.TestRailLoggingPlugin.html#option\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-testrail.TestRailLoggingPlugin\"},{\"kind\":262144,\"name\":\"enabled\",\"url\":\"classes/aft_testrail.TestRailLoggingPlugin.html#enabled\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-testrail.TestRailLoggingPlugin\"},{\"kind\":4194304,\"name\":\"UiTestPlatformOptions\",\"url\":\"types/aft_ui.UiTestPlatformOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-ui\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_ui.UiTestPlatformOptions.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-ui.UiTestPlatformOptions\"},{\"kind\":1024,\"name\":\"os\",\"url\":\"types/aft_ui.UiTestPlatformOptions.html#__type.os\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui.UiTestPlatformOptions.__type\"},{\"kind\":1024,\"name\":\"osVersion\",\"url\":\"types/aft_ui.UiTestPlatformOptions.html#__type.osVersion\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui.UiTestPlatformOptions.__type\"},{\"kind\":1024,\"name\":\"browser\",\"url\":\"types/aft_ui.UiTestPlatformOptions.html#__type.browser\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui.UiTestPlatformOptions.__type\"},{\"kind\":1024,\"name\":\"browserVersion\",\"url\":\"types/aft_ui.UiTestPlatformOptions.html#__type.browserVersion\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui.UiTestPlatformOptions.__type\"},{\"kind\":1024,\"name\":\"deviceName\",\"url\":\"types/aft_ui.UiTestPlatformOptions.html#__type.deviceName\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui.UiTestPlatformOptions.__type\"},{\"kind\":128,\"name\":\"UiPlatform\",\"url\":\"classes/aft_ui.UiPlatform.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-ui\"},{\"kind\":1024,\"name\":\"ANY\",\"url\":\"classes/aft_ui.UiPlatform.html#ANY\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-ui.UiPlatform\"},{\"kind\":2048,\"name\":\"parse\",\"url\":\"classes/aft_ui.UiPlatform.html#parse\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui.UiPlatform\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_ui.UiPlatform.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-ui.UiPlatform\"},{\"kind\":1024,\"name\":\"os\",\"url\":\"classes/aft_ui.UiPlatform.html#os\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-ui.UiPlatform\"},{\"kind\":1024,\"name\":\"osVersion\",\"url\":\"classes/aft_ui.UiPlatform.html#osVersion\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-ui.UiPlatform\"},{\"kind\":1024,\"name\":\"browser\",\"url\":\"classes/aft_ui.UiPlatform.html#browser\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-ui.UiPlatform\"},{\"kind\":1024,\"name\":\"browserVersion\",\"url\":\"classes/aft_ui.UiPlatform.html#browserVersion\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-ui.UiPlatform\"},{\"kind\":1024,\"name\":\"deviceName\",\"url\":\"classes/aft_ui.UiPlatform.html#deviceName\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-ui.UiPlatform\"},{\"kind\":2048,\"name\":\"toString\",\"url\":\"classes/aft_ui.UiPlatform.html#toString\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui.UiPlatform\"},{\"kind\":4194304,\"name\":\"UiFacetOptions\",\"url\":\"types/aft_ui.UiFacetOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-ui\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_ui.UiFacetOptions.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-ui.UiFacetOptions\"},{\"kind\":1024,\"name\":\"index\",\"url\":\"types/aft_ui.UiFacetOptions.html#__type.index\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui.UiFacetOptions.__type\"},{\"kind\":1024,\"name\":\"locator\",\"url\":\"types/aft_ui.UiFacetOptions.html#__type.locator\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui.UiFacetOptions.__type\"},{\"kind\":1024,\"name\":\"parent\",\"url\":\"types/aft_ui.UiFacetOptions.html#__type.parent\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui.UiFacetOptions.__type\"},{\"kind\":1024,\"name\":\"session\",\"url\":\"types/aft_ui.UiFacetOptions.html#__type.session\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui.UiFacetOptions.__type\"},{\"kind\":1024,\"name\":\"logMgr\",\"url\":\"types/aft_ui.UiFacetOptions.html#__type.logMgr\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui.UiFacetOptions.__type\"},{\"kind\":1024,\"name\":\"maxWaitMs\",\"url\":\"types/aft_ui.UiFacetOptions.html#__type.maxWaitMs\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui.UiFacetOptions.__type\"},{\"kind\":1024,\"name\":\"retryDelayMs\",\"url\":\"types/aft_ui.UiFacetOptions.html#__type.retryDelayMs\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui.UiFacetOptions.__type\"},{\"kind\":1024,\"name\":\"retryDelayBackOff\",\"url\":\"types/aft_ui.UiFacetOptions.html#__type.retryDelayBackOff\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui.UiFacetOptions.__type\"},{\"kind\":128,\"name\":\"UiFacet\",\"url\":\"classes/aft_ui.UiFacet.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-ui\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_ui.UiFacet.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-ui.UiFacet\"},{\"kind\":1024,\"name\":\"_logMgr\",\"url\":\"classes/aft_ui.UiFacet.html#_logMgr\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui.UiFacet\"},{\"kind\":1024,\"name\":\"_opts\",\"url\":\"classes/aft_ui.UiFacet.html#_opts\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui.UiFacet\"},{\"kind\":2048,\"name\":\"option\",\"url\":\"classes/aft_ui.UiFacet.html#option\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui.UiFacet\"},{\"kind\":262144,\"name\":\"logMgr\",\"url\":\"classes/aft_ui.UiFacet.html#logMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui.UiFacet\"},{\"kind\":262144,\"name\":\"index\",\"url\":\"classes/aft_ui.UiFacet.html#index\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui.UiFacet\"},{\"kind\":262144,\"name\":\"maxWaitMs\",\"url\":\"classes/aft_ui.UiFacet.html#maxWaitMs\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui.UiFacet\"},{\"kind\":262144,\"name\":\"retryDelayMs\",\"url\":\"classes/aft_ui.UiFacet.html#retryDelayMs\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui.UiFacet\"},{\"kind\":262144,\"name\":\"retryDelayBackOff\",\"url\":\"classes/aft_ui.UiFacet.html#retryDelayBackOff\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui.UiFacet\"},{\"kind\":262144,\"name\":\"locator\",\"url\":\"classes/aft_ui.UiFacet.html#locator\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui.UiFacet\"},{\"kind\":262144,\"name\":\"session\",\"url\":\"classes/aft_ui.UiFacet.html#session\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui.UiFacet\"},{\"kind\":262144,\"name\":\"parent\",\"url\":\"classes/aft_ui.UiFacet.html#parent\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui.UiFacet\"},{\"kind\":2048,\"name\":\"getElements\",\"url\":\"classes/aft_ui.UiFacet.html#getElements\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui.UiFacet\"},{\"kind\":2048,\"name\":\"getElement\",\"url\":\"classes/aft_ui.UiFacet.html#getElement\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui.UiFacet\"},{\"kind\":2048,\"name\":\"getFacet\",\"url\":\"classes/aft_ui.UiFacet.html#getFacet\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui.UiFacet\"},{\"kind\":2048,\"name\":\"getRoot\",\"url\":\"classes/aft_ui.UiFacet.html#getRoot\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui.UiFacet\"},{\"kind\":4194304,\"name\":\"UiElementOptions\",\"url\":\"types/aft_ui.UiElementOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-ui\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_ui.UiElementOptions.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-ui.UiElementOptions\"},{\"kind\":1024,\"name\":\"locator\",\"url\":\"types/aft_ui.UiElementOptions.html#__type.locator\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui.UiElementOptions.__type\"},{\"kind\":1024,\"name\":\"maxWaitMs\",\"url\":\"types/aft_ui.UiElementOptions.html#__type.maxWaitMs\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui.UiElementOptions.__type\"},{\"kind\":1024,\"name\":\"retryDelayMs\",\"url\":\"types/aft_ui.UiElementOptions.html#__type.retryDelayMs\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui.UiElementOptions.__type\"},{\"kind\":1024,\"name\":\"retryDelayBackOff\",\"url\":\"types/aft_ui.UiElementOptions.html#__type.retryDelayBackOff\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui.UiElementOptions.__type\"},{\"kind\":4194304,\"name\":\"UiSessionGeneratorPluginOptions\",\"url\":\"types/aft_ui.UiSessionGeneratorPluginOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-ui\"},{\"kind\":128,\"name\":\"UiSessionGeneratorPlugin\",\"url\":\"classes/aft_ui.UiSessionGeneratorPlugin.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-ui\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_ui.UiSessionGeneratorPlugin.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui.UiSessionGeneratorPlugin\"},{\"kind\":1024,\"name\":\"_logMgr\",\"url\":\"classes/aft_ui.UiSessionGeneratorPlugin.html#_logMgr\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui.UiSessionGeneratorPlugin\"},{\"kind\":1024,\"name\":\"_platform\",\"url\":\"classes/aft_ui.UiSessionGeneratorPlugin.html#_platform\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui.UiSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"logMgr\",\"url\":\"classes/aft_ui.UiSessionGeneratorPlugin.html#logMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui.UiSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"uiplatform\",\"url\":\"classes/aft_ui.UiSessionGeneratorPlugin.html#uiplatform\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui.UiSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"newUiSession\",\"url\":\"classes/aft_ui.UiSessionGeneratorPlugin.html#newUiSession\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui.UiSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"option\",\"url\":\"classes/aft_ui.UiSessionGeneratorPlugin.html#option\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui.UiSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"enabled\",\"url\":\"classes/aft_ui.UiSessionGeneratorPlugin.html#enabled\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui.UiSessionGeneratorPlugin\"},{\"kind\":4194304,\"name\":\"UiSessionOptions\",\"url\":\"types/aft_ui.UiSessionOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-ui\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_ui.UiSessionOptions.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-ui.UiSessionOptions\"},{\"kind\":1024,\"name\":\"logMgr\",\"url\":\"types/aft_ui.UiSessionOptions.html#__type.logMgr\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui.UiSessionOptions.__type\"},{\"kind\":1024,\"name\":\"uiplatform\",\"url\":\"types/aft_ui.UiSessionOptions.html#__type.uiplatform\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui.UiSessionOptions.__type\"},{\"kind\":1024,\"name\":\"driver\",\"url\":\"types/aft_ui.UiSessionOptions.html#__type.driver\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui.UiSessionOptions.__type\"},{\"kind\":128,\"name\":\"UiSession\",\"url\":\"classes/aft_ui.UiSession.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-ui\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_ui.UiSession.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-ui.UiSession\"},{\"kind\":1024,\"name\":\"_options\",\"url\":\"classes/aft_ui.UiSession.html#_options\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui.UiSession\"},{\"kind\":1024,\"name\":\"_platform\",\"url\":\"classes/aft_ui.UiSession.html#_platform\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui.UiSession\"},{\"kind\":1024,\"name\":\"_logMgr\",\"url\":\"classes/aft_ui.UiSession.html#_logMgr\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui.UiSession\"},{\"kind\":2048,\"name\":\"option\",\"url\":\"classes/aft_ui.UiSession.html#option\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui.UiSession\"},{\"kind\":1024,\"name\":\"driver\",\"url\":\"classes/aft_ui.UiSession.html#driver\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-ui.UiSession\"},{\"kind\":262144,\"name\":\"platform\",\"url\":\"classes/aft_ui.UiSession.html#platform\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui.UiSession\"},{\"kind\":262144,\"name\":\"logMgr\",\"url\":\"classes/aft_ui.UiSession.html#logMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui.UiSession\"},{\"kind\":2048,\"name\":\"getFacet\",\"url\":\"classes/aft_ui.UiSession.html#getFacet\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui.UiSession\"},{\"kind\":2048,\"name\":\"dispose\",\"url\":\"classes/aft_ui.UiSession.html#dispose\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui.UiSession\"},{\"kind\":4194304,\"name\":\"UiSessionGeneratorManagerOptions\",\"url\":\"types/aft_ui.UiSessionGeneratorManagerOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-ui\"},{\"kind\":128,\"name\":\"UiSessionGeneratorManager\",\"url\":\"classes/aft_ui.UiSessionGeneratorManager.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-ui\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_ui.UiSessionGeneratorManager.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui.UiSessionGeneratorManager\"},{\"kind\":1024,\"name\":\"_uiPlt\",\"url\":\"classes/aft_ui.UiSessionGeneratorManager.html#_uiPlt\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui.UiSessionGeneratorManager\"},{\"kind\":2048,\"name\":\"uiplatform\",\"url\":\"classes/aft_ui.UiSessionGeneratorManager.html#uiplatform\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui.UiSessionGeneratorManager\"},{\"kind\":2048,\"name\":\"pluginConfigs\",\"url\":\"classes/aft_ui.UiSessionGeneratorManager.html#pluginConfigs\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui.UiSessionGeneratorManager\"},{\"kind\":2048,\"name\":\"newUiSession\",\"url\":\"classes/aft_ui.UiSessionGeneratorManager.html#newUiSession\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui.UiSessionGeneratorManager\"},{\"kind\":2048,\"name\":\"config\",\"url\":\"classes/aft_ui.UiSessionGeneratorManager.html#config\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui.UiSessionGeneratorManager\"},{\"kind\":2048,\"name\":\"logMgr\",\"url\":\"classes/aft_ui.UiSessionGeneratorManager.html#logMgr\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui.UiSessionGeneratorManager\"},{\"kind\":2048,\"name\":\"option\",\"url\":\"classes/aft_ui.UiSessionGeneratorManager.html#option\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui.UiSessionGeneratorManager\"},{\"kind\":2048,\"name\":\"plugins\",\"url\":\"classes/aft_ui.UiSessionGeneratorManager.html#plugins\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui.UiSessionGeneratorManager\"},{\"kind\":2048,\"name\":\"first\",\"url\":\"classes/aft_ui.UiSessionGeneratorManager.html#first\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui.UiSessionGeneratorManager\"},{\"kind\":2048,\"name\":\"enabled\",\"url\":\"classes/aft_ui.UiSessionGeneratorManager.html#enabled\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui.UiSessionGeneratorManager\"},{\"kind\":2048,\"name\":\"named\",\"url\":\"classes/aft_ui.UiSessionGeneratorManager.html#named\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui.UiSessionGeneratorManager\"},{\"kind\":2048,\"name\":\"load\",\"url\":\"classes/aft_ui.UiSessionGeneratorManager.html#load\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui.UiSessionGeneratorManager\"},{\"kind\":32,\"name\":\"browserSessionGeneratorMgr\",\"url\":\"variables/aft_ui_browsers.browserSessionGeneratorMgr.html\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"aft-ui-browsers\"},{\"kind\":4194304,\"name\":\"WebElementOptions\",\"url\":\"types/aft_ui_browsers.WebElementOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-ui-browsers\"},{\"kind\":4194304,\"name\":\"BrowserFacetOptions\",\"url\":\"types/aft_ui_browsers.BrowserFacetOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-ui-browsers\"},{\"kind\":128,\"name\":\"BrowserFacet\",\"url\":\"classes/aft_ui_browsers.BrowserFacet.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-ui-browsers\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_ui_browsers.BrowserFacet.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserFacet\"},{\"kind\":262144,\"name\":\"locator\",\"url\":\"classes/aft_ui_browsers.BrowserFacet.html#locator\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserFacet\"},{\"kind\":262144,\"name\":\"session\",\"url\":\"classes/aft_ui_browsers.BrowserFacet.html#session\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserFacet\"},{\"kind\":262144,\"name\":\"parent\",\"url\":\"classes/aft_ui_browsers.BrowserFacet.html#parent\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserFacet\"},{\"kind\":2048,\"name\":\"getElements\",\"url\":\"classes/aft_ui_browsers.BrowserFacet.html#getElements\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserFacet\"},{\"kind\":2048,\"name\":\"getElement\",\"url\":\"classes/aft_ui_browsers.BrowserFacet.html#getElement\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserFacet\"},{\"kind\":2048,\"name\":\"getFacet\",\"url\":\"classes/aft_ui_browsers.BrowserFacet.html#getFacet\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserFacet\"},{\"kind\":2048,\"name\":\"getRoot\",\"url\":\"classes/aft_ui_browsers.BrowserFacet.html#getRoot\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserFacet\"},{\"kind\":2048,\"name\":\"option\",\"url\":\"classes/aft_ui_browsers.BrowserFacet.html#option\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserFacet\"},{\"kind\":262144,\"name\":\"logMgr\",\"url\":\"classes/aft_ui_browsers.BrowserFacet.html#logMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserFacet\"},{\"kind\":262144,\"name\":\"index\",\"url\":\"classes/aft_ui_browsers.BrowserFacet.html#index\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserFacet\"},{\"kind\":262144,\"name\":\"maxWaitMs\",\"url\":\"classes/aft_ui_browsers.BrowserFacet.html#maxWaitMs\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserFacet\"},{\"kind\":262144,\"name\":\"retryDelayMs\",\"url\":\"classes/aft_ui_browsers.BrowserFacet.html#retryDelayMs\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserFacet\"},{\"kind\":262144,\"name\":\"retryDelayBackOff\",\"url\":\"classes/aft_ui_browsers.BrowserFacet.html#retryDelayBackOff\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserFacet\"},{\"kind\":128,\"name\":\"BrowserVerifier\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-ui-browsers\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":1024,\"name\":\"_assertion\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#_assertion\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":1024,\"name\":\"_sessionMgr\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#_sessionMgr\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":1024,\"name\":\"_session\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#_session\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":1024,\"name\":\"_sessionOptions\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#_sessionOptions\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":262144,\"name\":\"sessionGeneratorManager\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#sessionGeneratorManager\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":262144,\"name\":\"session\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#session\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":262144,\"name\":\"sessionOptions\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#sessionOptions\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":2048,\"name\":\"withBrowserSessionOptions\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#withBrowserSessionOptions\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":2048,\"name\":\"withBrowserSessionGeneratorManager\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#withBrowserSessionGeneratorManager\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":2048,\"name\":\"_resolveAssertion\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#_resolveAssertion\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":1024,\"name\":\"_matcher\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#_matcher\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":1024,\"name\":\"_description\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#_description\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":1024,\"name\":\"_startTime\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#_startTime\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":1024,\"name\":\"_innerPromise\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#_innerPromise\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":1024,\"name\":\"_tests\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#_tests\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":1024,\"name\":\"_defects\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#_defects\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":1024,\"name\":\"_logMgr\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#_logMgr\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":1024,\"name\":\"_testMgr\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#_testMgr\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":1024,\"name\":\"_defectMgr\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#_defectMgr\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":1024,\"name\":\"_buildMgr\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#_buildMgr\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":262144,\"name\":\"logMgr\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#logMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":262144,\"name\":\"testMgr\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#testMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":262144,\"name\":\"defectMgr\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#defectMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":262144,\"name\":\"buildMgr\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#buildMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":2048,\"name\":\"then\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#then\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":2048,\"name\":\"_getInnerPromise\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#_getInnerPromise\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":262144,\"name\":\"and\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#and\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":2048,\"name\":\"verify\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#verify\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":2048,\"name\":\"withDescription\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#withDescription\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":2048,\"name\":\"withTestIds\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#withTestIds\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":2048,\"name\":\"withKnownDefectIds\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#withKnownDefectIds\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":2048,\"name\":\"returns\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#returns\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":2048,\"name\":\"withLogManager\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#withLogManager\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":2048,\"name\":\"withTestCaseManager\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#withTestCaseManager\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":2048,\"name\":\"withDefectManager\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#withDefectManager\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":2048,\"name\":\"withBuildInfoManager\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#withBuildInfoManager\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":2048,\"name\":\"_shouldRun_tests\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#_shouldRun_tests\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":2048,\"name\":\"_shouldRun_defects\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#_shouldRun_defects\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":2048,\"name\":\"_logResult\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#_logResult\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":2048,\"name\":\"_logMessage\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#_logMessage\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":2048,\"name\":\"_generateTestResults\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#_generateTestResults\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":2048,\"name\":\"_generateTestResult\",\"url\":\"classes/aft_ui_browsers.BrowserVerifier.html#_generateTestResult\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserVerifier\"},{\"kind\":64,\"name\":\"verifyWithBrowser\",\"url\":\"functions/aft_ui_browsers.verifyWithBrowser.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"aft-ui-browsers\"},{\"kind\":4194304,\"name\":\"BrowserSessionGeneratorPluginOptions\",\"url\":\"types/aft_ui_browsers.BrowserSessionGeneratorPluginOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-ui-browsers\"},{\"kind\":128,\"name\":\"BrowserSessionGeneratorPlugin\",\"url\":\"classes/aft_ui_browsers.BrowserSessionGeneratorPlugin.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-ui-browsers\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_ui_browsers.BrowserSessionGeneratorPlugin.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserSessionGeneratorPlugin\"},{\"kind\":1024,\"name\":\"_url\",\"url\":\"classes/aft_ui_browsers.BrowserSessionGeneratorPlugin.html#_url\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-browsers.BrowserSessionGeneratorPlugin\"},{\"kind\":1024,\"name\":\"_resolution\",\"url\":\"classes/aft_ui_browsers.BrowserSessionGeneratorPlugin.html#_resolution\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-browsers.BrowserSessionGeneratorPlugin\"},{\"kind\":1024,\"name\":\"_caps\",\"url\":\"classes/aft_ui_browsers.BrowserSessionGeneratorPlugin.html#_caps\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-browsers.BrowserSessionGeneratorPlugin\"},{\"kind\":1024,\"name\":\"_timeout\",\"url\":\"classes/aft_ui_browsers.BrowserSessionGeneratorPlugin.html#_timeout\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-browsers.BrowserSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"url\",\"url\":\"classes/aft_ui_browsers.BrowserSessionGeneratorPlugin.html#url\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"resolution\",\"url\":\"classes/aft_ui_browsers.BrowserSessionGeneratorPlugin.html#resolution\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"additionalCapabilities\",\"url\":\"classes/aft_ui_browsers.BrowserSessionGeneratorPlugin.html#additionalCapabilities\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"implicitTimeout\",\"url\":\"classes/aft_ui_browsers.BrowserSessionGeneratorPlugin.html#implicitTimeout\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"generateCapabilities\",\"url\":\"classes/aft_ui_browsers.BrowserSessionGeneratorPlugin.html#generateCapabilities\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"createDriver\",\"url\":\"classes/aft_ui_browsers.BrowserSessionGeneratorPlugin.html#createDriver\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-ui-browsers.BrowserSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"logMgr\",\"url\":\"classes/aft_ui_browsers.BrowserSessionGeneratorPlugin.html#logMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"uiplatform\",\"url\":\"classes/aft_ui_browsers.BrowserSessionGeneratorPlugin.html#uiplatform\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"newUiSession\",\"url\":\"classes/aft_ui_browsers.BrowserSessionGeneratorPlugin.html#newUiSession\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"option\",\"url\":\"classes/aft_ui_browsers.BrowserSessionGeneratorPlugin.html#option\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"enabled\",\"url\":\"classes/aft_ui_browsers.BrowserSessionGeneratorPlugin.html#enabled\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserSessionGeneratorPlugin\"},{\"kind\":4194304,\"name\":\"BrowserSessionOptions\",\"url\":\"types/aft_ui_browsers.BrowserSessionOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-ui-browsers\"},{\"kind\":128,\"name\":\"BrowserSession\",\"url\":\"classes/aft_ui_browsers.BrowserSession.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-ui-browsers\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_ui_browsers.BrowserSession.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserSession\"},{\"kind\":1024,\"name\":\"_uiplatform\",\"url\":\"classes/aft_ui_browsers.BrowserSession.html#_uiplatform\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-browsers.BrowserSession\"},{\"kind\":1024,\"name\":\"_resolution\",\"url\":\"classes/aft_ui_browsers.BrowserSession.html#_resolution\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-browsers.BrowserSession\"},{\"kind\":1024,\"name\":\"_additionalCapabilities\",\"url\":\"classes/aft_ui_browsers.BrowserSession.html#_additionalCapabilities\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-browsers.BrowserSession\"},{\"kind\":262144,\"name\":\"uiplatform\",\"url\":\"classes/aft_ui_browsers.BrowserSession.html#uiplatform\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserSession\"},{\"kind\":262144,\"name\":\"resolution\",\"url\":\"classes/aft_ui_browsers.BrowserSession.html#resolution\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserSession\"},{\"kind\":262144,\"name\":\"additionalCapabilities\",\"url\":\"classes/aft_ui_browsers.BrowserSession.html#additionalCapabilities\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserSession\"},{\"kind\":262144,\"name\":\"driver\",\"url\":\"classes/aft_ui_browsers.BrowserSession.html#driver\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserSession\"},{\"kind\":2048,\"name\":\"getFacet\",\"url\":\"classes/aft_ui_browsers.BrowserSession.html#getFacet\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserSession\"},{\"kind\":2048,\"name\":\"goTo\",\"url\":\"classes/aft_ui_browsers.BrowserSession.html#goTo\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserSession\"},{\"kind\":2048,\"name\":\"refresh\",\"url\":\"classes/aft_ui_browsers.BrowserSession.html#refresh\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserSession\"},{\"kind\":2048,\"name\":\"resize\",\"url\":\"classes/aft_ui_browsers.BrowserSession.html#resize\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserSession\"},{\"kind\":2048,\"name\":\"dispose\",\"url\":\"classes/aft_ui_browsers.BrowserSession.html#dispose\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserSession\"},{\"kind\":2048,\"name\":\"option\",\"url\":\"classes/aft_ui_browsers.BrowserSession.html#option\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserSession\"},{\"kind\":262144,\"name\":\"platform\",\"url\":\"classes/aft_ui_browsers.BrowserSession.html#platform\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserSession\"},{\"kind\":262144,\"name\":\"logMgr\",\"url\":\"classes/aft_ui_browsers.BrowserSession.html#logMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserSession\"},{\"kind\":4194304,\"name\":\"BrowserStackBrowserSessionGeneratorPluginOptions\",\"url\":\"types/aft_ui_browsers.BrowserStackBrowserSessionGeneratorPluginOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-ui-browsers\"},{\"kind\":128,\"name\":\"BrowserStackBrowserSessionGeneratorPlugin\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSessionGeneratorPlugin.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-ui-browsers\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSessionGeneratorPlugin.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSessionGeneratorPlugin\"},{\"kind\":1024,\"name\":\"_user\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSessionGeneratorPlugin.html#_user\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSessionGeneratorPlugin\"},{\"kind\":1024,\"name\":\"_key\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSessionGeneratorPlugin.html#_key\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSessionGeneratorPlugin\"},{\"kind\":1024,\"name\":\"_local\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSessionGeneratorPlugin.html#_local\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSessionGeneratorPlugin\"},{\"kind\":1024,\"name\":\"_localIdentifier\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSessionGeneratorPlugin.html#_localIdentifier\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSessionGeneratorPlugin\"},{\"kind\":1024,\"name\":\"_debug\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSessionGeneratorPlugin.html#_debug\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"user\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSessionGeneratorPlugin.html#user\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"key\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSessionGeneratorPlugin.html#key\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"local\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSessionGeneratorPlugin.html#local\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"localIdentifier\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSessionGeneratorPlugin.html#localIdentifier\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"debug\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSessionGeneratorPlugin.html#debug\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"url\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSessionGeneratorPlugin.html#url\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"newUiSession\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSessionGeneratorPlugin.html#newUiSession\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"generateCapabilities\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSessionGeneratorPlugin.html#generateCapabilities\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"resolution\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSessionGeneratorPlugin.html#resolution\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"additionalCapabilities\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSessionGeneratorPlugin.html#additionalCapabilities\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"implicitTimeout\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSessionGeneratorPlugin.html#implicitTimeout\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"createDriver\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSessionGeneratorPlugin.html#createDriver\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"logMgr\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSessionGeneratorPlugin.html#logMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"uiplatform\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSessionGeneratorPlugin.html#uiplatform\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"option\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSessionGeneratorPlugin.html#option\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"enabled\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSessionGeneratorPlugin.html#enabled\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSessionGeneratorPlugin\"},{\"kind\":4194304,\"name\":\"BrowserStackBrowserSessionOptions\",\"url\":\"types/aft_ui_browsers.BrowserStackBrowserSessionOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-ui-browsers\"},{\"kind\":128,\"name\":\"BrowserStackBrowserSession\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSession.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-ui-browsers\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSession.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSession\"},{\"kind\":1024,\"name\":\"_user\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSession.html#_user\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSession\"},{\"kind\":1024,\"name\":\"_key\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSession.html#_key\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSession\"},{\"kind\":1024,\"name\":\"_local\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSession.html#_local\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSession\"},{\"kind\":1024,\"name\":\"_localIdentifier\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSession.html#_localIdentifier\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSession\"},{\"kind\":1024,\"name\":\"_debug\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSession.html#_debug\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSession\"},{\"kind\":262144,\"name\":\"user\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSession.html#user\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSession\"},{\"kind\":262144,\"name\":\"key\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSession.html#key\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSession\"},{\"kind\":262144,\"name\":\"local\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSession.html#local\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSession\"},{\"kind\":262144,\"name\":\"localIdentifier\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSession.html#localIdentifier\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSession\"},{\"kind\":262144,\"name\":\"debug\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSession.html#debug\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSession\"},{\"kind\":2048,\"name\":\"dispose\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSession.html#dispose\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSession\"},{\"kind\":262144,\"name\":\"uiplatform\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSession.html#uiplatform\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSession\"},{\"kind\":262144,\"name\":\"resolution\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSession.html#resolution\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSession\"},{\"kind\":262144,\"name\":\"additionalCapabilities\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSession.html#additionalCapabilities\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSession\"},{\"kind\":262144,\"name\":\"driver\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSession.html#driver\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSession\"},{\"kind\":2048,\"name\":\"getFacet\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSession.html#getFacet\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSession\"},{\"kind\":2048,\"name\":\"goTo\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSession.html#goTo\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSession\"},{\"kind\":2048,\"name\":\"refresh\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSession.html#refresh\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSession\"},{\"kind\":2048,\"name\":\"resize\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSession.html#resize\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSession\"},{\"kind\":2048,\"name\":\"option\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSession.html#option\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSession\"},{\"kind\":262144,\"name\":\"platform\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSession.html#platform\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSession\"},{\"kind\":262144,\"name\":\"logMgr\",\"url\":\"classes/aft_ui_browsers.BrowserStackBrowserSession.html#logMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.BrowserStackBrowserSession\"},{\"kind\":4194304,\"name\":\"SauceLabsBrowserSessionGeneratorPluginOptions\",\"url\":\"types/aft_ui_browsers.SauceLabsBrowserSessionGeneratorPluginOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-ui-browsers\"},{\"kind\":128,\"name\":\"SauceLabsBrowserSessionGeneratorPlugin\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSessionGeneratorPlugin.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-ui-browsers\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSessionGeneratorPlugin.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSessionGeneratorPlugin\"},{\"kind\":1024,\"name\":\"_username\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSessionGeneratorPlugin.html#_username\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSessionGeneratorPlugin\"},{\"kind\":1024,\"name\":\"_accessKey\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSessionGeneratorPlugin.html#_accessKey\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSessionGeneratorPlugin\"},{\"kind\":1024,\"name\":\"_tunnel\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSessionGeneratorPlugin.html#_tunnel\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSessionGeneratorPlugin\"},{\"kind\":1024,\"name\":\"_tunnelIdentifier\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSessionGeneratorPlugin.html#_tunnelIdentifier\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"username\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSessionGeneratorPlugin.html#username\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"accessKey\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSessionGeneratorPlugin.html#accessKey\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"tunnel\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSessionGeneratorPlugin.html#tunnel\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"tunnelIdentifier\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSessionGeneratorPlugin.html#tunnelIdentifier\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"url\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSessionGeneratorPlugin.html#url\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"newUiSession\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSessionGeneratorPlugin.html#newUiSession\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"generateCapabilities\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSessionGeneratorPlugin.html#generateCapabilities\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"resolution\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSessionGeneratorPlugin.html#resolution\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"additionalCapabilities\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSessionGeneratorPlugin.html#additionalCapabilities\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"implicitTimeout\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSessionGeneratorPlugin.html#implicitTimeout\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"createDriver\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSessionGeneratorPlugin.html#createDriver\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"logMgr\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSessionGeneratorPlugin.html#logMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"uiplatform\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSessionGeneratorPlugin.html#uiplatform\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"option\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSessionGeneratorPlugin.html#option\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"enabled\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSessionGeneratorPlugin.html#enabled\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSessionGeneratorPlugin\"},{\"kind\":4194304,\"name\":\"SauceLabsBrowserSessionOptions\",\"url\":\"types/aft_ui_browsers.SauceLabsBrowserSessionOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-ui-browsers\"},{\"kind\":128,\"name\":\"SauceLabsBrowserSession\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSession.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-ui-browsers\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSession.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSession\"},{\"kind\":1024,\"name\":\"_username\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSession.html#_username\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSession\"},{\"kind\":1024,\"name\":\"_accessKey\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSession.html#_accessKey\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSession\"},{\"kind\":1024,\"name\":\"_tunnel\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSession.html#_tunnel\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSession\"},{\"kind\":1024,\"name\":\"_tunnelIdentifier\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSession.html#_tunnelIdentifier\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSession\"},{\"kind\":262144,\"name\":\"username\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSession.html#username\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSession\"},{\"kind\":262144,\"name\":\"accessKey\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSession.html#accessKey\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSession\"},{\"kind\":262144,\"name\":\"tunnel\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSession.html#tunnel\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSession\"},{\"kind\":262144,\"name\":\"tunnelIdentifier\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSession.html#tunnelIdentifier\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSession\"},{\"kind\":2048,\"name\":\"dispose\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSession.html#dispose\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSession\"},{\"kind\":262144,\"name\":\"uiplatform\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSession.html#uiplatform\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSession\"},{\"kind\":262144,\"name\":\"resolution\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSession.html#resolution\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSession\"},{\"kind\":262144,\"name\":\"additionalCapabilities\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSession.html#additionalCapabilities\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSession\"},{\"kind\":262144,\"name\":\"driver\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSession.html#driver\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSession\"},{\"kind\":2048,\"name\":\"getFacet\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSession.html#getFacet\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSession\"},{\"kind\":2048,\"name\":\"goTo\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSession.html#goTo\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSession\"},{\"kind\":2048,\"name\":\"refresh\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSession.html#refresh\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSession\"},{\"kind\":2048,\"name\":\"resize\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSession.html#resize\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSession\"},{\"kind\":2048,\"name\":\"option\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSession.html#option\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSession\"},{\"kind\":262144,\"name\":\"platform\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSession.html#platform\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSession\"},{\"kind\":262144,\"name\":\"logMgr\",\"url\":\"classes/aft_ui_browsers.SauceLabsBrowserSession.html#logMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.SauceLabsBrowserSession\"},{\"kind\":128,\"name\":\"SeleniumGridSessionGeneratorPlugin\",\"url\":\"classes/aft_ui_browsers.SeleniumGridSessionGeneratorPlugin.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-ui-browsers\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_ui_browsers.SeleniumGridSessionGeneratorPlugin.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.SeleniumGridSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"newUiSession\",\"url\":\"classes/aft_ui_browsers.SeleniumGridSessionGeneratorPlugin.html#newUiSession\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.SeleniumGridSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"generateCapabilities\",\"url\":\"classes/aft_ui_browsers.SeleniumGridSessionGeneratorPlugin.html#generateCapabilities\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-browsers.SeleniumGridSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"url\",\"url\":\"classes/aft_ui_browsers.SeleniumGridSessionGeneratorPlugin.html#url\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.SeleniumGridSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"resolution\",\"url\":\"classes/aft_ui_browsers.SeleniumGridSessionGeneratorPlugin.html#resolution\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.SeleniumGridSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"additionalCapabilities\",\"url\":\"classes/aft_ui_browsers.SeleniumGridSessionGeneratorPlugin.html#additionalCapabilities\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.SeleniumGridSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"implicitTimeout\",\"url\":\"classes/aft_ui_browsers.SeleniumGridSessionGeneratorPlugin.html#implicitTimeout\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.SeleniumGridSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"createDriver\",\"url\":\"classes/aft_ui_browsers.SeleniumGridSessionGeneratorPlugin.html#createDriver\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-browsers.SeleniumGridSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"logMgr\",\"url\":\"classes/aft_ui_browsers.SeleniumGridSessionGeneratorPlugin.html#logMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.SeleniumGridSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"uiplatform\",\"url\":\"classes/aft_ui_browsers.SeleniumGridSessionGeneratorPlugin.html#uiplatform\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.SeleniumGridSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"option\",\"url\":\"classes/aft_ui_browsers.SeleniumGridSessionGeneratorPlugin.html#option\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.SeleniumGridSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"enabled\",\"url\":\"classes/aft_ui_browsers.SeleniumGridSessionGeneratorPlugin.html#enabled\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-browsers.SeleniumGridSessionGeneratorPlugin\"},{\"kind\":32,\"name\":\"mobileAppSessionGeneratorMgr\",\"url\":\"variables/aft_ui_mobile_apps.mobileAppSessionGeneratorMgr.html\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"aft-ui-mobile-apps\"},{\"kind\":4194304,\"name\":\"MobileAppElementOptions\",\"url\":\"types/aft_ui_mobile_apps.MobileAppElementOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-ui-mobile-apps\"},{\"kind\":4194304,\"name\":\"MobileAppFacetOptions\",\"url\":\"types/aft_ui_mobile_apps.MobileAppFacetOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-ui-mobile-apps\"},{\"kind\":128,\"name\":\"MobileAppFacet\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppFacet.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-ui-mobile-apps\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppFacet.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppFacet\"},{\"kind\":262144,\"name\":\"locator\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppFacet.html#locator\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.MobileAppFacet\"},{\"kind\":262144,\"name\":\"session\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppFacet.html#session\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.MobileAppFacet\"},{\"kind\":262144,\"name\":\"parent\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppFacet.html#parent\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.MobileAppFacet\"},{\"kind\":2048,\"name\":\"getElements\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppFacet.html#getElements\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.MobileAppFacet\"},{\"kind\":2048,\"name\":\"getElement\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppFacet.html#getElement\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.MobileAppFacet\"},{\"kind\":2048,\"name\":\"getFacet\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppFacet.html#getFacet\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.MobileAppFacet\"},{\"kind\":2048,\"name\":\"getRoot\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppFacet.html#getRoot\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.MobileAppFacet\"},{\"kind\":2048,\"name\":\"option\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppFacet.html#option\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppFacet\"},{\"kind\":262144,\"name\":\"logMgr\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppFacet.html#logMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppFacet\"},{\"kind\":262144,\"name\":\"index\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppFacet.html#index\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppFacet\"},{\"kind\":262144,\"name\":\"maxWaitMs\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppFacet.html#maxWaitMs\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppFacet\"},{\"kind\":262144,\"name\":\"retryDelayMs\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppFacet.html#retryDelayMs\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppFacet\"},{\"kind\":262144,\"name\":\"retryDelayBackOff\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppFacet.html#retryDelayBackOff\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppFacet\"},{\"kind\":128,\"name\":\"MobileAppVerifier\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-ui-mobile-apps\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":1024,\"name\":\"_assertion\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#_assertion\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":1024,\"name\":\"_sessionMgr\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#_sessionMgr\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":1024,\"name\":\"_session\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#_session\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":1024,\"name\":\"_sessionOptions\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#_sessionOptions\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":262144,\"name\":\"sessionGeneratorManager\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#sessionGeneratorManager\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":262144,\"name\":\"session\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#session\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":2048,\"name\":\"withMobileAppSessionOptions\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#withMobileAppSessionOptions\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":2048,\"name\":\"withMobileAppSessionGeneratorManager\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#withMobileAppSessionGeneratorManager\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":262144,\"name\":\"sessionOptions\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#sessionOptions\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":2048,\"name\":\"_resolveAssertion\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#_resolveAssertion\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":1024,\"name\":\"_matcher\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#_matcher\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":1024,\"name\":\"_description\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#_description\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":1024,\"name\":\"_startTime\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#_startTime\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":1024,\"name\":\"_innerPromise\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#_innerPromise\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":1024,\"name\":\"_tests\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#_tests\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":1024,\"name\":\"_defects\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#_defects\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":1024,\"name\":\"_logMgr\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#_logMgr\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":1024,\"name\":\"_testMgr\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#_testMgr\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":1024,\"name\":\"_defectMgr\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#_defectMgr\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":1024,\"name\":\"_buildMgr\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#_buildMgr\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":262144,\"name\":\"logMgr\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#logMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":262144,\"name\":\"testMgr\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#testMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":262144,\"name\":\"defectMgr\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#defectMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":262144,\"name\":\"buildMgr\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#buildMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":2048,\"name\":\"then\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#then\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":2048,\"name\":\"_getInnerPromise\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#_getInnerPromise\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":262144,\"name\":\"and\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#and\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":2048,\"name\":\"verify\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#verify\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":2048,\"name\":\"withDescription\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#withDescription\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":2048,\"name\":\"withTestIds\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#withTestIds\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":2048,\"name\":\"withKnownDefectIds\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#withKnownDefectIds\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":2048,\"name\":\"returns\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#returns\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":2048,\"name\":\"withLogManager\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#withLogManager\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":2048,\"name\":\"withTestCaseManager\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#withTestCaseManager\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":2048,\"name\":\"withDefectManager\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#withDefectManager\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":2048,\"name\":\"withBuildInfoManager\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#withBuildInfoManager\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":2048,\"name\":\"_shouldRun_tests\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#_shouldRun_tests\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":2048,\"name\":\"_shouldRun_defects\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#_shouldRun_defects\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":2048,\"name\":\"_logResult\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#_logResult\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":2048,\"name\":\"_logMessage\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#_logMessage\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":2048,\"name\":\"_generateTestResults\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#_generateTestResults\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":2048,\"name\":\"_generateTestResult\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppVerifier.html#_generateTestResult\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppVerifier\"},{\"kind\":64,\"name\":\"verifyWithMobileApp\",\"url\":\"functions/aft_ui_mobile_apps.verifyWithMobileApp.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"aft-ui-mobile-apps\"},{\"kind\":4194304,\"name\":\"MobileAppSessionGeneratorPluginOptions\",\"url\":\"types/aft_ui_mobile_apps.MobileAppSessionGeneratorPluginOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-ui-mobile-apps\"},{\"kind\":128,\"name\":\"MobileAppSessionGeneratorPlugin\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppSessionGeneratorPlugin.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-ui-mobile-apps\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppSessionGeneratorPlugin.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppSessionGeneratorPlugin\"},{\"kind\":1024,\"name\":\"_app\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppSessionGeneratorPlugin.html#_app\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-mobile-apps.MobileAppSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"generateRemoteOptions\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppSessionGeneratorPlugin.html#generateRemoteOptions\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.MobileAppSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"app\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppSessionGeneratorPlugin.html#app\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.MobileAppSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"newUiSession\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppSessionGeneratorPlugin.html#newUiSession\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.MobileAppSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"createDriver\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppSessionGeneratorPlugin.html#createDriver\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.MobileAppSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"sendCommand\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppSessionGeneratorPlugin.html#sendCommand\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.MobileAppSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"logMgr\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppSessionGeneratorPlugin.html#logMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"uiplatform\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppSessionGeneratorPlugin.html#uiplatform\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"option\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppSessionGeneratorPlugin.html#option\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"enabled\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppSessionGeneratorPlugin.html#enabled\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppSessionGeneratorPlugin\"},{\"kind\":4194304,\"name\":\"MobileAppSessionOptions\",\"url\":\"types/aft_ui_mobile_apps.MobileAppSessionOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-ui-mobile-apps\"},{\"kind\":128,\"name\":\"MobileAppSession\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppSession.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-ui-mobile-apps\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppSession.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppSession\"},{\"kind\":1024,\"name\":\"_driver\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppSession.html#_driver\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-mobile-apps.MobileAppSession\"},{\"kind\":262144,\"name\":\"driver\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppSession.html#driver\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.MobileAppSession\"},{\"kind\":2048,\"name\":\"getFacet\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppSession.html#getFacet\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.MobileAppSession\"},{\"kind\":2048,\"name\":\"dispose\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppSession.html#dispose\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.MobileAppSession\"},{\"kind\":2048,\"name\":\"option\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppSession.html#option\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppSession\"},{\"kind\":262144,\"name\":\"platform\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppSession.html#platform\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppSession\"},{\"kind\":262144,\"name\":\"logMgr\",\"url\":\"classes/aft_ui_mobile_apps.MobileAppSession.html#logMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.MobileAppSession\"},{\"kind\":4194304,\"name\":\"BrowserStackMobileAppSessionGeneratorPluginOptions\",\"url\":\"types/aft_ui_mobile_apps.BrowserStackMobileAppSessionGeneratorPluginOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-ui-mobile-apps\"},{\"kind\":128,\"name\":\"BrowserStackMobileAppSessionGeneratorPlugin\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSessionGeneratorPlugin.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-ui-mobile-apps\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSessionGeneratorPlugin.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSessionGeneratorPlugin\"},{\"kind\":1024,\"name\":\"_api\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSessionGeneratorPlugin.html#_api\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSessionGeneratorPlugin\"},{\"kind\":1024,\"name\":\"_apiUrl\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSessionGeneratorPlugin.html#_apiUrl\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSessionGeneratorPlugin\"},{\"kind\":1024,\"name\":\"_user\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSessionGeneratorPlugin.html#_user\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSessionGeneratorPlugin\"},{\"kind\":1024,\"name\":\"_key\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSessionGeneratorPlugin.html#_key\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSessionGeneratorPlugin\"},{\"kind\":1024,\"name\":\"_debug\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSessionGeneratorPlugin.html#_debug\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSessionGeneratorPlugin\"},{\"kind\":1024,\"name\":\"_local\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSessionGeneratorPlugin.html#_local\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSessionGeneratorPlugin\"},{\"kind\":1024,\"name\":\"_localIdentifier\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSessionGeneratorPlugin.html#_localIdentifier\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"api\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSessionGeneratorPlugin.html#api\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"apiUrl\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSessionGeneratorPlugin.html#apiUrl\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"user\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSessionGeneratorPlugin.html#user\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"key\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSessionGeneratorPlugin.html#key\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"debug\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSessionGeneratorPlugin.html#debug\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"local\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSessionGeneratorPlugin.html#local\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"localIdentifier\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSessionGeneratorPlugin.html#localIdentifier\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"newUiSession\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSessionGeneratorPlugin.html#newUiSession\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"generateRemoteOptions\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSessionGeneratorPlugin.html#generateRemoteOptions\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"sendCommand\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSessionGeneratorPlugin.html#sendCommand\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"app\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSessionGeneratorPlugin.html#app\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"createDriver\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSessionGeneratorPlugin.html#createDriver\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"logMgr\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSessionGeneratorPlugin.html#logMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"uiplatform\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSessionGeneratorPlugin.html#uiplatform\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"option\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSessionGeneratorPlugin.html#option\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"enabled\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSessionGeneratorPlugin.html#enabled\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSessionGeneratorPlugin\"},{\"kind\":4194304,\"name\":\"BrowserStackMobileAppSessionOptions\",\"url\":\"types/aft_ui_mobile_apps.BrowserStackMobileAppSessionOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-ui-mobile-apps\"},{\"kind\":128,\"name\":\"BrowserStackMobileAppSession\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSession.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-ui-mobile-apps\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSession.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSession\"},{\"kind\":1024,\"name\":\"_user\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSession.html#_user\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSession\"},{\"kind\":1024,\"name\":\"_key\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSession.html#_key\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSession\"},{\"kind\":1024,\"name\":\"_debug\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSession.html#_debug\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSession\"},{\"kind\":1024,\"name\":\"_local\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSession.html#_local\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSession\"},{\"kind\":1024,\"name\":\"_localIdentifier\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSession.html#_localIdentifier\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSession\"},{\"kind\":262144,\"name\":\"user\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSession.html#user\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSession\"},{\"kind\":262144,\"name\":\"key\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSession.html#key\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSession\"},{\"kind\":262144,\"name\":\"debug\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSession.html#debug\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSession\"},{\"kind\":262144,\"name\":\"local\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSession.html#local\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSession\"},{\"kind\":262144,\"name\":\"localIdentifier\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSession.html#localIdentifier\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSession\"},{\"kind\":2048,\"name\":\"dispose\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSession.html#dispose\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSession\"},{\"kind\":262144,\"name\":\"driver\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSession.html#driver\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSession\"},{\"kind\":2048,\"name\":\"getFacet\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSession.html#getFacet\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSession\"},{\"kind\":2048,\"name\":\"option\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSession.html#option\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSession\"},{\"kind\":262144,\"name\":\"platform\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSession.html#platform\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSession\"},{\"kind\":262144,\"name\":\"logMgr\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackMobileAppSession.html#logMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileAppSession\"},{\"kind\":4194304,\"name\":\"RecentGroupAppsResponse\",\"url\":\"types/aft_ui_mobile_apps.RecentGroupAppsResponse.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-ui-mobile-apps\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_ui_mobile_apps.RecentGroupAppsResponse.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-ui-mobile-apps.RecentGroupAppsResponse\"},{\"kind\":1024,\"name\":\"apps\",\"url\":\"types/aft_ui_mobile_apps.RecentGroupAppsResponse.html#__type.apps\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui-mobile-apps.RecentGroupAppsResponse.__type\"},{\"kind\":4194304,\"name\":\"BrowserStackMobileApp\",\"url\":\"types/aft_ui_mobile_apps.BrowserStackMobileApp.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-ui-mobile-apps\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_ui_mobile_apps.BrowserStackMobileApp.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileApp\"},{\"kind\":1024,\"name\":\"app_name\",\"url\":\"types/aft_ui_mobile_apps.BrowserStackMobileApp.html#__type.app_name\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileApp.__type\"},{\"kind\":1024,\"name\":\"app_version\",\"url\":\"types/aft_ui_mobile_apps.BrowserStackMobileApp.html#__type.app_version\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileApp.__type\"},{\"kind\":1024,\"name\":\"app_url\",\"url\":\"types/aft_ui_mobile_apps.BrowserStackMobileApp.html#__type.app_url\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileApp.__type\"},{\"kind\":1024,\"name\":\"app_id\",\"url\":\"types/aft_ui_mobile_apps.BrowserStackMobileApp.html#__type.app_id\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileApp.__type\"},{\"kind\":1024,\"name\":\"uploaded_at\",\"url\":\"types/aft_ui_mobile_apps.BrowserStackMobileApp.html#__type.uploaded_at\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileApp.__type\"},{\"kind\":1024,\"name\":\"custom_id\",\"url\":\"types/aft_ui_mobile_apps.BrowserStackMobileApp.html#__type.custom_id\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileApp.__type\"},{\"kind\":1024,\"name\":\"shareable_id\",\"url\":\"types/aft_ui_mobile_apps.BrowserStackMobileApp.html#__type.shareable_id\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui-mobile-apps.BrowserStackMobileApp.__type\"},{\"kind\":4194304,\"name\":\"SetSessionStatusRequest\",\"url\":\"types/aft_ui_mobile_apps.SetSessionStatusRequest.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-ui-mobile-apps\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_ui_mobile_apps.SetSessionStatusRequest.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-ui-mobile-apps.SetSessionStatusRequest\"},{\"kind\":1024,\"name\":\"sessionId\",\"url\":\"types/aft_ui_mobile_apps.SetSessionStatusRequest.html#__type.sessionId\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui-mobile-apps.SetSessionStatusRequest.__type\"},{\"kind\":1024,\"name\":\"status\",\"url\":\"types/aft_ui_mobile_apps.SetSessionStatusRequest.html#__type.status\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui-mobile-apps.SetSessionStatusRequest.__type\"},{\"kind\":1024,\"name\":\"message\",\"url\":\"types/aft_ui_mobile_apps.SetSessionStatusRequest.html#__type.message\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui-mobile-apps.SetSessionStatusRequest.__type\"},{\"kind\":4194304,\"name\":\"UploadRequest\",\"url\":\"types/aft_ui_mobile_apps.UploadRequest.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-ui-mobile-apps\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_ui_mobile_apps.UploadRequest.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-ui-mobile-apps.UploadRequest\"},{\"kind\":1024,\"name\":\"file\",\"url\":\"types/aft_ui_mobile_apps.UploadRequest.html#__type.file\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui-mobile-apps.UploadRequest.__type\"},{\"kind\":1024,\"name\":\"custom_id\",\"url\":\"types/aft_ui_mobile_apps.UploadRequest.html#__type.custom_id\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui-mobile-apps.UploadRequest.__type\"},{\"kind\":4194304,\"name\":\"UploadResponse\",\"url\":\"types/aft_ui_mobile_apps.UploadResponse.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-ui-mobile-apps\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_ui_mobile_apps.UploadResponse.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-ui-mobile-apps.UploadResponse\"},{\"kind\":1024,\"name\":\"app_url\",\"url\":\"types/aft_ui_mobile_apps.UploadResponse.html#__type.app_url\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui-mobile-apps.UploadResponse.__type\"},{\"kind\":1024,\"name\":\"custom_id\",\"url\":\"types/aft_ui_mobile_apps.UploadResponse.html#__type.custom_id\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui-mobile-apps.UploadResponse.__type\"},{\"kind\":1024,\"name\":\"shareable_id\",\"url\":\"types/aft_ui_mobile_apps.UploadResponse.html#__type.shareable_id\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui-mobile-apps.UploadResponse.__type\"},{\"kind\":4194304,\"name\":\"BrowserStackAppAutomateApiOptions\",\"url\":\"types/aft_ui_mobile_apps.BrowserStackAppAutomateApiOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-ui-mobile-apps\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_ui_mobile_apps.BrowserStackAppAutomateApiOptions.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-ui-mobile-apps.BrowserStackAppAutomateApiOptions\"},{\"kind\":1024,\"name\":\"apiUrl\",\"url\":\"types/aft_ui_mobile_apps.BrowserStackAppAutomateApiOptions.html#__type.apiUrl\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui-mobile-apps.BrowserStackAppAutomateApiOptions.__type\"},{\"kind\":1024,\"name\":\"user\",\"url\":\"types/aft_ui_mobile_apps.BrowserStackAppAutomateApiOptions.html#__type.user\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui-mobile-apps.BrowserStackAppAutomateApiOptions.__type\"},{\"kind\":1024,\"name\":\"key\",\"url\":\"types/aft_ui_mobile_apps.BrowserStackAppAutomateApiOptions.html#__type.key\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui-mobile-apps.BrowserStackAppAutomateApiOptions.__type\"},{\"kind\":1024,\"name\":\"logMgr\",\"url\":\"types/aft_ui_mobile_apps.BrowserStackAppAutomateApiOptions.html#__type.logMgr\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui-mobile-apps.BrowserStackAppAutomateApiOptions.__type\"},{\"kind\":128,\"name\":\"BrowserStackAppAutomateApi\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackAppAutomateApi.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-ui-mobile-apps\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackAppAutomateApi.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.BrowserStackAppAutomateApi\"},{\"kind\":1024,\"name\":\"_options\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackAppAutomateApi.html#_options\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-mobile-apps.BrowserStackAppAutomateApi\"},{\"kind\":1024,\"name\":\"_apiUrl\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackAppAutomateApi.html#_apiUrl\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-mobile-apps.BrowserStackAppAutomateApi\"},{\"kind\":1024,\"name\":\"_user\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackAppAutomateApi.html#_user\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-mobile-apps.BrowserStackAppAutomateApi\"},{\"kind\":1024,\"name\":\"_key\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackAppAutomateApi.html#_key\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-mobile-apps.BrowserStackAppAutomateApi\"},{\"kind\":1024,\"name\":\"_logMgr\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackAppAutomateApi.html#_logMgr\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-mobile-apps.BrowserStackAppAutomateApi\"},{\"kind\":2048,\"name\":\"option\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackAppAutomateApi.html#option\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.BrowserStackAppAutomateApi\"},{\"kind\":262144,\"name\":\"apiUrl\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackAppAutomateApi.html#apiUrl\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.BrowserStackAppAutomateApi\"},{\"kind\":262144,\"name\":\"user\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackAppAutomateApi.html#user\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.BrowserStackAppAutomateApi\"},{\"kind\":262144,\"name\":\"key\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackAppAutomateApi.html#key\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.BrowserStackAppAutomateApi\"},{\"kind\":262144,\"name\":\"logMgr\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackAppAutomateApi.html#logMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.BrowserStackAppAutomateApi\"},{\"kind\":2048,\"name\":\"uploadApp\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackAppAutomateApi.html#uploadApp\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.BrowserStackAppAutomateApi\"},{\"kind\":2048,\"name\":\"getApps\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackAppAutomateApi.html#getApps\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.BrowserStackAppAutomateApi\"},{\"kind\":2048,\"name\":\"setSessionStatus\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackAppAutomateApi.html#setSessionStatus\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.BrowserStackAppAutomateApi\"},{\"kind\":2048,\"name\":\"_getAuthHeader\",\"url\":\"classes/aft_ui_mobile_apps.BrowserStackAppAutomateApi.html#_getAuthHeader\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-mobile-apps.BrowserStackAppAutomateApi\"},{\"kind\":4194304,\"name\":\"SauceLabsMobileAppSessionGeneratorPluginOptions\",\"url\":\"types/aft_ui_mobile_apps.SauceLabsMobileAppSessionGeneratorPluginOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-ui-mobile-apps\"},{\"kind\":128,\"name\":\"SauceLabsMobileAppSessionGeneratorPlugin\",\"url\":\"classes/aft_ui_mobile_apps.SauceLabsMobileAppSessionGeneratorPlugin.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-ui-mobile-apps\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_ui_mobile_apps.SauceLabsMobileAppSessionGeneratorPlugin.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.SauceLabsMobileAppSessionGeneratorPlugin\"},{\"kind\":1024,\"name\":\"_username\",\"url\":\"classes/aft_ui_mobile_apps.SauceLabsMobileAppSessionGeneratorPlugin.html#_username\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-mobile-apps.SauceLabsMobileAppSessionGeneratorPlugin\"},{\"kind\":1024,\"name\":\"_accessKey\",\"url\":\"classes/aft_ui_mobile_apps.SauceLabsMobileAppSessionGeneratorPlugin.html#_accessKey\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-mobile-apps.SauceLabsMobileAppSessionGeneratorPlugin\"},{\"kind\":1024,\"name\":\"_tunnel\",\"url\":\"classes/aft_ui_mobile_apps.SauceLabsMobileAppSessionGeneratorPlugin.html#_tunnel\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-mobile-apps.SauceLabsMobileAppSessionGeneratorPlugin\"},{\"kind\":1024,\"name\":\"_tunnelIdentifier\",\"url\":\"classes/aft_ui_mobile_apps.SauceLabsMobileAppSessionGeneratorPlugin.html#_tunnelIdentifier\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-mobile-apps.SauceLabsMobileAppSessionGeneratorPlugin\"},{\"kind\":1024,\"name\":\"_apiUrl\",\"url\":\"classes/aft_ui_mobile_apps.SauceLabsMobileAppSessionGeneratorPlugin.html#_apiUrl\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-mobile-apps.SauceLabsMobileAppSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"username\",\"url\":\"classes/aft_ui_mobile_apps.SauceLabsMobileAppSessionGeneratorPlugin.html#username\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.SauceLabsMobileAppSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"accessKey\",\"url\":\"classes/aft_ui_mobile_apps.SauceLabsMobileAppSessionGeneratorPlugin.html#accessKey\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.SauceLabsMobileAppSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"tunnel\",\"url\":\"classes/aft_ui_mobile_apps.SauceLabsMobileAppSessionGeneratorPlugin.html#tunnel\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.SauceLabsMobileAppSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"tunnelIdentifier\",\"url\":\"classes/aft_ui_mobile_apps.SauceLabsMobileAppSessionGeneratorPlugin.html#tunnelIdentifier\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.SauceLabsMobileAppSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"apiUrl\",\"url\":\"classes/aft_ui_mobile_apps.SauceLabsMobileAppSessionGeneratorPlugin.html#apiUrl\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.SauceLabsMobileAppSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"newUiSession\",\"url\":\"classes/aft_ui_mobile_apps.SauceLabsMobileAppSessionGeneratorPlugin.html#newUiSession\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.SauceLabsMobileAppSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"generateRemoteOptions\",\"url\":\"classes/aft_ui_mobile_apps.SauceLabsMobileAppSessionGeneratorPlugin.html#generateRemoteOptions\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.SauceLabsMobileAppSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"sendCommand\",\"url\":\"classes/aft_ui_mobile_apps.SauceLabsMobileAppSessionGeneratorPlugin.html#sendCommand\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.SauceLabsMobileAppSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"app\",\"url\":\"classes/aft_ui_mobile_apps.SauceLabsMobileAppSessionGeneratorPlugin.html#app\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.SauceLabsMobileAppSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"createDriver\",\"url\":\"classes/aft_ui_mobile_apps.SauceLabsMobileAppSessionGeneratorPlugin.html#createDriver\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.SauceLabsMobileAppSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"logMgr\",\"url\":\"classes/aft_ui_mobile_apps.SauceLabsMobileAppSessionGeneratorPlugin.html#logMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.SauceLabsMobileAppSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"uiplatform\",\"url\":\"classes/aft_ui_mobile_apps.SauceLabsMobileAppSessionGeneratorPlugin.html#uiplatform\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.SauceLabsMobileAppSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"option\",\"url\":\"classes/aft_ui_mobile_apps.SauceLabsMobileAppSessionGeneratorPlugin.html#option\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.SauceLabsMobileAppSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"enabled\",\"url\":\"classes/aft_ui_mobile_apps.SauceLabsMobileAppSessionGeneratorPlugin.html#enabled\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.SauceLabsMobileAppSessionGeneratorPlugin\"},{\"kind\":4194304,\"name\":\"SauceLabsMobileAppSessionOptions\",\"url\":\"types/aft_ui_mobile_apps.SauceLabsMobileAppSessionOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-ui-mobile-apps\"},{\"kind\":128,\"name\":\"SauceLabsMobileAppSession\",\"url\":\"classes/aft_ui_mobile_apps.SauceLabsMobileAppSession.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-ui-mobile-apps\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_ui_mobile_apps.SauceLabsMobileAppSession.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.SauceLabsMobileAppSession\"},{\"kind\":1024,\"name\":\"_username\",\"url\":\"classes/aft_ui_mobile_apps.SauceLabsMobileAppSession.html#_username\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-mobile-apps.SauceLabsMobileAppSession\"},{\"kind\":1024,\"name\":\"_accessKey\",\"url\":\"classes/aft_ui_mobile_apps.SauceLabsMobileAppSession.html#_accessKey\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-mobile-apps.SauceLabsMobileAppSession\"},{\"kind\":1024,\"name\":\"_tunnel\",\"url\":\"classes/aft_ui_mobile_apps.SauceLabsMobileAppSession.html#_tunnel\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-mobile-apps.SauceLabsMobileAppSession\"},{\"kind\":1024,\"name\":\"_tunnelIdentifier\",\"url\":\"classes/aft_ui_mobile_apps.SauceLabsMobileAppSession.html#_tunnelIdentifier\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-mobile-apps.SauceLabsMobileAppSession\"},{\"kind\":262144,\"name\":\"username\",\"url\":\"classes/aft_ui_mobile_apps.SauceLabsMobileAppSession.html#username\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.SauceLabsMobileAppSession\"},{\"kind\":262144,\"name\":\"accessKey\",\"url\":\"classes/aft_ui_mobile_apps.SauceLabsMobileAppSession.html#accessKey\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.SauceLabsMobileAppSession\"},{\"kind\":262144,\"name\":\"tunnel\",\"url\":\"classes/aft_ui_mobile_apps.SauceLabsMobileAppSession.html#tunnel\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.SauceLabsMobileAppSession\"},{\"kind\":262144,\"name\":\"tunnelIdentifier\",\"url\":\"classes/aft_ui_mobile_apps.SauceLabsMobileAppSession.html#tunnelIdentifier\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.SauceLabsMobileAppSession\"},{\"kind\":2048,\"name\":\"dispose\",\"url\":\"classes/aft_ui_mobile_apps.SauceLabsMobileAppSession.html#dispose\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.SauceLabsMobileAppSession\"},{\"kind\":262144,\"name\":\"driver\",\"url\":\"classes/aft_ui_mobile_apps.SauceLabsMobileAppSession.html#driver\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.SauceLabsMobileAppSession\"},{\"kind\":2048,\"name\":\"getFacet\",\"url\":\"classes/aft_ui_mobile_apps.SauceLabsMobileAppSession.html#getFacet\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.SauceLabsMobileAppSession\"},{\"kind\":2048,\"name\":\"option\",\"url\":\"classes/aft_ui_mobile_apps.SauceLabsMobileAppSession.html#option\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.SauceLabsMobileAppSession\"},{\"kind\":262144,\"name\":\"platform\",\"url\":\"classes/aft_ui_mobile_apps.SauceLabsMobileAppSession.html#platform\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.SauceLabsMobileAppSession\"},{\"kind\":262144,\"name\":\"logMgr\",\"url\":\"classes/aft_ui_mobile_apps.SauceLabsMobileAppSession.html#logMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.SauceLabsMobileAppSession\"},{\"kind\":4194304,\"name\":\"AppiumGridSessionGeneratorPluginOptions\",\"url\":\"types/aft_ui_mobile_apps.AppiumGridSessionGeneratorPluginOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-ui-mobile-apps\"},{\"kind\":128,\"name\":\"AppiumGridSessionGeneratorPlugin\",\"url\":\"classes/aft_ui_mobile_apps.AppiumGridSessionGeneratorPlugin.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-ui-mobile-apps\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_ui_mobile_apps.AppiumGridSessionGeneratorPlugin.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.AppiumGridSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"newUiSession\",\"url\":\"classes/aft_ui_mobile_apps.AppiumGridSessionGeneratorPlugin.html#newUiSession\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.AppiumGridSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"generateRemoteOptions\",\"url\":\"classes/aft_ui_mobile_apps.AppiumGridSessionGeneratorPlugin.html#generateRemoteOptions\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.AppiumGridSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"sendCommand\",\"url\":\"classes/aft_ui_mobile_apps.AppiumGridSessionGeneratorPlugin.html#sendCommand\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-mobile-apps.AppiumGridSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"app\",\"url\":\"classes/aft_ui_mobile_apps.AppiumGridSessionGeneratorPlugin.html#app\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.AppiumGridSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"createDriver\",\"url\":\"classes/aft_ui_mobile_apps.AppiumGridSessionGeneratorPlugin.html#createDriver\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.AppiumGridSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"logMgr\",\"url\":\"classes/aft_ui_mobile_apps.AppiumGridSessionGeneratorPlugin.html#logMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.AppiumGridSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"uiplatform\",\"url\":\"classes/aft_ui_mobile_apps.AppiumGridSessionGeneratorPlugin.html#uiplatform\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.AppiumGridSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"option\",\"url\":\"classes/aft_ui_mobile_apps.AppiumGridSessionGeneratorPlugin.html#option\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.AppiumGridSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"enabled\",\"url\":\"classes/aft_ui_mobile_apps.AppiumGridSessionGeneratorPlugin.html#enabled\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-mobile-apps.AppiumGridSessionGeneratorPlugin\"},{\"kind\":32,\"name\":\"httpService\",\"url\":\"variables/aft_web_services.httpService.html\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"aft-web-services\"},{\"kind\":4,\"name\":\"XML\",\"url\":\"modules/aft_web_services.XML.html\",\"classes\":\"tsd-kind-namespace tsd-parent-kind-module\",\"parent\":\"aft-web-services\"},{\"kind\":64,\"name\":\"toObject\",\"url\":\"functions/aft_web_services.XML.toObject.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-namespace\",\"parent\":\"aft-web-services.XML\"},{\"kind\":4194304,\"name\":\"HttpMethod\",\"url\":\"types/aft_web_services.HttpMethod.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-web-services\"},{\"kind\":4194304,\"name\":\"HttpRequest\",\"url\":\"types/aft_web_services.HttpRequest.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-web-services\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_web_services.HttpRequest.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-web-services.HttpRequest\"},{\"kind\":1024,\"name\":\"url\",\"url\":\"types/aft_web_services.HttpRequest.html#__type.url\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpRequest.__type\"},{\"kind\":1024,\"name\":\"allowAutoRedirect\",\"url\":\"types/aft_web_services.HttpRequest.html#__type.allowAutoRedirect\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpRequest.__type\"},{\"kind\":1024,\"name\":\"headers\",\"url\":\"types/aft_web_services.HttpRequest.html#__type.headers\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpRequest.__type\"},{\"kind\":1024,\"name\":\"method\",\"url\":\"types/aft_web_services.HttpRequest.html#__type.method\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpRequest.__type\"},{\"kind\":1024,\"name\":\"postData\",\"url\":\"types/aft_web_services.HttpRequest.html#__type.postData\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpRequest.__type\"},{\"kind\":1024,\"name\":\"multipart\",\"url\":\"types/aft_web_services.HttpRequest.html#__type.multipart\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpRequest.__type\"},{\"kind\":1024,\"name\":\"logMgr\",\"url\":\"types/aft_web_services.HttpRequest.html#__type.logMgr\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpRequest.__type\"},{\"kind\":4194304,\"name\":\"HttpResponse\",\"url\":\"types/aft_web_services.HttpResponse.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-web-services\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_web_services.HttpResponse.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-web-services.HttpResponse\"},{\"kind\":1024,\"name\":\"headers\",\"url\":\"types/aft_web_services.HttpResponse.html#__type.headers\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpResponse.__type\"},{\"kind\":1024,\"name\":\"data\",\"url\":\"types/aft_web_services.HttpResponse.html#__type.data\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpResponse.__type\"},{\"kind\":1024,\"name\":\"statusCode\",\"url\":\"types/aft_web_services.HttpResponse.html#__type.statusCode\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpResponse.__type\"},{\"kind\":32,\"name\":\"httpData\",\"url\":\"variables/aft_web_services.httpData.html\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"aft-web-services\"}],\"index\":{\"version\":\"2.3.9\",\"fields\":[\"name\",\"comment\"],\"fieldVectors\":[[\"name/0\",[0,33.081,1,47.68]],[\"comment/0\",[]],[\"name/1\",[0,25.679,2,37.011,3,34.169]],[\"comment/1\",[]],[\"name/2\",[0,25.679,4,32.297,5,37.011]],[\"comment/2\",[]],[\"name/3\",[0,25.679,4,32.297,6,37.011]],[\"comment/3\",[]],[\"name/4\",[0,25.679,4,32.297,7,37.011]],[\"comment/4\",[]],[\"name/5\",[0,25.679,3,34.169,8,37.011]],[\"comment/5\",[]],[\"name/6\",[0,33.081,9,47.68]],[\"comment/6\",[]],[\"name/7\",[0,33.081,10,41.607]],[\"comment/7\",[]],[\"name/8\",[0,25.679,10,32.297,11,37.011]],[\"comment/8\",[]],[\"name/9\",[0,20.984,10,26.392,12,30.244,13,27.922]],[\"comment/9\",[]],[\"name/10\",[0,25.679,14,37.011,15,37.011]],[\"comment/10\",[]],[\"name/11\",[16,66.988]],[\"comment/11\",[]],[\"name/12\",[17,30.271]],[\"comment/12\",[]],[\"name/13\",[18,66.988]],[\"comment/13\",[]],[\"name/14\",[19,66.988]],[\"comment/14\",[]],[\"name/15\",[20,66.988]],[\"comment/15\",[]],[\"name/16\",[21,66.988]],[\"comment/16\",[]],[\"name/17\",[22,61.845]],[\"comment/17\",[]],[\"name/18\",[23,49.521]],[\"comment/18\",[]],[\"name/19\",[24,66.988]],[\"comment/19\",[]],[\"name/20\",[17,30.271]],[\"comment/20\",[]],[\"name/21\",[25,66.988]],[\"comment/21\",[]],[\"name/22\",[23,49.521]],[\"comment/22\",[]],[\"name/23\",[26,66.988]],[\"comment/23\",[]],[\"name/24\",[27,66.988]],[\"comment/24\",[]],[\"name/25\",[17,30.271]],[\"comment/25\",[]],[\"name/26\",[28,66.988]],[\"comment/26\",[]],[\"name/27\",[23,49.521]],[\"comment/27\",[]],[\"name/28\",[29,66.988]],[\"comment/28\",[]],[\"name/29\",[23,49.521]],[\"comment/29\",[]],[\"name/30\",[30,66.988]],[\"comment/30\",[]],[\"name/31\",[31,46.477]],[\"comment/31\",[]],[\"name/32\",[32,66.988]],[\"comment/32\",[]],[\"name/33\",[33,34.31]],[\"comment/33\",[]],[\"name/34\",[34,66.988]],[\"comment/34\",[]],[\"name/35\",[35,66.988]],[\"comment/35\",[]],[\"name/36\",[17,30.271]],[\"comment/36\",[]],[\"name/37\",[36,55.926]],[\"comment/37\",[]],[\"name/38\",[23,49.521]],[\"comment/38\",[]],[\"name/39\",[37,66.988]],[\"comment/39\",[]],[\"name/40\",[17,30.271]],[\"comment/40\",[]],[\"name/41\",[38,66.988]],[\"comment/41\",[]],[\"name/42\",[39,61.845]],[\"comment/42\",[]],[\"name/43\",[40,61.845]],[\"comment/43\",[]],[\"name/44\",[41,61.845]],[\"comment/44\",[]],[\"name/45\",[42,61.845]],[\"comment/45\",[]],[\"name/46\",[23,49.521]],[\"comment/46\",[]],[\"name/47\",[43,61.845]],[\"comment/47\",[]],[\"name/48\",[44,61.845]],[\"comment/48\",[]],[\"name/49\",[45,61.845]],[\"comment/49\",[]],[\"name/50\",[46,61.845]],[\"comment/50\",[]],[\"name/51\",[47,61.845]],[\"comment/51\",[]],[\"name/52\",[48,61.845]],[\"comment/52\",[]],[\"name/53\",[49,66.988]],[\"comment/53\",[]],[\"name/54\",[50,61.845]],[\"comment/54\",[]],[\"name/55\",[51,61.845]],[\"comment/55\",[]],[\"name/56\",[52,66.988]],[\"comment/56\",[]],[\"name/57\",[53,37.339]],[\"comment/57\",[]],[\"name/58\",[54,66.988]],[\"comment/58\",[]],[\"name/59\",[53,37.339]],[\"comment/59\",[]],[\"name/60\",[55,66.988]],[\"comment/60\",[]],[\"name/61\",[56,66.988]],[\"comment/61\",[]],[\"name/62\",[53,37.339]],[\"comment/62\",[]],[\"name/63\",[57,66.988]],[\"comment/63\",[]],[\"name/64\",[58,66.988]],[\"comment/64\",[]],[\"name/65\",[59,66.988]],[\"comment/65\",[]],[\"name/66\",[60,66.988]],[\"comment/66\",[]],[\"name/67\",[53,37.339]],[\"comment/67\",[]],[\"name/68\",[61,66.988]],[\"comment/68\",[]],[\"name/69\",[62,61.845]],[\"comment/69\",[]],[\"name/70\",[63,55.926]],[\"comment/70\",[]],[\"name/71\",[64,66.988]],[\"comment/71\",[]],[\"name/72\",[53,37.339]],[\"comment/72\",[]],[\"name/73\",[65,66.988]],[\"comment/73\",[]],[\"name/74\",[66,61.845]],[\"comment/74\",[]],[\"name/75\",[67,66.988]],[\"comment/75\",[]],[\"name/76\",[68,66.988]],[\"comment/76\",[]],[\"name/77\",[69,61.845]],[\"comment/77\",[]],[\"name/78\",[53,37.339]],[\"comment/78\",[]],[\"name/79\",[70,66.988]],[\"comment/79\",[]],[\"name/80\",[71,66.988]],[\"comment/80\",[]],[\"name/81\",[69,61.845]],[\"comment/81\",[]],[\"name/82\",[72,66.988]],[\"comment/82\",[]],[\"name/83\",[73,66.988]],[\"comment/83\",[]],[\"name/84\",[74,66.988]],[\"comment/84\",[]],[\"name/85\",[75,66.988]],[\"comment/85\",[]],[\"name/86\",[76,66.988]],[\"comment/86\",[]],[\"name/87\",[77,66.988]],[\"comment/87\",[]],[\"name/88\",[53,37.339]],[\"comment/88\",[]],[\"name/89\",[78,34.31]],[\"comment/89\",[]],[\"name/90\",[79,66.988]],[\"comment/90\",[]],[\"name/91\",[80,61.845]],[\"comment/91\",[]],[\"name/92\",[81,55.926]],[\"comment/92\",[]],[\"name/93\",[17,30.271]],[\"comment/93\",[]],[\"name/94\",[81,55.926]],[\"comment/94\",[]],[\"name/95\",[82,66.988]],[\"comment/95\",[]],[\"name/96\",[80,61.845]],[\"comment/96\",[]],[\"name/97\",[83,66.988]],[\"comment/97\",[]],[\"name/98\",[84,66.988]],[\"comment/98\",[]],[\"name/99\",[63,55.926]],[\"comment/99\",[]],[\"name/100\",[85,66.988]],[\"comment/100\",[]],[\"name/101\",[86,61.845]],[\"comment/101\",[]],[\"name/102\",[87,66.988]],[\"comment/102\",[]],[\"name/103\",[88,66.988]],[\"comment/103\",[]],[\"name/104\",[89,66.988]],[\"comment/104\",[]],[\"name/105\",[90,66.988]],[\"comment/105\",[]],[\"name/106\",[91,66.988]],[\"comment/106\",[]],[\"name/107\",[81,55.926]],[\"comment/107\",[]],[\"name/108\",[92,66.988]],[\"comment/108\",[]],[\"name/109\",[93,66.988]],[\"comment/109\",[]],[\"name/110\",[94,66.988]],[\"comment/110\",[]],[\"name/111\",[95,66.988]],[\"comment/111\",[]],[\"name/112\",[17,30.271]],[\"comment/112\",[]],[\"name/113\",[96,66.988]],[\"comment/113\",[]],[\"name/114\",[97,66.988]],[\"comment/114\",[]],[\"name/115\",[98,66.988]],[\"comment/115\",[]],[\"name/116\",[99,66.988]],[\"comment/116\",[]],[\"name/117\",[100,61.845]],[\"comment/117\",[]],[\"name/118\",[101,66.988]],[\"comment/118\",[]],[\"name/119\",[102,66.988]],[\"comment/119\",[]],[\"name/120\",[103,66.988]],[\"comment/120\",[]],[\"name/121\",[104,66.988]],[\"comment/121\",[]],[\"name/122\",[17,30.271]],[\"comment/122\",[]],[\"name/123\",[105,61.845]],[\"comment/123\",[]],[\"name/124\",[106,66.988]],[\"comment/124\",[]],[\"name/125\",[40,61.845]],[\"comment/125\",[]],[\"name/126\",[41,61.845]],[\"comment/126\",[]],[\"name/127\",[42,61.845]],[\"comment/127\",[]],[\"name/128\",[23,49.521]],[\"comment/128\",[]],[\"name/129\",[43,61.845]],[\"comment/129\",[]],[\"name/130\",[44,61.845]],[\"comment/130\",[]],[\"name/131\",[45,61.845]],[\"comment/131\",[]],[\"name/132\",[46,61.845]],[\"comment/132\",[]],[\"name/133\",[47,61.845]],[\"comment/133\",[]],[\"name/134\",[48,61.845]],[\"comment/134\",[]],[\"name/135\",[107,66.988]],[\"comment/135\",[]],[\"name/136\",[108,66.988]],[\"comment/136\",[]],[\"name/137\",[50,61.845]],[\"comment/137\",[]],[\"name/138\",[51,61.845]],[\"comment/138\",[]],[\"name/139\",[109,66.988]],[\"comment/139\",[]],[\"name/140\",[110,41.69]],[\"comment/140\",[]],[\"name/141\",[111,66.988]],[\"comment/141\",[]],[\"name/142\",[53,37.339]],[\"comment/142\",[]],[\"name/143\",[112,66.988]],[\"comment/143\",[]],[\"name/144\",[113,66.988]],[\"comment/144\",[]],[\"name/145\",[114,48.401]],[\"comment/145\",[]],[\"name/146\",[115,66.988]],[\"comment/146\",[]],[\"name/147\",[116,66.988]],[\"comment/147\",[]],[\"name/148\",[117,61.845]],[\"comment/148\",[]],[\"name/149\",[118,66.988]],[\"comment/149\",[]],[\"name/150\",[17,30.271]],[\"comment/150\",[]],[\"name/151\",[119,61.845]],[\"comment/151\",[]],[\"name/152\",[120,58.456]],[\"comment/152\",[]],[\"name/153\",[121,66.988]],[\"comment/153\",[]],[\"name/154\",[122,61.845]],[\"comment/154\",[]],[\"name/155\",[123,61.845]],[\"comment/155\",[]],[\"name/156\",[124,61.845]],[\"comment/156\",[]],[\"name/157\",[125,61.845]],[\"comment/157\",[]],[\"name/158\",[126,61.845]],[\"comment/158\",[]],[\"name/159\",[127,61.845]],[\"comment/159\",[]],[\"name/160\",[81,55.926]],[\"comment/160\",[]],[\"name/161\",[128,61.845]],[\"comment/161\",[]],[\"name/162\",[129,61.845]],[\"comment/162\",[]],[\"name/163\",[62,61.845]],[\"comment/163\",[]],[\"name/164\",[130,61.845]],[\"comment/164\",[]],[\"name/165\",[119,61.845]],[\"comment/165\",[]],[\"name/166\",[120,58.456]],[\"comment/166\",[]],[\"name/167\",[131,66.988]],[\"comment/167\",[]],[\"name/168\",[122,61.845]],[\"comment/168\",[]],[\"name/169\",[123,61.845]],[\"comment/169\",[]],[\"name/170\",[124,61.845]],[\"comment/170\",[]],[\"name/171\",[125,61.845]],[\"comment/171\",[]],[\"name/172\",[126,61.845]],[\"comment/172\",[]],[\"name/173\",[127,61.845]],[\"comment/173\",[]],[\"name/174\",[132,66.988]],[\"comment/174\",[]],[\"name/175\",[128,61.845]],[\"comment/175\",[]],[\"name/176\",[129,61.845]],[\"comment/176\",[]],[\"name/177\",[133,66.988]],[\"comment/177\",[]],[\"name/178\",[130,61.845]],[\"comment/178\",[]],[\"name/179\",[134,66.988]],[\"comment/179\",[]],[\"name/180\",[135,66.988]],[\"comment/180\",[]],[\"name/181\",[136,66.988]],[\"comment/181\",[]],[\"name/182\",[137,66.988]],[\"comment/182\",[]],[\"name/183\",[138,66.988]],[\"comment/183\",[]],[\"name/184\",[139,66.988]],[\"comment/184\",[]],[\"name/185\",[140,66.988]],[\"comment/185\",[]],[\"name/186\",[141,66.988]],[\"comment/186\",[]],[\"name/187\",[142,55.926]],[\"comment/187\",[]],[\"name/188\",[143,55.926]],[\"comment/188\",[]],[\"name/189\",[117,61.845]],[\"comment/189\",[]],[\"name/190\",[144,66.988]],[\"comment/190\",[]],[\"name/191\",[145,66.988]],[\"comment/191\",[]],[\"name/192\",[17,30.271]],[\"comment/192\",[]],[\"name/193\",[146,58.456]],[\"comment/193\",[]],[\"name/194\",[147,58.456]],[\"comment/194\",[]],[\"name/195\",[148,58.456]],[\"comment/195\",[]],[\"name/196\",[149,58.456]],[\"comment/196\",[]],[\"name/197\",[150,58.456]],[\"comment/197\",[]],[\"name/198\",[151,58.456]],[\"comment/198\",[]],[\"name/199\",[152,53.905]],[\"comment/199\",[]],[\"name/200\",[153,46.477]],[\"comment/200\",[]],[\"name/201\",[154,58.456]],[\"comment/201\",[]],[\"name/202\",[155,58.456]],[\"comment/202\",[]],[\"name/203\",[156,58.456]],[\"comment/203\",[]],[\"name/204\",[78,34.31]],[\"comment/204\",[]],[\"name/205\",[157,58.456]],[\"comment/205\",[]],[\"name/206\",[158,58.456]],[\"comment/206\",[]],[\"name/207\",[159,58.456]],[\"comment/207\",[]],[\"name/208\",[142,55.926]],[\"comment/208\",[]],[\"name/209\",[143,55.926]],[\"comment/209\",[]],[\"name/210\",[160,58.456]],[\"comment/210\",[]],[\"name/211\",[161,58.456]],[\"comment/211\",[]],[\"name/212\",[162,55.926]],[\"comment/212\",[]],[\"name/213\",[163,58.456]],[\"comment/213\",[]],[\"name/214\",[164,58.456]],[\"comment/214\",[]],[\"name/215\",[165,58.456]],[\"comment/215\",[]],[\"name/216\",[166,58.456]],[\"comment/216\",[]],[\"name/217\",[167,58.456]],[\"comment/217\",[]],[\"name/218\",[168,58.456]],[\"comment/218\",[]],[\"name/219\",[169,58.456]],[\"comment/219\",[]],[\"name/220\",[170,58.456]],[\"comment/220\",[]],[\"name/221\",[171,58.456]],[\"comment/221\",[]],[\"name/222\",[172,58.456]],[\"comment/222\",[]],[\"name/223\",[173,53.905]],[\"comment/223\",[]],[\"name/224\",[174,53.905]],[\"comment/224\",[]],[\"name/225\",[175,53.905]],[\"comment/225\",[]],[\"name/226\",[176,53.905]],[\"comment/226\",[]],[\"name/227\",[162,55.926]],[\"comment/227\",[]],[\"name/228\",[177,66.988]],[\"comment/228\",[]],[\"name/229\",[178,66.988]],[\"comment/229\",[]],[\"name/230\",[179,66.988]],[\"comment/230\",[]],[\"name/231\",[180,66.988]],[\"comment/231\",[]],[\"name/232\",[181,66.988]],[\"comment/232\",[]],[\"name/233\",[182,66.988]],[\"comment/233\",[]],[\"name/234\",[183,66.988]],[\"comment/234\",[]],[\"name/235\",[184,66.988]],[\"comment/235\",[]],[\"name/236\",[185,66.988]],[\"comment/236\",[]],[\"name/237\",[186,66.988]],[\"comment/237\",[]],[\"name/238\",[187,66.988]],[\"comment/238\",[]],[\"name/239\",[188,66.988]],[\"comment/239\",[]],[\"name/240\",[189,66.988]],[\"comment/240\",[]],[\"name/241\",[190,66.988]],[\"comment/241\",[]],[\"name/242\",[191,66.988]],[\"comment/242\",[]],[\"name/243\",[53,37.339]],[\"comment/243\",[]],[\"name/244\",[192,37.698]],[\"comment/244\",[]],[\"name/245\",[193,66.988]],[\"comment/245\",[]],[\"name/246\",[17,30.271]],[\"comment/246\",[]],[\"name/247\",[194,61.845]],[\"comment/247\",[]],[\"name/248\",[195,66.988]],[\"comment/248\",[]],[\"name/249\",[33,34.31]],[\"comment/249\",[]],[\"name/250\",[192,37.698]],[\"comment/250\",[]],[\"name/251\",[196,66.988]],[\"comment/251\",[]],[\"name/252\",[53,37.339]],[\"comment/252\",[]],[\"name/253\",[197,61.845]],[\"comment/253\",[]],[\"name/254\",[198,66.988]],[\"comment/254\",[]],[\"name/255\",[22,61.845]],[\"comment/255\",[]],[\"name/256\",[199,66.988]],[\"comment/256\",[]],[\"name/257\",[200,66.988]],[\"comment/257\",[]],[\"name/258\",[53,37.339]],[\"comment/258\",[]],[\"name/259\",[201,49.521]],[\"comment/259\",[]],[\"name/260\",[202,66.988]],[\"comment/260\",[]],[\"name/261\",[17,30.271]],[\"comment/261\",[]],[\"name/262\",[203,66.988]],[\"comment/262\",[]],[\"name/263\",[204,61.845]],[\"comment/263\",[]],[\"name/264\",[36,55.926]],[\"comment/264\",[]],[\"name/265\",[31,46.477]],[\"comment/265\",[]],[\"name/266\",[33,34.31]],[\"comment/266\",[]],[\"name/267\",[205,50.782]],[\"comment/267\",[]],[\"name/268\",[201,49.521]],[\"comment/268\",[]],[\"name/269\",[206,50.782]],[\"comment/269\",[]],[\"name/270\",[192,37.698]],[\"comment/270\",[]],[\"name/271\",[207,50.782]],[\"comment/271\",[]],[\"name/272\",[208,50.782]],[\"comment/272\",[]],[\"name/273\",[209,66.988]],[\"comment/273\",[]],[\"name/274\",[210,66.988]],[\"comment/274\",[]],[\"name/275\",[17,30.271]],[\"comment/275\",[]],[\"name/276\",[153,46.477]],[\"comment/276\",[]],[\"name/277\",[31,46.477]],[\"comment/277\",[]],[\"name/278\",[78,34.31]],[\"comment/278\",[]],[\"name/279\",[33,34.31]],[\"comment/279\",[]],[\"name/280\",[205,50.782]],[\"comment/280\",[]],[\"name/281\",[201,49.521]],[\"comment/281\",[]],[\"name/282\",[206,50.782]],[\"comment/282\",[]],[\"name/283\",[192,37.698]],[\"comment/283\",[]],[\"name/284\",[207,50.782]],[\"comment/284\",[]],[\"name/285\",[208,50.782]],[\"comment/285\",[]],[\"name/286\",[211,66.988]],[\"comment/286\",[]],[\"name/287\",[212,66.988]],[\"comment/287\",[]],[\"name/288\",[17,30.271]],[\"comment/288\",[]],[\"name/289\",[213,61.845]],[\"comment/289\",[]],[\"name/290\",[214,61.845]],[\"comment/290\",[]],[\"name/291\",[33,34.31]],[\"comment/291\",[]],[\"name/292\",[192,37.698]],[\"comment/292\",[]],[\"name/293\",[215,66.988]],[\"comment/293\",[]],[\"name/294\",[216,66.988]],[\"comment/294\",[]],[\"name/295\",[17,30.271]],[\"comment/295\",[]],[\"name/296\",[217,66.988]],[\"comment/296\",[]],[\"name/297\",[213,61.845]],[\"comment/297\",[]],[\"name/298\",[214,61.845]],[\"comment/298\",[]],[\"name/299\",[23,49.521]],[\"comment/299\",[]],[\"name/300\",[31,46.477]],[\"comment/300\",[]],[\"name/301\",[78,34.31]],[\"comment/301\",[]],[\"name/302\",[33,34.31]],[\"comment/302\",[]],[\"name/303\",[205,50.782]],[\"comment/303\",[]],[\"name/304\",[201,49.521]],[\"comment/304\",[]],[\"name/305\",[206,50.782]],[\"comment/305\",[]],[\"name/306\",[192,37.698]],[\"comment/306\",[]],[\"name/307\",[207,50.782]],[\"comment/307\",[]],[\"name/308\",[208,50.782]],[\"comment/308\",[]],[\"name/309\",[218,66.988]],[\"comment/309\",[]],[\"name/310\",[219,66.988]],[\"comment/310\",[]],[\"name/311\",[220,66.988]],[\"comment/311\",[]],[\"name/312\",[53,37.339]],[\"comment/312\",[]],[\"name/313\",[221,61.845]],[\"comment/313\",[]],[\"name/314\",[222,61.845]],[\"comment/314\",[]],[\"name/315\",[223,61.845]],[\"comment/315\",[]],[\"name/316\",[224,55.926]],[\"comment/316\",[]],[\"name/317\",[225,66.988]],[\"comment/317\",[]],[\"name/318\",[226,66.988]],[\"comment/318\",[]],[\"name/319\",[17,30.271]],[\"comment/319\",[]],[\"name/320\",[227,61.845]],[\"comment/320\",[]],[\"name/321\",[228,61.845]],[\"comment/321\",[]],[\"name/322\",[33,34.31]],[\"comment/322\",[]],[\"name/323\",[192,37.698]],[\"comment/323\",[]],[\"name/324\",[229,66.988]],[\"comment/324\",[]],[\"name/325\",[17,30.271]],[\"comment/325\",[]],[\"name/326\",[227,61.845]],[\"comment/326\",[]],[\"name/327\",[228,61.845]],[\"comment/327\",[]],[\"name/328\",[31,46.477]],[\"comment/328\",[]],[\"name/329\",[78,34.31]],[\"comment/329\",[]],[\"name/330\",[33,34.31]],[\"comment/330\",[]],[\"name/331\",[205,50.782]],[\"comment/331\",[]],[\"name/332\",[201,49.521]],[\"comment/332\",[]],[\"name/333\",[206,50.782]],[\"comment/333\",[]],[\"name/334\",[192,37.698]],[\"comment/334\",[]],[\"name/335\",[207,50.782]],[\"comment/335\",[]],[\"name/336\",[208,50.782]],[\"comment/336\",[]],[\"name/337\",[230,55.926]],[\"comment/337\",[]],[\"name/338\",[231,66.988]],[\"comment/338\",[]],[\"name/339\",[53,37.339]],[\"comment/339\",[]],[\"name/340\",[197,61.845]],[\"comment/340\",[]],[\"name/341\",[232,50.782]],[\"comment/341\",[]],[\"name/342\",[63,55.926]],[\"comment/342\",[]],[\"name/343\",[233,66.988]],[\"comment/343\",[]],[\"name/344\",[234,61.845]],[\"comment/344\",[]],[\"name/345\",[17,30.271]],[\"comment/345\",[]],[\"name/346\",[235,66.988]],[\"comment/346\",[]],[\"name/347\",[236,66.988]],[\"comment/347\",[]],[\"name/348\",[232,50.782]],[\"comment/348\",[]],[\"name/349\",[237,66.988]],[\"comment/349\",[]],[\"name/350\",[238,53.905]],[\"comment/350\",[]],[\"name/351\",[239,66.988]],[\"comment/351\",[]],[\"name/352\",[240,66.988]],[\"comment/352\",[]],[\"name/353\",[241,66.988]],[\"comment/353\",[]],[\"name/354\",[242,58.456]],[\"comment/354\",[]],[\"name/355\",[243,58.456]],[\"comment/355\",[]],[\"name/356\",[244,66.988]],[\"comment/356\",[]],[\"name/357\",[245,52.223]],[\"comment/357\",[]],[\"name/358\",[246,52.223]],[\"comment/358\",[]],[\"name/359\",[110,41.69]],[\"comment/359\",[]],[\"name/360\",[205,50.782]],[\"comment/360\",[]],[\"name/361\",[31,46.477]],[\"comment/361\",[]],[\"name/362\",[33,34.31]],[\"comment/362\",[]],[\"name/363\",[201,49.521]],[\"comment/363\",[]],[\"name/364\",[206,50.782]],[\"comment/364\",[]],[\"name/365\",[192,37.698]],[\"comment/365\",[]],[\"name/366\",[207,50.782]],[\"comment/366\",[]],[\"name/367\",[208,50.782]],[\"comment/367\",[]],[\"name/368\",[234,61.845]],[\"comment/368\",[]],[\"name/369\",[247,66.988]],[\"comment/369\",[]],[\"name/370\",[248,66.988]],[\"comment/370\",[]],[\"name/371\",[249,61.845]],[\"comment/371\",[]],[\"name/372\",[249,61.845]],[\"comment/372\",[]],[\"name/373\",[250,66.988]],[\"comment/373\",[]],[\"name/374\",[251,66.988]],[\"comment/374\",[]],[\"name/375\",[252,66.988]],[\"comment/375\",[]],[\"name/376\",[253,66.988]],[\"comment/376\",[]],[\"name/377\",[17,30.271]],[\"comment/377\",[]],[\"name/378\",[254,66.988]],[\"comment/378\",[]],[\"name/379\",[232,50.782]],[\"comment/379\",[]],[\"name/380\",[245,52.223]],[\"comment/380\",[]],[\"name/381\",[246,52.223]],[\"comment/381\",[]],[\"name/382\",[110,41.69]],[\"comment/382\",[]],[\"name/383\",[33,34.31]],[\"comment/383\",[]],[\"name/384\",[192,37.698]],[\"comment/384\",[]],[\"name/385\",[255,66.988]],[\"comment/385\",[]],[\"name/386\",[256,66.988]],[\"comment/386\",[]],[\"name/387\",[17,30.271]],[\"comment/387\",[]],[\"name/388\",[257,58.456]],[\"comment/388\",[]],[\"name/389\",[258,58.456]],[\"comment/389\",[]],[\"name/390\",[259,53.905]],[\"comment/390\",[]],[\"name/391\",[33,34.31]],[\"comment/391\",[]],[\"name/392\",[192,37.698]],[\"comment/392\",[]],[\"name/393\",[260,66.988]],[\"comment/393\",[]],[\"name/394\",[261,66.988]],[\"comment/394\",[]],[\"name/395\",[17,30.271]],[\"comment/395\",[]],[\"name/396\",[257,58.456]],[\"comment/396\",[]],[\"name/397\",[258,58.456]],[\"comment/397\",[]],[\"name/398\",[259,53.905]],[\"comment/398\",[]],[\"name/399\",[31,46.477]],[\"comment/399\",[]],[\"name/400\",[78,34.31]],[\"comment/400\",[]],[\"name/401\",[33,34.31]],[\"comment/401\",[]],[\"name/402\",[205,50.782]],[\"comment/402\",[]],[\"name/403\",[201,49.521]],[\"comment/403\",[]],[\"name/404\",[206,50.782]],[\"comment/404\",[]],[\"name/405\",[192,37.698]],[\"comment/405\",[]],[\"name/406\",[207,50.782]],[\"comment/406\",[]],[\"name/407\",[208,50.782]],[\"comment/407\",[]],[\"name/408\",[262,58.456]],[\"comment/408\",[]],[\"name/409\",[263,66.988]],[\"comment/409\",[]],[\"name/410\",[53,37.339]],[\"comment/410\",[]],[\"name/411\",[221,61.845]],[\"comment/411\",[]],[\"name/412\",[264,61.845]],[\"comment/412\",[]],[\"name/413\",[222,61.845]],[\"comment/413\",[]],[\"name/414\",[223,61.845]],[\"comment/414\",[]],[\"name/415\",[224,55.926]],[\"comment/415\",[]],[\"name/416\",[120,58.456]],[\"comment/416\",[]],[\"name/417\",[265,66.988]],[\"comment/417\",[]],[\"name/418\",[53,37.339]],[\"comment/418\",[]],[\"name/419\",[266,66.988]],[\"comment/419\",[]],[\"name/420\",[267,66.988]],[\"comment/420\",[]],[\"name/421\",[224,55.926]],[\"comment/421\",[]],[\"name/422\",[268,66.988]],[\"comment/422\",[]],[\"name/423\",[264,61.845]],[\"comment/423\",[]],[\"name/424\",[230,55.926]],[\"comment/424\",[]],[\"name/425\",[269,66.988]],[\"comment/425\",[]],[\"name/426\",[270,66.988]],[\"comment/426\",[]],[\"name/427\",[271,66.988]],[\"comment/427\",[]],[\"name/428\",[17,30.271]],[\"comment/428\",[]],[\"name/429\",[272,66.988]],[\"comment/429\",[]],[\"name/430\",[273,61.845]],[\"comment/430\",[]],[\"name/431\",[274,66.988]],[\"comment/431\",[]],[\"name/432\",[275,66.988]],[\"comment/432\",[]],[\"name/433\",[276,66.988]],[\"comment/433\",[]],[\"name/434\",[277,66.988]],[\"comment/434\",[]],[\"name/435\",[278,61.845]],[\"comment/435\",[]],[\"name/436\",[17,30.271]],[\"comment/436\",[]],[\"name/437\",[153,46.477]],[\"comment/437\",[]],[\"name/438\",[273,61.845]],[\"comment/438\",[]],[\"name/439\",[279,55.926]],[\"comment/439\",[]],[\"name/440\",[280,61.845]],[\"comment/440\",[]],[\"name/441\",[78,34.31]],[\"comment/441\",[]],[\"name/442\",[281,61.845]],[\"comment/442\",[]],[\"name/443\",[17,30.271]],[\"comment/443\",[]],[\"name/444\",[282,61.845]],[\"comment/444\",[]],[\"name/445\",[152,53.905]],[\"comment/445\",[]],[\"name/446\",[262,58.456]],[\"comment/446\",[]],[\"name/447\",[230,55.926]],[\"comment/447\",[]],[\"name/448\",[242,58.456]],[\"comment/448\",[]],[\"name/449\",[243,58.456]],[\"comment/449\",[]],[\"name/450\",[283,61.845]],[\"comment/450\",[]],[\"name/451\",[259,53.905]],[\"comment/451\",[]],[\"name/452\",[110,41.69]],[\"comment/452\",[]],[\"name/453\",[173,53.905]],[\"comment/453\",[]],[\"name/454\",[174,53.905]],[\"comment/454\",[]],[\"name/455\",[175,53.905]],[\"comment/455\",[]],[\"name/456\",[176,53.905]],[\"comment/456\",[]],[\"name/457\",[279,55.926]],[\"comment/457\",[]],[\"name/458\",[280,61.845]],[\"comment/458\",[]],[\"name/459\",[78,34.31]],[\"comment/459\",[]],[\"name/460\",[284,66.988]],[\"comment/460\",[]],[\"name/461\",[285,66.988]],[\"comment/461\",[]],[\"name/462\",[17,30.271]],[\"comment/462\",[]],[\"name/463\",[286,58.456]],[\"comment/463\",[]],[\"name/464\",[287,66.988]],[\"comment/464\",[]],[\"name/465\",[288,66.988]],[\"comment/465\",[]],[\"name/466\",[289,66.988]],[\"comment/466\",[]],[\"name/467\",[290,66.988]],[\"comment/467\",[]],[\"name/468\",[291,66.988]],[\"comment/468\",[]],[\"name/469\",[292,66.988]],[\"comment/469\",[]],[\"name/470\",[293,66.988]],[\"comment/470\",[]],[\"name/471\",[294,66.988]],[\"comment/471\",[]],[\"name/472\",[295,66.988]],[\"comment/472\",[]],[\"name/473\",[296,66.988]],[\"comment/473\",[]],[\"name/474\",[297,66.988]],[\"comment/474\",[]],[\"name/475\",[298,58.456]],[\"comment/475\",[]],[\"name/476\",[245,52.223]],[\"comment/476\",[]],[\"name/477\",[246,52.223]],[\"comment/477\",[]],[\"name/478\",[110,41.69]],[\"comment/478\",[]],[\"name/479\",[299,66.988]],[\"comment/479\",[]],[\"name/480\",[300,66.988]],[\"comment/480\",[]],[\"name/481\",[301,66.988]],[\"comment/481\",[]],[\"name/482\",[302,66.988]],[\"comment/482\",[]],[\"name/483\",[232,50.782]],[\"comment/483\",[]],[\"name/484\",[33,34.31]],[\"comment/484\",[]],[\"name/485\",[192,37.698]],[\"comment/485\",[]],[\"name/486\",[303,66.988]],[\"comment/486\",[]],[\"name/487\",[304,66.988]],[\"comment/487\",[]],[\"name/488\",[17,30.271]],[\"comment/488\",[]],[\"name/489\",[305,66.988]],[\"comment/489\",[]],[\"name/490\",[306,66.988]],[\"comment/490\",[]],[\"name/491\",[307,66.988]],[\"comment/491\",[]],[\"name/492\",[308,66.988]],[\"comment/492\",[]],[\"name/493\",[309,66.988]],[\"comment/493\",[]],[\"name/494\",[310,66.988]],[\"comment/494\",[]],[\"name/495\",[245,52.223]],[\"comment/495\",[]],[\"name/496\",[246,52.223]],[\"comment/496\",[]],[\"name/497\",[110,41.69]],[\"comment/497\",[]],[\"name/498\",[311,66.988]],[\"comment/498\",[]],[\"name/499\",[312,66.988]],[\"comment/499\",[]],[\"name/500\",[232,50.782]],[\"comment/500\",[]],[\"name/501\",[33,34.31]],[\"comment/501\",[]],[\"name/502\",[192,37.698]],[\"comment/502\",[]],[\"name/503\",[313,66.988]],[\"comment/503\",[]],[\"name/504\",[314,66.988]],[\"comment/504\",[]],[\"name/505\",[17,30.271]],[\"comment/505\",[]],[\"name/506\",[315,66.988]],[\"comment/506\",[]],[\"name/507\",[286,58.456]],[\"comment/507\",[]],[\"name/508\",[105,61.845]],[\"comment/508\",[]],[\"name/509\",[316,66.988]],[\"comment/509\",[]],[\"name/510\",[317,66.988]],[\"comment/510\",[]],[\"name/511\",[318,66.988]],[\"comment/511\",[]],[\"name/512\",[298,58.456]],[\"comment/512\",[]],[\"name/513\",[319,66.988]],[\"comment/513\",[]],[\"name/514\",[245,52.223]],[\"comment/514\",[]],[\"name/515\",[246,52.223]],[\"comment/515\",[]],[\"name/516\",[110,41.69]],[\"comment/516\",[]],[\"name/517\",[320,66.988]],[\"comment/517\",[]],[\"name/518\",[232,50.782]],[\"comment/518\",[]],[\"name/519\",[33,34.31]],[\"comment/519\",[]],[\"name/520\",[192,37.698]],[\"comment/520\",[]],[\"name/521\",[278,61.845]],[\"comment/521\",[]],[\"name/522\",[17,30.271]],[\"comment/522\",[]],[\"name/523\",[153,46.477]],[\"comment/523\",[]],[\"name/524\",[279,55.926]],[\"comment/524\",[]],[\"name/525\",[321,61.845]],[\"comment/525\",[]],[\"name/526\",[78,34.31]],[\"comment/526\",[]],[\"name/527\",[110,41.69]],[\"comment/527\",[]],[\"name/528\",[281,61.845]],[\"comment/528\",[]],[\"name/529\",[17,30.271]],[\"comment/529\",[]],[\"name/530\",[282,61.845]],[\"comment/530\",[]],[\"name/531\",[152,53.905]],[\"comment/531\",[]],[\"name/532\",[262,58.456]],[\"comment/532\",[]],[\"name/533\",[230,55.926]],[\"comment/533\",[]],[\"name/534\",[242,58.456]],[\"comment/534\",[]],[\"name/535\",[243,58.456]],[\"comment/535\",[]],[\"name/536\",[283,61.845]],[\"comment/536\",[]],[\"name/537\",[259,53.905]],[\"comment/537\",[]],[\"name/538\",[173,53.905]],[\"comment/538\",[]],[\"name/539\",[174,53.905]],[\"comment/539\",[]],[\"name/540\",[175,53.905]],[\"comment/540\",[]],[\"name/541\",[176,53.905]],[\"comment/541\",[]],[\"name/542\",[279,55.926]],[\"comment/542\",[]],[\"name/543\",[321,61.845]],[\"comment/543\",[]],[\"name/544\",[78,34.31]],[\"comment/544\",[]],[\"name/545\",[110,41.69]],[\"comment/545\",[]],[\"name/546\",[322,66.988]],[\"comment/546\",[]],[\"name/547\",[17,30.271]],[\"comment/547\",[]],[\"name/548\",[323,66.988]],[\"comment/548\",[]],[\"name/549\",[324,66.988]],[\"comment/549\",[]],[\"name/550\",[53,37.339]],[\"comment/550\",[]],[\"name/551\",[325,50.782]],[\"comment/551\",[]],[\"name/552\",[114,48.401]],[\"comment/552\",[]],[\"name/553\",[326,52.223]],[\"comment/553\",[]],[\"name/554\",[327,61.845]],[\"comment/554\",[]],[\"name/555\",[328,61.845]],[\"comment/555\",[]],[\"name/556\",[329,61.845]],[\"comment/556\",[]],[\"name/557\",[330,66.988]],[\"comment/557\",[]],[\"name/558\",[331,66.988]],[\"comment/558\",[]],[\"name/559\",[17,30.271]],[\"comment/559\",[]],[\"name/560\",[332,61.845]],[\"comment/560\",[]],[\"name/561\",[333,52.223]],[\"comment/561\",[]],[\"name/562\",[334,53.905]],[\"comment/562\",[]],[\"name/563\",[335,66.988]],[\"comment/563\",[]],[\"name/564\",[336,66.988]],[\"comment/564\",[]],[\"name/565\",[337,66.988]],[\"comment/565\",[]],[\"name/566\",[39,61.845]],[\"comment/566\",[]],[\"name/567\",[338,66.988]],[\"comment/567\",[]],[\"name/568\",[204,61.845]],[\"comment/568\",[]],[\"name/569\",[31,46.477]],[\"comment/569\",[]],[\"name/570\",[325,50.782]],[\"comment/570\",[]],[\"name/571\",[114,48.401]],[\"comment/571\",[]],[\"name/572\",[326,52.223]],[\"comment/572\",[]],[\"name/573\",[327,61.845]],[\"comment/573\",[]],[\"name/574\",[328,61.845]],[\"comment/574\",[]],[\"name/575\",[329,61.845]],[\"comment/575\",[]],[\"name/576\",[339,66.988]],[\"comment/576\",[]],[\"name/577\",[340,66.988]],[\"comment/577\",[]],[\"name/578\",[341,66.988]],[\"comment/578\",[]],[\"name/579\",[342,66.988]],[\"comment/579\",[]],[\"name/580\",[343,66.988]],[\"comment/580\",[]],[\"name/581\",[17,30.271]],[\"comment/581\",[]],[\"name/582\",[344,61.845]],[\"comment/582\",[]],[\"name/583\",[345,58.456]],[\"comment/583\",[]],[\"name/584\",[153,46.477]],[\"comment/584\",[]],[\"name/585\",[31,46.477]],[\"comment/585\",[]],[\"name/586\",[346,58.456]],[\"comment/586\",[]],[\"name/587\",[78,34.31]],[\"comment/587\",[]],[\"name/588\",[257,58.456]],[\"comment/588\",[]],[\"name/589\",[258,58.456]],[\"comment/589\",[]],[\"name/590\",[259,53.905]],[\"comment/590\",[]],[\"name/591\",[110,41.69]],[\"comment/591\",[]],[\"name/592\",[347,66.988]],[\"comment/592\",[]],[\"name/593\",[348,66.988]],[\"comment/593\",[]],[\"name/594\",[349,66.988]],[\"comment/594\",[]],[\"name/595\",[33,34.31]],[\"comment/595\",[]],[\"name/596\",[192,37.698]],[\"comment/596\",[]],[\"name/597\",[350,66.988]],[\"comment/597\",[]],[\"name/598\",[351,66.988]],[\"comment/598\",[]],[\"name/599\",[17,30.271]],[\"comment/599\",[]],[\"name/600\",[286,58.456]],[\"comment/600\",[]],[\"name/601\",[344,61.845]],[\"comment/601\",[]],[\"name/602\",[345,58.456]],[\"comment/602\",[]],[\"name/603\",[31,46.477]],[\"comment/603\",[]],[\"name/604\",[346,58.456]],[\"comment/604\",[]],[\"name/605\",[352,66.988]],[\"comment/605\",[]],[\"name/606\",[298,58.456]],[\"comment/606\",[]],[\"name/607\",[245,52.223]],[\"comment/607\",[]],[\"name/608\",[246,52.223]],[\"comment/608\",[]],[\"name/609\",[110,41.69]],[\"comment/609\",[]],[\"name/610\",[353,66.988]],[\"comment/610\",[]],[\"name/611\",[354,66.988]],[\"comment/611\",[]],[\"name/612\",[232,50.782]],[\"comment/612\",[]],[\"name/613\",[33,34.31]],[\"comment/613\",[]],[\"name/614\",[192,37.698]],[\"comment/614\",[]],[\"name/615\",[355,66.988]],[\"comment/615\",[]],[\"name/616\",[53,37.339]],[\"comment/616\",[]],[\"name/617\",[356,61.845]],[\"comment/617\",[]],[\"name/618\",[357,61.845]],[\"comment/618\",[]],[\"name/619\",[358,61.845]],[\"comment/619\",[]],[\"name/620\",[359,61.845]],[\"comment/620\",[]],[\"name/621\",[360,61.845]],[\"comment/621\",[]],[\"name/622\",[361,43.472]],[\"comment/622\",[]],[\"name/623\",[362,66.988]],[\"comment/623\",[]],[\"name/624\",[363,66.988]],[\"comment/624\",[]],[\"name/625\",[17,30.271]],[\"comment/625\",[]],[\"name/626\",[356,61.845]],[\"comment/626\",[]],[\"name/627\",[357,61.845]],[\"comment/627\",[]],[\"name/628\",[358,61.845]],[\"comment/628\",[]],[\"name/629\",[359,61.845]],[\"comment/629\",[]],[\"name/630\",[360,61.845]],[\"comment/630\",[]],[\"name/631\",[86,61.845]],[\"comment/631\",[]],[\"name/632\",[364,66.988]],[\"comment/632\",[]],[\"name/633\",[53,37.339]],[\"comment/633\",[]],[\"name/634\",[365,55.926]],[\"comment/634\",[]],[\"name/635\",[366,53.905]],[\"comment/635\",[]],[\"name/636\",[367,55.926]],[\"comment/636\",[]],[\"name/637\",[368,52.223]],[\"comment/637\",[]],[\"name/638\",[78,34.31]],[\"comment/638\",[]],[\"name/639\",[369,53.905]],[\"comment/639\",[]],[\"name/640\",[370,53.905]],[\"comment/640\",[]],[\"name/641\",[371,53.905]],[\"comment/641\",[]],[\"name/642\",[372,66.988]],[\"comment/642\",[]],[\"name/643\",[17,30.271]],[\"comment/643\",[]],[\"name/644\",[153,46.477]],[\"comment/644\",[]],[\"name/645\",[194,61.845]],[\"comment/645\",[]],[\"name/646\",[33,34.31]],[\"comment/646\",[]],[\"name/647\",[78,34.31]],[\"comment/647\",[]],[\"name/648\",[365,55.926]],[\"comment/648\",[]],[\"name/649\",[369,53.905]],[\"comment/649\",[]],[\"name/650\",[370,53.905]],[\"comment/650\",[]],[\"name/651\",[371,53.905]],[\"comment/651\",[]],[\"name/652\",[366,53.905]],[\"comment/652\",[]],[\"name/653\",[368,52.223]],[\"comment/653\",[]],[\"name/654\",[367,55.926]],[\"comment/654\",[]],[\"name/655\",[373,58.456]],[\"comment/655\",[]],[\"name/656\",[374,58.456]],[\"comment/656\",[]],[\"name/657\",[375,47.394]],[\"comment/657\",[]],[\"name/658\",[376,58.456]],[\"comment/658\",[]],[\"name/659\",[377,66.988]],[\"comment/659\",[]],[\"name/660\",[53,37.339]],[\"comment/660\",[]],[\"name/661\",[366,53.905]],[\"comment/661\",[]],[\"name/662\",[369,53.905]],[\"comment/662\",[]],[\"name/663\",[370,53.905]],[\"comment/663\",[]],[\"name/664\",[371,53.905]],[\"comment/664\",[]],[\"name/665\",[378,66.988]],[\"comment/665\",[]],[\"name/666\",[379,66.988]],[\"comment/666\",[]],[\"name/667\",[17,30.271]],[\"comment/667\",[]],[\"name/668\",[153,46.477]],[\"comment/668\",[]],[\"name/669\",[380,61.845]],[\"comment/669\",[]],[\"name/670\",[78,34.31]],[\"comment/670\",[]],[\"name/671\",[361,43.472]],[\"comment/671\",[]],[\"name/672\",[381,47.394]],[\"comment/672\",[]],[\"name/673\",[33,34.31]],[\"comment/673\",[]],[\"name/674\",[192,37.698]],[\"comment/674\",[]],[\"name/675\",[382,66.988]],[\"comment/675\",[]],[\"name/676\",[53,37.339]],[\"comment/676\",[]],[\"name/677\",[78,34.31]],[\"comment/677\",[]],[\"name/678\",[361,43.472]],[\"comment/678\",[]],[\"name/679\",[383,49.521]],[\"comment/679\",[]],[\"name/680\",[384,66.988]],[\"comment/680\",[]],[\"name/681\",[17,30.271]],[\"comment/681\",[]],[\"name/682\",[36,55.926]],[\"comment/682\",[]],[\"name/683\",[380,61.845]],[\"comment/683\",[]],[\"name/684\",[153,46.477]],[\"comment/684\",[]],[\"name/685\",[33,34.31]],[\"comment/685\",[]],[\"name/686\",[383,49.521]],[\"comment/686\",[]],[\"name/687\",[385,50.782]],[\"comment/687\",[]],[\"name/688\",[78,34.31]],[\"comment/688\",[]],[\"name/689\",[375,47.394]],[\"comment/689\",[]],[\"name/690\",[110,41.69]],[\"comment/690\",[]],[\"name/691\",[386,66.988]],[\"comment/691\",[]],[\"name/692\",[387,66.988]],[\"comment/692\",[]],[\"name/693\",[17,30.271]],[\"comment/693\",[]],[\"name/694\",[388,66.988]],[\"comment/694\",[]],[\"name/695\",[361,43.472]],[\"comment/695\",[]],[\"name/696\",[205,50.782]],[\"comment/696\",[]],[\"name/697\",[381,47.394]],[\"comment/697\",[]],[\"name/698\",[31,46.477]],[\"comment/698\",[]],[\"name/699\",[78,34.31]],[\"comment/699\",[]],[\"name/700\",[33,34.31]],[\"comment/700\",[]],[\"name/701\",[201,49.521]],[\"comment/701\",[]],[\"name/702\",[206,50.782]],[\"comment/702\",[]],[\"name/703\",[192,37.698]],[\"comment/703\",[]],[\"name/704\",[207,50.782]],[\"comment/704\",[]],[\"name/705\",[208,50.782]],[\"comment/705\",[]],[\"name/706\",[389,66.988]],[\"comment/706\",[]],[\"name/707\",[390,66.988]],[\"comment/707\",[]],[\"name/708\",[391,66.988]],[\"comment/708\",[]],[\"name/709\",[392,66.988]],[\"comment/709\",[]],[\"name/710\",[17,30.271]],[\"comment/710\",[]],[\"name/711\",[366,53.905]],[\"comment/711\",[]],[\"name/712\",[368,52.223]],[\"comment/712\",[]],[\"name/713\",[367,55.926]],[\"comment/713\",[]],[\"name/714\",[373,58.456]],[\"comment/714\",[]],[\"name/715\",[374,58.456]],[\"comment/715\",[]],[\"name/716\",[375,47.394]],[\"comment/716\",[]],[\"name/717\",[376,58.456]],[\"comment/717\",[]],[\"name/718\",[33,34.31]],[\"comment/718\",[]],[\"name/719\",[78,34.31]],[\"comment/719\",[]],[\"name/720\",[365,55.926]],[\"comment/720\",[]],[\"name/721\",[369,53.905]],[\"comment/721\",[]],[\"name/722\",[370,53.905]],[\"comment/722\",[]],[\"name/723\",[371,53.905]],[\"comment/723\",[]],[\"name/724\",[393,66.988]],[\"comment/724\",[]],[\"name/725\",[17,30.271]],[\"comment/725\",[]],[\"name/726\",[146,58.456]],[\"comment/726\",[]],[\"name/727\",[394,61.845]],[\"comment/727\",[]],[\"name/728\",[395,61.845]],[\"comment/728\",[]],[\"name/729\",[396,61.845]],[\"comment/729\",[]],[\"name/730\",[397,61.845]],[\"comment/730\",[]],[\"name/731\",[368,52.223]],[\"comment/731\",[]],[\"name/732\",[398,61.845]],[\"comment/732\",[]],[\"name/733\",[399,66.988]],[\"comment/733\",[]],[\"name/734\",[400,66.988]],[\"comment/734\",[]],[\"name/735\",[160,58.456]],[\"comment/735\",[]],[\"name/736\",[147,58.456]],[\"comment/736\",[]],[\"name/737\",[148,58.456]],[\"comment/737\",[]],[\"name/738\",[149,58.456]],[\"comment/738\",[]],[\"name/739\",[150,58.456]],[\"comment/739\",[]],[\"name/740\",[151,58.456]],[\"comment/740\",[]],[\"name/741\",[152,53.905]],[\"comment/741\",[]],[\"name/742\",[153,46.477]],[\"comment/742\",[]],[\"name/743\",[154,58.456]],[\"comment/743\",[]],[\"name/744\",[155,58.456]],[\"comment/744\",[]],[\"name/745\",[156,58.456]],[\"comment/745\",[]],[\"name/746\",[78,34.31]],[\"comment/746\",[]],[\"name/747\",[157,58.456]],[\"comment/747\",[]],[\"name/748\",[158,58.456]],[\"comment/748\",[]],[\"name/749\",[159,58.456]],[\"comment/749\",[]],[\"name/750\",[142,55.926]],[\"comment/750\",[]],[\"name/751\",[143,55.926]],[\"comment/751\",[]],[\"name/752\",[161,58.456]],[\"comment/752\",[]],[\"name/753\",[162,55.926]],[\"comment/753\",[]],[\"name/754\",[163,58.456]],[\"comment/754\",[]],[\"name/755\",[164,58.456]],[\"comment/755\",[]],[\"name/756\",[165,58.456]],[\"comment/756\",[]],[\"name/757\",[166,58.456]],[\"comment/757\",[]],[\"name/758\",[167,58.456]],[\"comment/758\",[]],[\"name/759\",[168,58.456]],[\"comment/759\",[]],[\"name/760\",[169,58.456]],[\"comment/760\",[]],[\"name/761\",[170,58.456]],[\"comment/761\",[]],[\"name/762\",[171,58.456]],[\"comment/762\",[]],[\"name/763\",[172,58.456]],[\"comment/763\",[]],[\"name/764\",[173,53.905]],[\"comment/764\",[]],[\"name/765\",[174,53.905]],[\"comment/765\",[]],[\"name/766\",[175,53.905]],[\"comment/766\",[]],[\"name/767\",[176,53.905]],[\"comment/767\",[]],[\"name/768\",[401,66.988]],[\"comment/768\",[]],[\"name/769\",[402,66.988]],[\"comment/769\",[]],[\"name/770\",[403,66.988]],[\"comment/770\",[]],[\"name/771\",[17,30.271]],[\"comment/771\",[]],[\"name/772\",[332,61.845]],[\"comment/772\",[]],[\"name/773\",[404,61.845]],[\"comment/773\",[]],[\"name/774\",[405,66.988]],[\"comment/774\",[]],[\"name/775\",[100,61.845]],[\"comment/775\",[]],[\"name/776\",[325,50.782]],[\"comment/776\",[]],[\"name/777\",[406,50.782]],[\"comment/777\",[]],[\"name/778\",[407,50.782]],[\"comment/778\",[]],[\"name/779\",[408,55.926]],[\"comment/779\",[]],[\"name/780\",[409,55.926]],[\"comment/780\",[]],[\"name/781\",[410,49.521]],[\"comment/781\",[]],[\"name/782\",[78,34.31]],[\"comment/782\",[]],[\"name/783\",[361,43.472]],[\"comment/783\",[]],[\"name/784\",[381,47.394]],[\"comment/784\",[]],[\"name/785\",[33,34.31]],[\"comment/785\",[]],[\"name/786\",[192,37.698]],[\"comment/786\",[]],[\"name/787\",[411,66.988]],[\"comment/787\",[]],[\"name/788\",[412,66.988]],[\"comment/788\",[]],[\"name/789\",[17,30.271]],[\"comment/789\",[]],[\"name/790\",[413,66.988]],[\"comment/790\",[]],[\"name/791\",[404,61.845]],[\"comment/791\",[]],[\"name/792\",[414,66.988]],[\"comment/792\",[]],[\"name/793\",[361,43.472]],[\"comment/793\",[]],[\"name/794\",[406,50.782]],[\"comment/794\",[]],[\"name/795\",[407,50.782]],[\"comment/795\",[]],[\"name/796\",[383,49.521]],[\"comment/796\",[]],[\"name/797\",[375,47.394]],[\"comment/797\",[]],[\"name/798\",[415,58.456]],[\"comment/798\",[]],[\"name/799\",[416,58.456]],[\"comment/799\",[]],[\"name/800\",[417,58.456]],[\"comment/800\",[]],[\"name/801\",[110,41.69]],[\"comment/801\",[]],[\"name/802\",[33,34.31]],[\"comment/802\",[]],[\"name/803\",[385,50.782]],[\"comment/803\",[]],[\"name/804\",[78,34.31]],[\"comment/804\",[]],[\"name/805\",[418,66.988]],[\"comment/805\",[]],[\"name/806\",[419,66.988]],[\"comment/806\",[]],[\"name/807\",[17,30.271]],[\"comment/807\",[]],[\"name/808\",[333,52.223]],[\"comment/808\",[]],[\"name/809\",[420,53.905]],[\"comment/809\",[]],[\"name/810\",[421,55.926]],[\"comment/810\",[]],[\"name/811\",[422,55.926]],[\"comment/811\",[]],[\"name/812\",[423,55.926]],[\"comment/812\",[]],[\"name/813\",[114,48.401]],[\"comment/813\",[]],[\"name/814\",[424,52.223]],[\"comment/814\",[]],[\"name/815\",[425,55.926]],[\"comment/815\",[]],[\"name/816\",[426,55.926]],[\"comment/816\",[]],[\"name/817\",[238,53.905]],[\"comment/817\",[]],[\"name/818\",[325,50.782]],[\"comment/818\",[]],[\"name/819\",[381,47.394]],[\"comment/819\",[]],[\"name/820\",[409,55.926]],[\"comment/820\",[]],[\"name/821\",[406,50.782]],[\"comment/821\",[]],[\"name/822\",[407,50.782]],[\"comment/822\",[]],[\"name/823\",[408,55.926]],[\"comment/823\",[]],[\"name/824\",[410,49.521]],[\"comment/824\",[]],[\"name/825\",[78,34.31]],[\"comment/825\",[]],[\"name/826\",[361,43.472]],[\"comment/826\",[]],[\"name/827\",[33,34.31]],[\"comment/827\",[]],[\"name/828\",[192,37.698]],[\"comment/828\",[]],[\"name/829\",[427,66.988]],[\"comment/829\",[]],[\"name/830\",[428,66.988]],[\"comment/830\",[]],[\"name/831\",[17,30.271]],[\"comment/831\",[]],[\"name/832\",[333,52.223]],[\"comment/832\",[]],[\"name/833\",[420,53.905]],[\"comment/833\",[]],[\"name/834\",[421,55.926]],[\"comment/834\",[]],[\"name/835\",[422,55.926]],[\"comment/835\",[]],[\"name/836\",[423,55.926]],[\"comment/836\",[]],[\"name/837\",[114,48.401]],[\"comment/837\",[]],[\"name/838\",[424,52.223]],[\"comment/838\",[]],[\"name/839\",[425,55.926]],[\"comment/839\",[]],[\"name/840\",[426,55.926]],[\"comment/840\",[]],[\"name/841\",[238,53.905]],[\"comment/841\",[]],[\"name/842\",[110,41.69]],[\"comment/842\",[]],[\"name/843\",[361,43.472]],[\"comment/843\",[]],[\"name/844\",[406,50.782]],[\"comment/844\",[]],[\"name/845\",[407,50.782]],[\"comment/845\",[]],[\"name/846\",[383,49.521]],[\"comment/846\",[]],[\"name/847\",[375,47.394]],[\"comment/847\",[]],[\"name/848\",[415,58.456]],[\"comment/848\",[]],[\"name/849\",[416,58.456]],[\"comment/849\",[]],[\"name/850\",[417,58.456]],[\"comment/850\",[]],[\"name/851\",[33,34.31]],[\"comment/851\",[]],[\"name/852\",[385,50.782]],[\"comment/852\",[]],[\"name/853\",[78,34.31]],[\"comment/853\",[]],[\"name/854\",[429,66.988]],[\"comment/854\",[]],[\"name/855\",[430,66.988]],[\"comment/855\",[]],[\"name/856\",[17,30.271]],[\"comment/856\",[]],[\"name/857\",[431,55.926]],[\"comment/857\",[]],[\"name/858\",[334,53.905]],[\"comment/858\",[]],[\"name/859\",[432,55.926]],[\"comment/859\",[]],[\"name/860\",[433,55.926]],[\"comment/860\",[]],[\"name/861\",[434,55.926]],[\"comment/861\",[]],[\"name/862\",[326,52.223]],[\"comment/862\",[]],[\"name/863\",[435,55.926]],[\"comment/863\",[]],[\"name/864\",[436,55.926]],[\"comment/864\",[]],[\"name/865\",[325,50.782]],[\"comment/865\",[]],[\"name/866\",[381,47.394]],[\"comment/866\",[]],[\"name/867\",[409,55.926]],[\"comment/867\",[]],[\"name/868\",[406,50.782]],[\"comment/868\",[]],[\"name/869\",[407,50.782]],[\"comment/869\",[]],[\"name/870\",[408,55.926]],[\"comment/870\",[]],[\"name/871\",[410,49.521]],[\"comment/871\",[]],[\"name/872\",[78,34.31]],[\"comment/872\",[]],[\"name/873\",[361,43.472]],[\"comment/873\",[]],[\"name/874\",[33,34.31]],[\"comment/874\",[]],[\"name/875\",[192,37.698]],[\"comment/875\",[]],[\"name/876\",[437,66.988]],[\"comment/876\",[]],[\"name/877\",[438,66.988]],[\"comment/877\",[]],[\"name/878\",[17,30.271]],[\"comment/878\",[]],[\"name/879\",[431,55.926]],[\"comment/879\",[]],[\"name/880\",[334,53.905]],[\"comment/880\",[]],[\"name/881\",[432,55.926]],[\"comment/881\",[]],[\"name/882\",[433,55.926]],[\"comment/882\",[]],[\"name/883\",[434,55.926]],[\"comment/883\",[]],[\"name/884\",[326,52.223]],[\"comment/884\",[]],[\"name/885\",[435,55.926]],[\"comment/885\",[]],[\"name/886\",[436,55.926]],[\"comment/886\",[]],[\"name/887\",[110,41.69]],[\"comment/887\",[]],[\"name/888\",[361,43.472]],[\"comment/888\",[]],[\"name/889\",[406,50.782]],[\"comment/889\",[]],[\"name/890\",[407,50.782]],[\"comment/890\",[]],[\"name/891\",[383,49.521]],[\"comment/891\",[]],[\"name/892\",[375,47.394]],[\"comment/892\",[]],[\"name/893\",[415,58.456]],[\"comment/893\",[]],[\"name/894\",[416,58.456]],[\"comment/894\",[]],[\"name/895\",[417,58.456]],[\"comment/895\",[]],[\"name/896\",[33,34.31]],[\"comment/896\",[]],[\"name/897\",[385,50.782]],[\"comment/897\",[]],[\"name/898\",[78,34.31]],[\"comment/898\",[]],[\"name/899\",[439,66.988]],[\"comment/899\",[]],[\"name/900\",[17,30.271]],[\"comment/900\",[]],[\"name/901\",[381,47.394]],[\"comment/901\",[]],[\"name/902\",[409,55.926]],[\"comment/902\",[]],[\"name/903\",[325,50.782]],[\"comment/903\",[]],[\"name/904\",[406,50.782]],[\"comment/904\",[]],[\"name/905\",[407,50.782]],[\"comment/905\",[]],[\"name/906\",[408,55.926]],[\"comment/906\",[]],[\"name/907\",[410,49.521]],[\"comment/907\",[]],[\"name/908\",[78,34.31]],[\"comment/908\",[]],[\"name/909\",[361,43.472]],[\"comment/909\",[]],[\"name/910\",[33,34.31]],[\"comment/910\",[]],[\"name/911\",[192,37.698]],[\"comment/911\",[]],[\"name/912\",[440,66.988]],[\"comment/912\",[]],[\"name/913\",[441,66.988]],[\"comment/913\",[]],[\"name/914\",[442,66.988]],[\"comment/914\",[]],[\"name/915\",[443,66.988]],[\"comment/915\",[]],[\"name/916\",[17,30.271]],[\"comment/916\",[]],[\"name/917\",[366,53.905]],[\"comment/917\",[]],[\"name/918\",[368,52.223]],[\"comment/918\",[]],[\"name/919\",[367,55.926]],[\"comment/919\",[]],[\"name/920\",[373,58.456]],[\"comment/920\",[]],[\"name/921\",[374,58.456]],[\"comment/921\",[]],[\"name/922\",[375,47.394]],[\"comment/922\",[]],[\"name/923\",[376,58.456]],[\"comment/923\",[]],[\"name/924\",[33,34.31]],[\"comment/924\",[]],[\"name/925\",[78,34.31]],[\"comment/925\",[]],[\"name/926\",[365,55.926]],[\"comment/926\",[]],[\"name/927\",[369,53.905]],[\"comment/927\",[]],[\"name/928\",[370,53.905]],[\"comment/928\",[]],[\"name/929\",[371,53.905]],[\"comment/929\",[]],[\"name/930\",[444,66.988]],[\"comment/930\",[]],[\"name/931\",[17,30.271]],[\"comment/931\",[]],[\"name/932\",[146,58.456]],[\"comment/932\",[]],[\"name/933\",[394,61.845]],[\"comment/933\",[]],[\"name/934\",[395,61.845]],[\"comment/934\",[]],[\"name/935\",[396,61.845]],[\"comment/935\",[]],[\"name/936\",[397,61.845]],[\"comment/936\",[]],[\"name/937\",[368,52.223]],[\"comment/937\",[]],[\"name/938\",[445,66.988]],[\"comment/938\",[]],[\"name/939\",[446,66.988]],[\"comment/939\",[]],[\"name/940\",[398,61.845]],[\"comment/940\",[]],[\"name/941\",[160,58.456]],[\"comment/941\",[]],[\"name/942\",[147,58.456]],[\"comment/942\",[]],[\"name/943\",[148,58.456]],[\"comment/943\",[]],[\"name/944\",[149,58.456]],[\"comment/944\",[]],[\"name/945\",[150,58.456]],[\"comment/945\",[]],[\"name/946\",[151,58.456]],[\"comment/946\",[]],[\"name/947\",[152,53.905]],[\"comment/947\",[]],[\"name/948\",[153,46.477]],[\"comment/948\",[]],[\"name/949\",[154,58.456]],[\"comment/949\",[]],[\"name/950\",[155,58.456]],[\"comment/950\",[]],[\"name/951\",[156,58.456]],[\"comment/951\",[]],[\"name/952\",[78,34.31]],[\"comment/952\",[]],[\"name/953\",[157,58.456]],[\"comment/953\",[]],[\"name/954\",[158,58.456]],[\"comment/954\",[]],[\"name/955\",[159,58.456]],[\"comment/955\",[]],[\"name/956\",[142,55.926]],[\"comment/956\",[]],[\"name/957\",[143,55.926]],[\"comment/957\",[]],[\"name/958\",[161,58.456]],[\"comment/958\",[]],[\"name/959\",[162,55.926]],[\"comment/959\",[]],[\"name/960\",[163,58.456]],[\"comment/960\",[]],[\"name/961\",[164,58.456]],[\"comment/961\",[]],[\"name/962\",[165,58.456]],[\"comment/962\",[]],[\"name/963\",[166,58.456]],[\"comment/963\",[]],[\"name/964\",[167,58.456]],[\"comment/964\",[]],[\"name/965\",[168,58.456]],[\"comment/965\",[]],[\"name/966\",[169,58.456]],[\"comment/966\",[]],[\"name/967\",[170,58.456]],[\"comment/967\",[]],[\"name/968\",[171,58.456]],[\"comment/968\",[]],[\"name/969\",[172,58.456]],[\"comment/969\",[]],[\"name/970\",[173,53.905]],[\"comment/970\",[]],[\"name/971\",[174,53.905]],[\"comment/971\",[]],[\"name/972\",[175,53.905]],[\"comment/972\",[]],[\"name/973\",[176,53.905]],[\"comment/973\",[]],[\"name/974\",[447,66.988]],[\"comment/974\",[]],[\"name/975\",[448,66.988]],[\"comment/975\",[]],[\"name/976\",[449,66.988]],[\"comment/976\",[]],[\"name/977\",[17,30.271]],[\"comment/977\",[]],[\"name/978\",[450,66.988]],[\"comment/978\",[]],[\"name/979\",[451,55.926]],[\"comment/979\",[]],[\"name/980\",[452,55.926]],[\"comment/980\",[]],[\"name/981\",[381,47.394]],[\"comment/981\",[]],[\"name/982\",[410,49.521]],[\"comment/982\",[]],[\"name/983\",[453,55.926]],[\"comment/983\",[]],[\"name/984\",[78,34.31]],[\"comment/984\",[]],[\"name/985\",[361,43.472]],[\"comment/985\",[]],[\"name/986\",[33,34.31]],[\"comment/986\",[]],[\"name/987\",[192,37.698]],[\"comment/987\",[]],[\"name/988\",[454,66.988]],[\"comment/988\",[]],[\"name/989\",[455,66.988]],[\"comment/989\",[]],[\"name/990\",[17,30.271]],[\"comment/990\",[]],[\"name/991\",[456,66.988]],[\"comment/991\",[]],[\"name/992\",[383,49.521]],[\"comment/992\",[]],[\"name/993\",[375,47.394]],[\"comment/993\",[]],[\"name/994\",[110,41.69]],[\"comment/994\",[]],[\"name/995\",[33,34.31]],[\"comment/995\",[]],[\"name/996\",[385,50.782]],[\"comment/996\",[]],[\"name/997\",[78,34.31]],[\"comment/997\",[]],[\"name/998\",[457,66.988]],[\"comment/998\",[]],[\"name/999\",[458,66.988]],[\"comment/999\",[]],[\"name/1000\",[17,30.271]],[\"comment/1000\",[]],[\"name/1001\",[345,58.456]],[\"comment/1001\",[]],[\"name/1002\",[459,58.456]],[\"comment/1002\",[]],[\"name/1003\",[333,52.223]],[\"comment/1003\",[]],[\"name/1004\",[420,53.905]],[\"comment/1004\",[]],[\"name/1005\",[423,55.926]],[\"comment/1005\",[]],[\"name/1006\",[421,55.926]],[\"comment/1006\",[]],[\"name/1007\",[422,55.926]],[\"comment/1007\",[]],[\"name/1008\",[346,58.456]],[\"comment/1008\",[]],[\"name/1009\",[460,55.926]],[\"comment/1009\",[]],[\"name/1010\",[114,48.401]],[\"comment/1010\",[]],[\"name/1011\",[424,52.223]],[\"comment/1011\",[]],[\"name/1012\",[238,53.905]],[\"comment/1012\",[]],[\"name/1013\",[425,55.926]],[\"comment/1013\",[]],[\"name/1014\",[426,55.926]],[\"comment/1014\",[]],[\"name/1015\",[381,47.394]],[\"comment/1015\",[]],[\"name/1016\",[451,55.926]],[\"comment/1016\",[]],[\"name/1017\",[453,55.926]],[\"comment/1017\",[]],[\"name/1018\",[452,55.926]],[\"comment/1018\",[]],[\"name/1019\",[410,49.521]],[\"comment/1019\",[]],[\"name/1020\",[78,34.31]],[\"comment/1020\",[]],[\"name/1021\",[361,43.472]],[\"comment/1021\",[]],[\"name/1022\",[33,34.31]],[\"comment/1022\",[]],[\"name/1023\",[192,37.698]],[\"comment/1023\",[]],[\"name/1024\",[461,66.988]],[\"comment/1024\",[]],[\"name/1025\",[462,66.988]],[\"comment/1025\",[]],[\"name/1026\",[17,30.271]],[\"comment/1026\",[]],[\"name/1027\",[333,52.223]],[\"comment/1027\",[]],[\"name/1028\",[420,53.905]],[\"comment/1028\",[]],[\"name/1029\",[423,55.926]],[\"comment/1029\",[]],[\"name/1030\",[421,55.926]],[\"comment/1030\",[]],[\"name/1031\",[422,55.926]],[\"comment/1031\",[]],[\"name/1032\",[114,48.401]],[\"comment/1032\",[]],[\"name/1033\",[424,52.223]],[\"comment/1033\",[]],[\"name/1034\",[238,53.905]],[\"comment/1034\",[]],[\"name/1035\",[425,55.926]],[\"comment/1035\",[]],[\"name/1036\",[426,55.926]],[\"comment/1036\",[]],[\"name/1037\",[110,41.69]],[\"comment/1037\",[]],[\"name/1038\",[383,49.521]],[\"comment/1038\",[]],[\"name/1039\",[375,47.394]],[\"comment/1039\",[]],[\"name/1040\",[33,34.31]],[\"comment/1040\",[]],[\"name/1041\",[385,50.782]],[\"comment/1041\",[]],[\"name/1042\",[78,34.31]],[\"comment/1042\",[]],[\"name/1043\",[463,66.988]],[\"comment/1043\",[]],[\"name/1044\",[53,37.339]],[\"comment/1044\",[]],[\"name/1045\",[13,61.845]],[\"comment/1045\",[]],[\"name/1046\",[464,66.988]],[\"comment/1046\",[]],[\"name/1047\",[53,37.339]],[\"comment/1047\",[]],[\"name/1048\",[465,66.988]],[\"comment/1048\",[]],[\"name/1049\",[466,66.988]],[\"comment/1049\",[]],[\"name/1050\",[467,61.845]],[\"comment/1050\",[]],[\"name/1051\",[468,66.988]],[\"comment/1051\",[]],[\"name/1052\",[469,66.988]],[\"comment/1052\",[]],[\"name/1053\",[470,58.456]],[\"comment/1053\",[]],[\"name/1054\",[471,61.845]],[\"comment/1054\",[]],[\"name/1055\",[472,66.988]],[\"comment/1055\",[]],[\"name/1056\",[53,37.339]],[\"comment/1056\",[]],[\"name/1057\",[473,66.988]],[\"comment/1057\",[]],[\"name/1058\",[224,55.926]],[\"comment/1058\",[]],[\"name/1059\",[63,55.926]],[\"comment/1059\",[]],[\"name/1060\",[474,66.988]],[\"comment/1060\",[]],[\"name/1061\",[53,37.339]],[\"comment/1061\",[]],[\"name/1062\",[475,66.988]],[\"comment/1062\",[]],[\"name/1063\",[470,58.456]],[\"comment/1063\",[]],[\"name/1064\",[476,66.988]],[\"comment/1064\",[]],[\"name/1065\",[53,37.339]],[\"comment/1065\",[]],[\"name/1066\",[467,61.845]],[\"comment/1066\",[]],[\"name/1067\",[470,58.456]],[\"comment/1067\",[]],[\"name/1068\",[471,61.845]],[\"comment/1068\",[]],[\"name/1069\",[477,66.988]],[\"comment/1069\",[]],[\"name/1070\",[53,37.339]],[\"comment/1070\",[]],[\"name/1071\",[460,55.926]],[\"comment/1071\",[]],[\"name/1072\",[114,48.401]],[\"comment/1072\",[]],[\"name/1073\",[424,52.223]],[\"comment/1073\",[]],[\"name/1074\",[78,34.31]],[\"comment/1074\",[]],[\"name/1075\",[478,66.988]],[\"comment/1075\",[]],[\"name/1076\",[17,30.271]],[\"comment/1076\",[]],[\"name/1077\",[36,55.926]],[\"comment/1077\",[]],[\"name/1078\",[459,58.456]],[\"comment/1078\",[]],[\"name/1079\",[333,52.223]],[\"comment/1079\",[]],[\"name/1080\",[420,53.905]],[\"comment/1080\",[]],[\"name/1081\",[153,46.477]],[\"comment/1081\",[]],[\"name/1082\",[33,34.31]],[\"comment/1082\",[]],[\"name/1083\",[460,55.926]],[\"comment/1083\",[]],[\"name/1084\",[114,48.401]],[\"comment/1084\",[]],[\"name/1085\",[424,52.223]],[\"comment/1085\",[]],[\"name/1086\",[78,34.31]],[\"comment/1086\",[]],[\"name/1087\",[479,66.988]],[\"comment/1087\",[]],[\"name/1088\",[480,66.988]],[\"comment/1088\",[]],[\"name/1089\",[481,66.988]],[\"comment/1089\",[]],[\"name/1090\",[482,66.988]],[\"comment/1090\",[]],[\"name/1091\",[483,66.988]],[\"comment/1091\",[]],[\"name/1092\",[484,66.988]],[\"comment/1092\",[]],[\"name/1093\",[17,30.271]],[\"comment/1093\",[]],[\"name/1094\",[431,55.926]],[\"comment/1094\",[]],[\"name/1095\",[334,53.905]],[\"comment/1095\",[]],[\"name/1096\",[432,55.926]],[\"comment/1096\",[]],[\"name/1097\",[433,55.926]],[\"comment/1097\",[]],[\"name/1098\",[459,58.456]],[\"comment/1098\",[]],[\"name/1099\",[434,55.926]],[\"comment/1099\",[]],[\"name/1100\",[326,52.223]],[\"comment/1100\",[]],[\"name/1101\",[435,55.926]],[\"comment/1101\",[]],[\"name/1102\",[436,55.926]],[\"comment/1102\",[]],[\"name/1103\",[460,55.926]],[\"comment/1103\",[]],[\"name/1104\",[381,47.394]],[\"comment/1104\",[]],[\"name/1105\",[451,55.926]],[\"comment/1105\",[]],[\"name/1106\",[453,55.926]],[\"comment/1106\",[]],[\"name/1107\",[452,55.926]],[\"comment/1107\",[]],[\"name/1108\",[410,49.521]],[\"comment/1108\",[]],[\"name/1109\",[78,34.31]],[\"comment/1109\",[]],[\"name/1110\",[361,43.472]],[\"comment/1110\",[]],[\"name/1111\",[33,34.31]],[\"comment/1111\",[]],[\"name/1112\",[192,37.698]],[\"comment/1112\",[]],[\"name/1113\",[485,66.988]],[\"comment/1113\",[]],[\"name/1114\",[486,66.988]],[\"comment/1114\",[]],[\"name/1115\",[17,30.271]],[\"comment/1115\",[]],[\"name/1116\",[431,55.926]],[\"comment/1116\",[]],[\"name/1117\",[334,53.905]],[\"comment/1117\",[]],[\"name/1118\",[432,55.926]],[\"comment/1118\",[]],[\"name/1119\",[433,55.926]],[\"comment/1119\",[]],[\"name/1120\",[434,55.926]],[\"comment/1120\",[]],[\"name/1121\",[326,52.223]],[\"comment/1121\",[]],[\"name/1122\",[435,55.926]],[\"comment/1122\",[]],[\"name/1123\",[436,55.926]],[\"comment/1123\",[]],[\"name/1124\",[110,41.69]],[\"comment/1124\",[]],[\"name/1125\",[383,49.521]],[\"comment/1125\",[]],[\"name/1126\",[375,47.394]],[\"comment/1126\",[]],[\"name/1127\",[33,34.31]],[\"comment/1127\",[]],[\"name/1128\",[385,50.782]],[\"comment/1128\",[]],[\"name/1129\",[78,34.31]],[\"comment/1129\",[]],[\"name/1130\",[487,66.988]],[\"comment/1130\",[]],[\"name/1131\",[488,66.988]],[\"comment/1131\",[]],[\"name/1132\",[17,30.271]],[\"comment/1132\",[]],[\"name/1133\",[381,47.394]],[\"comment/1133\",[]],[\"name/1134\",[451,55.926]],[\"comment/1134\",[]],[\"name/1135\",[453,55.926]],[\"comment/1135\",[]],[\"name/1136\",[452,55.926]],[\"comment/1136\",[]],[\"name/1137\",[410,49.521]],[\"comment/1137\",[]],[\"name/1138\",[78,34.31]],[\"comment/1138\",[]],[\"name/1139\",[361,43.472]],[\"comment/1139\",[]],[\"name/1140\",[33,34.31]],[\"comment/1140\",[]],[\"name/1141\",[192,37.698]],[\"comment/1141\",[]],[\"name/1142\",[489,66.988]],[\"comment/1142\",[]],[\"name/1143\",[490,66.988]],[\"comment/1143\",[]],[\"name/1144\",[491,66.988]],[\"comment/1144\",[]],[\"name/1145\",[492,66.988]],[\"comment/1145\",[]],[\"name/1146\",[493,66.988]],[\"comment/1146\",[]],[\"name/1147\",[53,37.339]],[\"comment/1147\",[]],[\"name/1148\",[325,50.782]],[\"comment/1148\",[]],[\"name/1149\",[494,66.988]],[\"comment/1149\",[]],[\"name/1150\",[495,61.845]],[\"comment/1150\",[]],[\"name/1151\",[496,66.988]],[\"comment/1151\",[]],[\"name/1152\",[497,66.988]],[\"comment/1152\",[]],[\"name/1153\",[498,66.988]],[\"comment/1153\",[]],[\"name/1154\",[78,34.31]],[\"comment/1154\",[]],[\"name/1155\",[499,66.988]],[\"comment/1155\",[]],[\"name/1156\",[53,37.339]],[\"comment/1156\",[]],[\"name/1157\",[495,61.845]],[\"comment/1157\",[]],[\"name/1158\",[66,61.845]],[\"comment/1158\",[]],[\"name/1159\",[500,66.988]],[\"comment/1159\",[]],[\"name/1160\",[501,66.988]],[\"comment/1160\",[]]],\"invertedIndex\":[[\"__type\",{\"_index\":53,\"name\":{\"57\":{},\"59\":{},\"62\":{},\"67\":{},\"72\":{},\"78\":{},\"88\":{},\"142\":{},\"243\":{},\"252\":{},\"258\":{},\"312\":{},\"339\":{},\"410\":{},\"418\":{},\"550\":{},\"616\":{},\"633\":{},\"660\":{},\"676\":{},\"1044\":{},\"1047\":{},\"1056\":{},\"1061\":{},\"1065\":{},\"1070\":{},\"1147\":{},\"1156\":{}},\"comment\":{}}],[\"_accesskey\",{\"_index\":334,\"name\":{\"562\":{},\"858\":{},\"880\":{},\"1095\":{},\"1117\":{}},\"comment\":{}}],[\"_additionalcapabilities\",{\"_index\":414,\"name\":{\"792\":{}},\"comment\":{}}],[\"_aftconfig\",{\"_index\":18,\"name\":{\"13\":{}},\"comment\":{}}],[\"_api\",{\"_index\":345,\"name\":{\"583\":{},\"602\":{},\"1001\":{}},\"comment\":{}}],[\"_apiurl\",{\"_index\":459,\"name\":{\"1002\":{},\"1078\":{},\"1098\":{}},\"comment\":{}}],[\"_app\",{\"_index\":450,\"name\":{\"978\":{}},\"comment\":{}}],[\"_appendtofile\",{\"_index\":311,\"name\":{\"498\":{}},\"comment\":{}}],[\"_assertion\",{\"_index\":146,\"name\":{\"193\":{},\"726\":{},\"932\":{}},\"comment\":{}}],[\"_async2sync\",{\"_index\":272,\"name\":{\"429\":{}},\"comment\":{}}],[\"_asyncspecdone\",{\"_index\":277,\"name\":{\"434\":{}},\"comment\":{}}],[\"_buildinfomgr\",{\"_index\":287,\"name\":{\"464\":{}},\"comment\":{}}],[\"_buildmgr\",{\"_index\":156,\"name\":{\"203\":{},\"745\":{},\"951\":{}},\"comment\":{}}],[\"_cacheduration\",{\"_index\":39,\"name\":{\"42\":{},\"566\":{}},\"comment\":{}}],[\"_caps\",{\"_index\":405,\"name\":{\"774\":{}},\"comment\":{}}],[\"_checkandsendlogs\",{\"_index\":300,\"name\":{\"480\":{}},\"comment\":{}}],[\"_client\",{\"_index\":288,\"name\":{\"465\":{}},\"comment\":{}}],[\"_config\",{\"_index\":204,\"name\":{\"263\":{},\"568\":{}},\"comment\":{}}],[\"_createkinesislogrecord\",{\"_index\":299,\"name\":{\"479\":{}},\"comment\":{}}],[\"_createtestcasefromcase\",{\"_index\":349,\"name\":{\"594\":{}},\"comment\":{}}],[\"_createtestcasefromtest\",{\"_index\":348,\"name\":{\"593\":{}},\"comment\":{}}],[\"_createtestplanifnone\",{\"_index\":354,\"name\":{\"611\":{}},\"comment\":{}}],[\"_dateformat\",{\"_index\":307,\"name\":{\"491\":{}},\"comment\":{}}],[\"_debug\",{\"_index\":423,\"name\":{\"812\":{},\"836\":{},\"1005\":{},\"1029\":{}},\"comment\":{}}],[\"_defectmgr\",{\"_index\":155,\"name\":{\"202\":{},\"744\":{},\"950\":{}},\"comment\":{}}],[\"_defects\",{\"_index\":152,\"name\":{\"199\":{},\"445\":{},\"531\":{},\"741\":{},\"947\":{}},\"comment\":{}}],[\"_description\",{\"_index\":148,\"name\":{\"195\":{},\"737\":{},\"943\":{}},\"comment\":{}}],[\"_driver\",{\"_index\":456,\"name\":{\"991\":{}},\"comment\":{}}],[\"_enabled\",{\"_index\":195,\"name\":{\"248\":{}},\"comment\":{}}],[\"_findtestsbyfield\",{\"_index\":347,\"name\":{\"592\":{}},\"comment\":{}}],[\"_format\",{\"_index\":312,\"name\":{\"499\":{}},\"comment\":{}}],[\"_generatetestresult\",{\"_index\":176,\"name\":{\"226\":{},\"456\":{},\"541\":{},\"767\":{},\"973\":{}},\"comment\":{}}],[\"_generatetestresults\",{\"_index\":175,\"name\":{\"225\":{},\"455\":{},\"540\":{},\"766\":{},\"972\":{}},\"comment\":{}}],[\"_getauthheader\",{\"_index\":482,\"name\":{\"1090\":{}},\"comment\":{}}],[\"_getinnerpromise\",{\"_index\":143,\"name\":{\"188\":{},\"209\":{},\"751\":{},\"957\":{}},\"comment\":{}}],[\"_gettestrailresultforexternalresult\",{\"_index\":353,\"name\":{\"610\":{}},\"comment\":{}}],[\"_includeresults\",{\"_index\":306,\"name\":{\"490\":{}},\"comment\":{}}],[\"_innerpromise\",{\"_index\":150,\"name\":{\"197\":{},\"739\":{},\"945\":{}},\"comment\":{}}],[\"_internalmap\",{\"_index\":38,\"name\":{\"41\":{}},\"comment\":{}}],[\"_iserror\",{\"_index\":87,\"name\":{\"102\":{}},\"comment\":{}}],[\"_isstillvalid\",{\"_index\":49,\"name\":{\"53\":{}},\"comment\":{}}],[\"_key\",{\"_index\":420,\"name\":{\"809\":{},\"833\":{},\"1004\":{},\"1028\":{},\"1080\":{}},\"comment\":{}}],[\"_level\",{\"_index\":254,\"name\":{\"378\":{}},\"comment\":{}}],[\"_local\",{\"_index\":421,\"name\":{\"810\":{},\"834\":{},\"1006\":{},\"1030\":{}},\"comment\":{}}],[\"_localidentifier\",{\"_index\":422,\"name\":{\"811\":{},\"835\":{},\"1007\":{},\"1031\":{}},\"comment\":{}}],[\"_lockfiledescriptor\",{\"_index\":99,\"name\":{\"116\":{}},\"comment\":{}}],[\"_logmessage\",{\"_index\":174,\"name\":{\"224\":{},\"454\":{},\"539\":{},\"765\":{},\"971\":{}},\"comment\":{}}],[\"_logmgr\",{\"_index\":153,\"name\":{\"200\":{},\"276\":{},\"437\":{},\"523\":{},\"584\":{},\"644\":{},\"668\":{},\"684\":{},\"742\":{},\"948\":{},\"1081\":{}},\"comment\":{}}],[\"_logresult\",{\"_index\":173,\"name\":{\"223\":{},\"453\":{},\"538\":{},\"764\":{},\"970\":{}},\"comment\":{}}],[\"_logs\",{\"_index\":286,\"name\":{\"463\":{},\"507\":{},\"600\":{}},\"comment\":{}}],[\"_matcher\",{\"_index\":147,\"name\":{\"194\":{},\"736\":{},\"942\":{}},\"comment\":{}}],[\"_memorymap\",{\"_index\":106,\"name\":{\"124\":{}},\"comment\":{}}],[\"_options\",{\"_index\":36,\"name\":{\"37\":{},\"264\":{},\"682\":{},\"1077\":{}},\"comment\":{}}],[\"_opts\",{\"_index\":194,\"name\":{\"247\":{},\"645\":{}},\"comment\":{}}],[\"_optsprovider\",{\"_index\":19,\"name\":{\"14\":{}},\"comment\":{}}],[\"_outputpath\",{\"_index\":305,\"name\":{\"489\":{}},\"comment\":{}}],[\"_planid\",{\"_index\":337,\"name\":{\"565\":{}},\"comment\":{}}],[\"_platform\",{\"_index\":380,\"name\":{\"669\":{},\"683\":{}},\"comment\":{}}],[\"_plugins\",{\"_index\":203,\"name\":{\"262\":{}},\"comment\":{}}],[\"_processmessage\",{\"_index\":88,\"name\":{\"103\":{}},\"comment\":{}}],[\"_processstack\",{\"_index\":89,\"name\":{\"104\":{}},\"comment\":{}}],[\"_projectid\",{\"_index\":335,\"name\":{\"563\":{}},\"comment\":{}}],[\"_providers\",{\"_index\":25,\"name\":{\"21\":{}},\"comment\":{}}],[\"_regeneratehtmlfile\",{\"_index\":320,\"name\":{\"517\":{}},\"comment\":{}}],[\"_removeinternalstacklines\",{\"_index\":90,\"name\":{\"105\":{}},\"comment\":{}}],[\"_removenewlinesandextrawhitespace\",{\"_index\":91,\"name\":{\"106\":{}},\"comment\":{}}],[\"_resolution\",{\"_index\":404,\"name\":{\"773\":{},\"791\":{}},\"comment\":{}}],[\"_resolveassertion\",{\"_index\":160,\"name\":{\"210\":{},\"735\":{},\"941\":{}},\"comment\":{}}],[\"_results\",{\"_index\":315,\"name\":{\"506\":{}},\"comment\":{}}],[\"_send\",{\"_index\":302,\"name\":{\"482\":{}},\"comment\":{}}],[\"_sendbatch\",{\"_index\":301,\"name\":{\"481\":{}},\"comment\":{}}],[\"_session\",{\"_index\":395,\"name\":{\"728\":{},\"934\":{}},\"comment\":{}}],[\"_sessionmgr\",{\"_index\":394,\"name\":{\"727\":{},\"933\":{}},\"comment\":{}}],[\"_sessionoptions\",{\"_index\":396,\"name\":{\"729\":{},\"935\":{}},\"comment\":{}}],[\"_shared\",{\"_index\":338,\"name\":{\"567\":{}},\"comment\":{}}],[\"_shouldrun_defects\",{\"_index\":172,\"name\":{\"222\":{},\"763\":{},\"969\":{}},\"comment\":{}}],[\"_shouldrun_tests\",{\"_index\":171,\"name\":{\"221\":{},\"762\":{},\"968\":{}},\"comment\":{}}],[\"_starttime\",{\"_index\":149,\"name\":{\"196\":{},\"738\":{},\"944\":{}},\"comment\":{}}],[\"_stepcount\",{\"_index\":235,\"name\":{\"346\":{}},\"comment\":{}}],[\"_suiteids\",{\"_index\":336,\"name\":{\"564\":{}},\"comment\":{}}],[\"_testcases\",{\"_index\":282,\"name\":{\"444\":{},\"530\":{}},\"comment\":{}}],[\"_testmgr\",{\"_index\":154,\"name\":{\"201\":{},\"743\":{},\"949\":{}},\"comment\":{}}],[\"_testnames\",{\"_index\":273,\"name\":{\"430\":{},\"438\":{}},\"comment\":{}}],[\"_tests\",{\"_index\":151,\"name\":{\"198\":{},\"740\":{},\"946\":{}},\"comment\":{}}],[\"_timeout\",{\"_index\":100,\"name\":{\"117\":{},\"775\":{}},\"comment\":{}}],[\"_trconfig\",{\"_index\":344,\"name\":{\"582\":{},\"601\":{}},\"comment\":{}}],[\"_tunnel\",{\"_index\":432,\"name\":{\"859\":{},\"881\":{},\"1096\":{},\"1118\":{}},\"comment\":{}}],[\"_tunnelidentifier\",{\"_index\":433,\"name\":{\"860\":{},\"882\":{},\"1097\":{},\"1119\":{}},\"comment\":{}}],[\"_uiplatform\",{\"_index\":413,\"name\":{\"790\":{}},\"comment\":{}}],[\"_uiplt\",{\"_index\":388,\"name\":{\"694\":{}},\"comment\":{}}],[\"_updatememorymap\",{\"_index\":108,\"name\":{\"136\":{}},\"comment\":{}}],[\"_url\",{\"_index\":332,\"name\":{\"560\":{},\"772\":{}},\"comment\":{}}],[\"_user\",{\"_index\":333,\"name\":{\"561\":{},\"808\":{},\"832\":{},\"1003\":{},\"1027\":{},\"1079\":{}},\"comment\":{}}],[\"_username\",{\"_index\":431,\"name\":{\"857\":{},\"879\":{},\"1094\":{},\"1116\":{}},\"comment\":{}}],[\"_verbosity\",{\"_index\":82,\"name\":{\"95\":{}},\"comment\":{}}],[\"_waitforlock\",{\"_index\":102,\"name\":{\"119\":{}},\"comment\":{}}],[\"_writetofile\",{\"_index\":107,\"name\":{\"135\":{}},\"comment\":{}}],[\"accesskey\",{\"_index\":326,\"name\":{\"553\":{},\"572\":{},\"862\":{},\"884\":{},\"1100\":{},\"1121\":{}},\"comment\":{}}],[\"accesskeyid\",{\"_index\":290,\"name\":{\"467\":{}},\"comment\":{}}],[\"action\",{\"_index\":52,\"name\":{\"56\":{}},\"comment\":{}}],[\"additionalcapabilities\",{\"_index\":407,\"name\":{\"778\":{},\"795\":{},\"822\":{},\"845\":{},\"869\":{},\"890\":{},\"905\":{}},\"comment\":{}}],[\"addlisteners\",{\"_index\":323,\"name\":{\"548\":{}},\"comment\":{}}],[\"aft\",{\"_index\":0,\"name\":{\"0\":{},\"1\":{},\"2\":{},\"3\":{},\"4\":{},\"5\":{},\"6\":{},\"7\":{},\"8\":{},\"9\":{},\"10\":{}},\"comment\":{}}],[\"aftconfig\",{\"_index\":21,\"name\":{\"16\":{}},\"comment\":{}}],[\"aftconfigprovider\",{\"_index\":16,\"name\":{\"11\":{}},\"comment\":{}}],[\"aftjasminereporter\",{\"_index\":271,\"name\":{\"427\":{}},\"comment\":{}}],[\"aftlog\",{\"_index\":278,\"name\":{\"435\":{},\"521\":{}},\"comment\":{}}],[\"aftmochareporter\",{\"_index\":322,\"name\":{\"546\":{}},\"comment\":{}}],[\"afttest\",{\"_index\":281,\"name\":{\"442\":{},\"528\":{}},\"comment\":{}}],[\"allowautoredirect\",{\"_index\":494,\"name\":{\"1149\":{}},\"comment\":{}}],[\"and\",{\"_index\":161,\"name\":{\"211\":{},\"752\":{},\"958\":{}},\"comment\":{}}],[\"any\",{\"_index\":362,\"name\":{\"623\":{}},\"comment\":{}}],[\"api\",{\"_index\":346,\"name\":{\"586\":{},\"604\":{},\"1008\":{}},\"comment\":{}}],[\"apiurl\",{\"_index\":460,\"name\":{\"1009\":{},\"1071\":{},\"1083\":{},\"1103\":{}},\"comment\":{}}],[\"app\",{\"_index\":452,\"name\":{\"980\":{},\"1018\":{},\"1107\":{},\"1136\":{}},\"comment\":{}}],[\"app_id\",{\"_index\":468,\"name\":{\"1051\":{}},\"comment\":{}}],[\"app_name\",{\"_index\":465,\"name\":{\"1048\":{}},\"comment\":{}}],[\"app_url\",{\"_index\":467,\"name\":{\"1050\":{},\"1066\":{}},\"comment\":{}}],[\"app_version\",{\"_index\":466,\"name\":{\"1049\":{}},\"comment\":{}}],[\"appiumgridsessiongeneratorplugin\",{\"_index\":488,\"name\":{\"1131\":{}},\"comment\":{}}],[\"appiumgridsessiongeneratorpluginoptions\",{\"_index\":487,\"name\":{\"1130\":{}},\"comment\":{}}],[\"apps\",{\"_index\":13,\"name\":{\"9\":{},\"1045\":{}},\"comment\":{}}],[\"awskinesis\",{\"_index\":5,\"name\":{\"2\":{}},\"comment\":{}}],[\"backofftype\",{\"_index\":123,\"name\":{\"155\":{},\"169\":{}},\"comment\":{}}],[\"batch\",{\"_index\":295,\"name\":{\"472\":{}},\"comment\":{}}],[\"batchsize\",{\"_index\":296,\"name\":{\"473\":{}},\"comment\":{}}],[\"between\",{\"_index\":184,\"name\":{\"235\":{}},\"comment\":{}}],[\"browser\",{\"_index\":358,\"name\":{\"619\":{},\"628\":{}},\"comment\":{}}],[\"browserfacet\",{\"_index\":392,\"name\":{\"709\":{}},\"comment\":{}}],[\"browserfacetoptions\",{\"_index\":391,\"name\":{\"708\":{}},\"comment\":{}}],[\"browsers\",{\"_index\":11,\"name\":{\"8\":{}},\"comment\":{}}],[\"browsersession\",{\"_index\":412,\"name\":{\"788\":{}},\"comment\":{}}],[\"browsersessiongeneratormgr\",{\"_index\":389,\"name\":{\"706\":{}},\"comment\":{}}],[\"browsersessiongeneratorplugin\",{\"_index\":403,\"name\":{\"770\":{}},\"comment\":{}}],[\"browsersessiongeneratorpluginoptions\",{\"_index\":402,\"name\":{\"769\":{}},\"comment\":{}}],[\"browsersessionoptions\",{\"_index\":411,\"name\":{\"787\":{}},\"comment\":{}}],[\"browserstackappautomateapi\",{\"_index\":478,\"name\":{\"1075\":{}},\"comment\":{}}],[\"browserstackappautomateapioptions\",{\"_index\":477,\"name\":{\"1069\":{}},\"comment\":{}}],[\"browserstackbrowsersession\",{\"_index\":428,\"name\":{\"830\":{}},\"comment\":{}}],[\"browserstackbrowsersessiongeneratorplugin\",{\"_index\":419,\"name\":{\"806\":{}},\"comment\":{}}],[\"browserstackbrowsersessiongeneratorpluginoptions\",{\"_index\":418,\"name\":{\"805\":{}},\"comment\":{}}],[\"browserstackbrowsersessionoptions\",{\"_index\":427,\"name\":{\"829\":{}},\"comment\":{}}],[\"browserstackmobileapp\",{\"_index\":464,\"name\":{\"1046\":{}},\"comment\":{}}],[\"browserstackmobileappsession\",{\"_index\":462,\"name\":{\"1025\":{}},\"comment\":{}}],[\"browserstackmobileappsessiongeneratorplugin\",{\"_index\":458,\"name\":{\"999\":{}},\"comment\":{}}],[\"browserstackmobileappsessiongeneratorpluginoptions\",{\"_index\":457,\"name\":{\"998\":{}},\"comment\":{}}],[\"browserstackmobileappsessionoptions\",{\"_index\":461,\"name\":{\"1024\":{}},\"comment\":{}}],[\"browserverifier\",{\"_index\":393,\"name\":{\"724\":{}},\"comment\":{}}],[\"browserversion\",{\"_index\":359,\"name\":{\"620\":{},\"629\":{}},\"comment\":{}}],[\"buildinfo\",{\"_index\":218,\"name\":{\"309\":{}},\"comment\":{}}],[\"buildinfomanager\",{\"_index\":216,\"name\":{\"294\":{}},\"comment\":{}}],[\"buildinfomanageroptions\",{\"_index\":215,\"name\":{\"293\":{}},\"comment\":{}}],[\"buildinfoplugin\",{\"_index\":212,\"name\":{\"287\":{}},\"comment\":{}}],[\"buildinfopluginoptions\",{\"_index\":211,\"name\":{\"286\":{}},\"comment\":{}}],[\"buildmgr\",{\"_index\":159,\"name\":{\"207\":{},\"749\":{},\"955\":{}},\"comment\":{}}],[\"buildname\",{\"_index\":213,\"name\":{\"289\":{},\"297\":{}},\"comment\":{}}],[\"buildnumber\",{\"_index\":214,\"name\":{\"290\":{},\"298\":{}},\"comment\":{}}],[\"cacheduration\",{\"_index\":340,\"name\":{\"577\":{}},\"comment\":{}}],[\"cachedurationms\",{\"_index\":330,\"name\":{\"557\":{}},\"comment\":{}}],[\"cachemap\",{\"_index\":37,\"name\":{\"39\":{}},\"comment\":{}}],[\"cacheobject\",{\"_index\":64,\"name\":{\"71\":{}},\"comment\":{}}],[\"calculatebackoffdelay\",{\"_index\":118,\"name\":{\"149\":{}},\"comment\":{}}],[\"cfgmgr\",{\"_index\":26,\"name\":{\"23\":{}},\"comment\":{}}],[\"chainedprovider\",{\"_index\":24,\"name\":{\"19\":{}},\"comment\":{}}],[\"class\",{\"_index\":54,\"name\":{\"58\":{}},\"comment\":{}}],[\"clear\",{\"_index\":40,\"name\":{\"43\":{},\"125\":{}},\"comment\":{}}],[\"client\",{\"_index\":289,\"name\":{\"466\":{}},\"comment\":{}}],[\"compare\",{\"_index\":180,\"name\":{\"231\":{}},\"comment\":{}}],[\"condition\",{\"_index\":124,\"name\":{\"156\":{},\"170\":{}},\"comment\":{}}],[\"config\",{\"_index\":31,\"name\":{\"31\":{},\"265\":{},\"277\":{},\"300\":{},\"328\":{},\"361\":{},\"399\":{},\"569\":{},\"585\":{},\"603\":{},\"698\":{}},\"comment\":{}}],[\"configkey\",{\"_index\":20,\"name\":{\"15\":{}},\"comment\":{}}],[\"constructor\",{\"_index\":17,\"name\":{\"12\":{},\"20\":{},\"25\":{},\"36\":{},\"40\":{},\"93\":{},\"112\":{},\"122\":{},\"150\":{},\"192\":{},\"246\":{},\"261\":{},\"275\":{},\"288\":{},\"295\":{},\"319\":{},\"325\":{},\"345\":{},\"377\":{},\"387\":{},\"395\":{},\"428\":{},\"436\":{},\"443\":{},\"462\":{},\"488\":{},\"505\":{},\"522\":{},\"529\":{},\"547\":{},\"559\":{},\"581\":{},\"599\":{},\"625\":{},\"643\":{},\"667\":{},\"681\":{},\"693\":{},\"710\":{},\"725\":{},\"771\":{},\"789\":{},\"807\":{},\"831\":{},\"856\":{},\"878\":{},\"900\":{},\"916\":{},\"931\":{},\"977\":{},\"990\":{},\"1000\":{},\"1026\":{},\"1076\":{},\"1093\":{},\"1115\":{},\"1132\":{}},\"comment\":{}}],[\"containing\",{\"_index\":185,\"name\":{\"236\":{}},\"comment\":{}}],[\"convert\",{\"_index\":73,\"name\":{\"83\":{}},\"comment\":{}}],[\"core\",{\"_index\":1,\"name\":{\"0\":{}},\"comment\":{}}],[\"created\",{\"_index\":264,\"name\":{\"412\":{},\"423\":{}},\"comment\":{}}],[\"createdriver\",{\"_index\":410,\"name\":{\"781\":{},\"824\":{},\"871\":{},\"907\":{},\"982\":{},\"1019\":{},\"1108\":{},\"1137\":{}},\"comment\":{}}],[\"credentials\",{\"_index\":297,\"name\":{\"474\":{}},\"comment\":{}}],[\"currentdelay\",{\"_index\":122,\"name\":{\"154\":{},\"168\":{}},\"comment\":{}}],[\"custom_id\",{\"_index\":470,\"name\":{\"1053\":{},\"1063\":{},\"1067\":{}},\"comment\":{}}],[\"data\",{\"_index\":66,\"name\":{\"74\":{},\"1158\":{}},\"comment\":{}}],[\"dateformat\",{\"_index\":310,\"name\":{\"494\":{}},\"comment\":{}}],[\"debug\",{\"_index\":238,\"name\":{\"350\":{},\"817\":{},\"841\":{},\"1012\":{},\"1034\":{}},\"comment\":{}}],[\"defaults\",{\"_index\":72,\"name\":{\"82\":{}},\"comment\":{}}],[\"defect\",{\"_index\":220,\"name\":{\"311\":{}},\"comment\":{}}],[\"defectmanager\",{\"_index\":229,\"name\":{\"324\":{}},\"comment\":{}}],[\"defectmgr\",{\"_index\":158,\"name\":{\"206\":{},\"748\":{},\"954\":{}},\"comment\":{}}],[\"defectplugin\",{\"_index\":226,\"name\":{\"318\":{}},\"comment\":{}}],[\"defectpluginoptions\",{\"_index\":225,\"name\":{\"317\":{}},\"comment\":{}}],[\"defects\",{\"_index\":230,\"name\":{\"337\":{},\"424\":{},\"447\":{},\"533\":{}},\"comment\":{}}],[\"defectstatus\",{\"_index\":219,\"name\":{\"310\":{}},\"comment\":{}}],[\"delay\",{\"_index\":121,\"name\":{\"153\":{}},\"comment\":{}}],[\"delete\",{\"_index\":41,\"name\":{\"44\":{},\"126\":{}},\"comment\":{}}],[\"deliverystream\",{\"_index\":294,\"name\":{\"471\":{}},\"comment\":{}}],[\"description\",{\"_index\":223,\"name\":{\"315\":{},\"414\":{}},\"comment\":{}}],[\"devicename\",{\"_index\":360,\"name\":{\"621\":{},\"630\":{}},\"comment\":{}}],[\"disposable\",{\"_index\":109,\"name\":{\"139\":{}},\"comment\":{}}],[\"dispose\",{\"_index\":110,\"name\":{\"140\":{},\"359\":{},\"382\":{},\"452\":{},\"478\":{},\"497\":{},\"516\":{},\"527\":{},\"545\":{},\"591\":{},\"609\":{},\"690\":{},\"801\":{},\"842\":{},\"887\":{},\"994\":{},\"1037\":{},\"1124\":{}},\"comment\":{}}],[\"driver\",{\"_index\":383,\"name\":{\"679\":{},\"686\":{},\"796\":{},\"846\":{},\"891\":{},\"992\":{},\"1038\":{},\"1125\":{}},\"comment\":{}}],[\"ellide\",{\"_index\":75,\"name\":{\"85\":{}},\"comment\":{}}],[\"ellipsislocation\",{\"_index\":74,\"name\":{\"84\":{}},\"comment\":{}}],[\"enabled\",{\"_index\":192,\"name\":{\"244\":{},\"250\":{},\"270\":{},\"283\":{},\"292\":{},\"306\":{},\"323\":{},\"334\":{},\"365\":{},\"384\":{},\"392\":{},\"405\":{},\"485\":{},\"502\":{},\"520\":{},\"596\":{},\"614\":{},\"674\":{},\"703\":{},\"786\":{},\"828\":{},\"875\":{},\"911\":{},\"987\":{},\"1023\":{},\"1112\":{},\"1141\":{}},\"comment\":{}}],[\"entries\",{\"_index\":46,\"name\":{\"50\":{},\"132\":{}},\"comment\":{}}],[\"envvarprovider\",{\"_index\":27,\"name\":{\"24\":{}},\"comment\":{}}],[\"equaling\",{\"_index\":182,\"name\":{\"233\":{}},\"comment\":{}}],[\"err\",{\"_index\":81,\"name\":{\"92\":{},\"94\":{},\"107\":{},\"160\":{}},\"comment\":{}}],[\"errlevel\",{\"_index\":79,\"name\":{\"90\":{}},\"comment\":{}}],[\"erroptions\",{\"_index\":77,\"name\":{\"87\":{}},\"comment\":{}}],[\"error\",{\"_index\":244,\"name\":{\"356\":{}},\"comment\":{}}],[\"errverbosity\",{\"_index\":76,\"name\":{\"86\":{}},\"comment\":{}}],[\"exactly\",{\"_index\":183,\"name\":{\"234\":{}},\"comment\":{}}],[\"exclude\",{\"_index\":70,\"name\":{\"79\":{}},\"comment\":{}}],[\"expected\",{\"_index\":178,\"name\":{\"229\":{}},\"comment\":{}}],[\"expiringfilelock\",{\"_index\":95,\"name\":{\"111\":{}},\"comment\":{}}],[\"fail\",{\"_index\":243,\"name\":{\"355\":{},\"449\":{},\"535\":{}},\"comment\":{}}],[\"failaction\",{\"_index\":127,\"name\":{\"159\":{},\"173\":{}},\"comment\":{}}],[\"failurestring\",{\"_index\":181,\"name\":{\"232\":{}},\"comment\":{}}],[\"file\",{\"_index\":475,\"name\":{\"1062\":{}},\"comment\":{}}],[\"fileio\",{\"_index\":103,\"name\":{\"120\":{}},\"comment\":{}}],[\"filename\",{\"_index\":105,\"name\":{\"123\":{},\"508\":{}},\"comment\":{}}],[\"filesystem\",{\"_index\":6,\"name\":{\"3\":{}},\"comment\":{}}],[\"filesystemloggingplugin\",{\"_index\":304,\"name\":{\"487\":{}},\"comment\":{}}],[\"filesystemloggingpluginoptions\",{\"_index\":303,\"name\":{\"486\":{}},\"comment\":{}}],[\"filesystemmap\",{\"_index\":104,\"name\":{\"121\":{}},\"comment\":{}}],[\"finddefects\",{\"_index\":228,\"name\":{\"321\":{},\"327\":{}},\"comment\":{}}],[\"findtestcases\",{\"_index\":258,\"name\":{\"389\":{},\"397\":{},\"589\":{}},\"comment\":{}}],[\"first\",{\"_index\":206,\"name\":{\"269\":{},\"282\":{},\"305\":{},\"333\":{},\"364\":{},\"404\":{},\"702\":{}},\"comment\":{}}],[\"foreach\",{\"_index\":42,\"name\":{\"45\":{},\"127\":{}},\"comment\":{}}],[\"format\",{\"_index\":247,\"name\":{\"369\":{}},\"comment\":{}}],[\"full\",{\"_index\":93,\"name\":{\"109\":{}},\"comment\":{}}],[\"fullname\",{\"_index\":280,\"name\":{\"440\":{},\"458\":{}},\"comment\":{}}],[\"fullpathandfile\",{\"_index\":317,\"name\":{\"510\":{}},\"comment\":{}}],[\"fulltitle\",{\"_index\":321,\"name\":{\"525\":{},\"543\":{}},\"comment\":{}}],[\"func\",{\"_index\":56,\"name\":{\"61\":{}},\"comment\":{}}],[\"generatecapabilities\",{\"_index\":409,\"name\":{\"780\":{},\"820\":{},\"867\":{},\"902\":{}},\"comment\":{}}],[\"generateremoteoptions\",{\"_index\":451,\"name\":{\"979\":{},\"1016\":{},\"1105\":{},\"1134\":{}},\"comment\":{}}],[\"get\",{\"_index\":23,\"name\":{\"18\":{},\"22\":{},\"27\":{},\"29\":{},\"38\":{},\"46\":{},\"128\":{},\"299\":{}},\"comment\":{}}],[\"getapps\",{\"_index\":480,\"name\":{\"1088\":{}},\"comment\":{}}],[\"getdefect\",{\"_index\":227,\"name\":{\"320\":{},\"326\":{}},\"comment\":{}}],[\"getelement\",{\"_index\":374,\"name\":{\"656\":{},\"715\":{},\"921\":{}},\"comment\":{}}],[\"getelements\",{\"_index\":373,\"name\":{\"655\":{},\"714\":{},\"920\":{}},\"comment\":{}}],[\"getfacet\",{\"_index\":375,\"name\":{\"657\":{},\"689\":{},\"716\":{},\"797\":{},\"847\":{},\"892\":{},\"922\":{},\"993\":{},\"1039\":{},\"1126\":{}},\"comment\":{}}],[\"getroot\",{\"_index\":376,\"name\":{\"658\":{},\"717\":{},\"923\":{}},\"comment\":{}}],[\"gettestcase\",{\"_index\":257,\"name\":{\"388\":{},\"396\":{},\"588\":{}},\"comment\":{}}],[\"goto\",{\"_index\":415,\"name\":{\"798\":{},\"848\":{},\"893\":{}},\"comment\":{}}],[\"greaterthan\",{\"_index\":187,\"name\":{\"238\":{}},\"comment\":{}}],[\"handle\",{\"_index\":94,\"name\":{\"110\":{}},\"comment\":{}}],[\"has\",{\"_index\":43,\"name\":{\"47\":{},\"129\":{}},\"comment\":{}}],[\"havingvalue\",{\"_index\":186,\"name\":{\"237\":{}},\"comment\":{}}],[\"headers\",{\"_index\":495,\"name\":{\"1150\":{},\"1157\":{}},\"comment\":{}}],[\"hostname\",{\"_index\":113,\"name\":{\"144\":{}},\"comment\":{}}],[\"html\",{\"_index\":7,\"name\":{\"4\":{}},\"comment\":{}}],[\"htmlloggingplugin\",{\"_index\":314,\"name\":{\"504\":{}},\"comment\":{}}],[\"htmlloggingpluginoptions\",{\"_index\":313,\"name\":{\"503\":{}},\"comment\":{}}],[\"httpdata\",{\"_index\":501,\"name\":{\"1160\":{}},\"comment\":{}}],[\"httpmethod\",{\"_index\":492,\"name\":{\"1145\":{}},\"comment\":{}}],[\"httprequest\",{\"_index\":493,\"name\":{\"1146\":{}},\"comment\":{}}],[\"httpresponse\",{\"_index\":499,\"name\":{\"1155\":{}},\"comment\":{}}],[\"httpservice\",{\"_index\":489,\"name\":{\"1142\":{}},\"comment\":{}}],[\"iconfigprovider\",{\"_index\":29,\"name\":{\"28\":{}},\"comment\":{}}],[\"id\",{\"_index\":221,\"name\":{\"313\":{},\"411\":{}},\"comment\":{}}],[\"ihasconfig\",{\"_index\":30,\"name\":{\"30\":{}},\"comment\":{}}],[\"ihasoptions\",{\"_index\":32,\"name\":{\"32\":{}},\"comment\":{}}],[\"implicittimeout\",{\"_index\":408,\"name\":{\"779\":{},\"823\":{},\"870\":{},\"906\":{}},\"comment\":{}}],[\"includeresults\",{\"_index\":309,\"name\":{\"493\":{}},\"comment\":{}}],[\"index\",{\"_index\":365,\"name\":{\"634\":{},\"648\":{},\"720\":{},\"926\":{}},\"comment\":{}}],[\"info\",{\"_index\":239,\"name\":{\"351\":{}},\"comment\":{}}],[\"ip\",{\"_index\":112,\"name\":{\"143\":{}},\"comment\":{}}],[\"isconditionmet\",{\"_index\":141,\"name\":{\"186\":{}},\"comment\":{}}],[\"issuccessful\",{\"_index\":133,\"name\":{\"177\":{}},\"comment\":{}}],[\"istype\",{\"_index\":250,\"name\":{\"373\":{}},\"comment\":{}}],[\"iterator\",{\"_index\":50,\"name\":{\"54\":{},\"137\":{}},\"comment\":{}}],[\"jasmine\",{\"_index\":2,\"name\":{\"1\":{}},\"comment\":{}}],[\"jasminestarted\",{\"_index\":274,\"name\":{\"431\":{}},\"comment\":{}}],[\"jsonkey\",{\"_index\":57,\"name\":{\"63\":{}},\"comment\":{}}],[\"jsonobject\",{\"_index\":59,\"name\":{\"65\":{}},\"comment\":{}}],[\"jsonvalue\",{\"_index\":58,\"name\":{\"64\":{}},\"comment\":{}}],[\"key\",{\"_index\":424,\"name\":{\"814\":{},\"838\":{},\"1011\":{},\"1033\":{},\"1073\":{},\"1085\":{}},\"comment\":{}}],[\"keys\",{\"_index\":47,\"name\":{\"51\":{},\"133\":{}},\"comment\":{}}],[\"kinesisloggingplugin\",{\"_index\":285,\"name\":{\"461\":{}},\"comment\":{}}],[\"kinesisloggingpluginoptions\",{\"_index\":284,\"name\":{\"460\":{}},\"comment\":{}}],[\"lasterror\",{\"_index\":132,\"name\":{\"174\":{}},\"comment\":{}}],[\"lessthan\",{\"_index\":188,\"name\":{\"239\":{}},\"comment\":{}}],[\"level\",{\"_index\":232,\"name\":{\"341\":{},\"348\":{},\"379\":{},\"483\":{},\"500\":{},\"518\":{},\"612\":{}},\"comment\":{}}],[\"load\",{\"_index\":208,\"name\":{\"272\":{},\"285\":{},\"308\":{},\"336\":{},\"367\":{},\"407\":{},\"705\":{}},\"comment\":{}}],[\"local\",{\"_index\":425,\"name\":{\"815\":{},\"839\":{},\"1013\":{},\"1035\":{}},\"comment\":{}}],[\"localidentifier\",{\"_index\":426,\"name\":{\"816\":{},\"840\":{},\"1014\":{},\"1036\":{}},\"comment\":{}}],[\"locator\",{\"_index\":366,\"name\":{\"635\":{},\"652\":{},\"661\":{},\"711\":{},\"917\":{}},\"comment\":{}}],[\"lockduration\",{\"_index\":97,\"name\":{\"114\":{}},\"comment\":{}}],[\"lockname\",{\"_index\":96,\"name\":{\"113\":{}},\"comment\":{}}],[\"log\",{\"_index\":245,\"name\":{\"357\":{},\"380\":{},\"476\":{},\"495\":{},\"514\":{},\"607\":{}},\"comment\":{}}],[\"logging\",{\"_index\":4,\"name\":{\"2\":{},\"3\":{},\"4\":{}},\"comment\":{}}],[\"loggingplugin\",{\"_index\":253,\"name\":{\"376\":{}},\"comment\":{}}],[\"loggingpluginoptions\",{\"_index\":252,\"name\":{\"375\":{}},\"comment\":{}}],[\"loglevel\",{\"_index\":249,\"name\":{\"371\":{},\"372\":{}},\"comment\":{}}],[\"logmanager\",{\"_index\":234,\"name\":{\"344\":{},\"368\":{}},\"comment\":{}}],[\"logmanageroptions\",{\"_index\":233,\"name\":{\"343\":{}},\"comment\":{}}],[\"logmessagedata\",{\"_index\":231,\"name\":{\"338\":{}},\"comment\":{}}],[\"logmgr\",{\"_index\":78,\"name\":{\"89\":{},\"204\":{},\"278\":{},\"301\":{},\"329\":{},\"400\":{},\"441\":{},\"459\":{},\"526\":{},\"544\":{},\"587\":{},\"638\":{},\"647\":{},\"670\":{},\"677\":{},\"688\":{},\"699\":{},\"719\":{},\"746\":{},\"782\":{},\"804\":{},\"825\":{},\"853\":{},\"872\":{},\"898\":{},\"908\":{},\"925\":{},\"952\":{},\"984\":{},\"997\":{},\"1020\":{},\"1042\":{},\"1074\":{},\"1086\":{},\"1109\":{},\"1129\":{},\"1138\":{},\"1154\":{}},\"comment\":{}}],[\"logname\",{\"_index\":236,\"name\":{\"347\":{}},\"comment\":{}}],[\"logresult\",{\"_index\":246,\"name\":{\"358\":{},\"381\":{},\"477\":{},\"496\":{},\"515\":{},\"608\":{}},\"comment\":{}}],[\"logs\",{\"_index\":298,\"name\":{\"475\":{},\"512\":{},\"606\":{}},\"comment\":{}}],[\"machineinfo\",{\"_index\":115,\"name\":{\"146\":{}},\"comment\":{}}],[\"machineinfodata\",{\"_index\":111,\"name\":{\"141\":{}},\"comment\":{}}],[\"maxattempts\",{\"_index\":125,\"name\":{\"157\":{},\"171\":{}},\"comment\":{}}],[\"maxduration\",{\"_index\":128,\"name\":{\"161\":{},\"175\":{}},\"comment\":{}}],[\"maxlogcharacters\",{\"_index\":352,\"name\":{\"605\":{}},\"comment\":{}}],[\"maxloglines\",{\"_index\":318,\"name\":{\"511\":{}},\"comment\":{}}],[\"maxwaitms\",{\"_index\":369,\"name\":{\"639\":{},\"649\":{},\"662\":{},\"721\":{},\"927\":{}},\"comment\":{}}],[\"merge\",{\"_index\":67,\"name\":{\"75\":{}},\"comment\":{}}],[\"message\",{\"_index\":63,\"name\":{\"70\":{},\"99\":{},\"342\":{},\"1059\":{}},\"comment\":{}}],[\"metadata\",{\"_index\":269,\"name\":{\"425\":{}},\"comment\":{}}],[\"method\",{\"_index\":496,\"name\":{\"1151\":{}},\"comment\":{}}],[\"mobile\",{\"_index\":12,\"name\":{\"9\":{}},\"comment\":{}}],[\"mobileappelementoptions\",{\"_index\":441,\"name\":{\"913\":{}},\"comment\":{}}],[\"mobileappfacet\",{\"_index\":443,\"name\":{\"915\":{}},\"comment\":{}}],[\"mobileappfacetoptions\",{\"_index\":442,\"name\":{\"914\":{}},\"comment\":{}}],[\"mobileappsession\",{\"_index\":455,\"name\":{\"989\":{}},\"comment\":{}}],[\"mobileappsessiongeneratormgr\",{\"_index\":440,\"name\":{\"912\":{}},\"comment\":{}}],[\"mobileappsessiongeneratorplugin\",{\"_index\":449,\"name\":{\"976\":{}},\"comment\":{}}],[\"mobileappsessiongeneratorpluginoptions\",{\"_index\":448,\"name\":{\"975\":{}},\"comment\":{}}],[\"mobileappsessionoptions\",{\"_index\":454,\"name\":{\"988\":{}},\"comment\":{}}],[\"mobileappverifier\",{\"_index\":444,\"name\":{\"930\":{}},\"comment\":{}}],[\"mocha\",{\"_index\":8,\"name\":{\"5\":{}},\"comment\":{}}],[\"multipart\",{\"_index\":498,\"name\":{\"1153\":{}},\"comment\":{}}],[\"name\",{\"_index\":197,\"name\":{\"253\":{},\"340\":{}},\"comment\":{}}],[\"named\",{\"_index\":207,\"name\":{\"271\":{},\"284\":{},\"307\":{},\"335\":{},\"366\":{},\"406\":{},\"704\":{}},\"comment\":{}}],[\"newuisession\",{\"_index\":381,\"name\":{\"672\":{},\"697\":{},\"784\":{},\"819\":{},\"866\":{},\"901\":{},\"981\":{},\"1015\":{},\"1104\":{},\"1133\":{}},\"comment\":{}}],[\"not\",{\"_index\":189,\"name\":{\"240\":{}},\"comment\":{}}],[\"obj\",{\"_index\":61,\"name\":{\"68\":{}},\"comment\":{}}],[\"option\",{\"_index\":33,\"name\":{\"33\":{},\"249\":{},\"266\":{},\"279\":{},\"291\":{},\"302\":{},\"322\":{},\"330\":{},\"362\":{},\"383\":{},\"391\":{},\"401\":{},\"484\":{},\"501\":{},\"519\":{},\"595\":{},\"613\":{},\"646\":{},\"673\":{},\"685\":{},\"700\":{},\"718\":{},\"785\":{},\"802\":{},\"827\":{},\"851\":{},\"874\":{},\"896\":{},\"910\":{},\"924\":{},\"986\":{},\"995\":{},\"1022\":{},\"1040\":{},\"1082\":{},\"1111\":{},\"1127\":{},\"1140\":{}},\"comment\":{}}],[\"options\",{\"_index\":22,\"name\":{\"17\":{},\"255\":{}},\"comment\":{}}],[\"optionsprovider\",{\"_index\":35,\"name\":{\"35\":{}},\"comment\":{}}],[\"optmgr\",{\"_index\":34,\"name\":{\"34\":{}},\"comment\":{}}],[\"os\",{\"_index\":356,\"name\":{\"617\":{},\"626\":{}},\"comment\":{}}],[\"osversion\",{\"_index\":357,\"name\":{\"618\":{},\"627\":{}},\"comment\":{}}],[\"outputdir\",{\"_index\":316,\"name\":{\"509\":{}},\"comment\":{}}],[\"outputpath\",{\"_index\":308,\"name\":{\"492\":{}},\"comment\":{}}],[\"parent\",{\"_index\":367,\"name\":{\"636\":{},\"654\":{},\"713\":{},\"919\":{}},\"comment\":{}}],[\"parse\",{\"_index\":363,\"name\":{\"624\":{}},\"comment\":{}}],[\"pass\",{\"_index\":242,\"name\":{\"354\":{},\"448\":{},\"534\":{}},\"comment\":{}}],[\"pending\",{\"_index\":283,\"name\":{\"450\":{},\"536\":{}},\"comment\":{}}],[\"planid\",{\"_index\":329,\"name\":{\"556\":{},\"575\":{}},\"comment\":{}}],[\"platform\",{\"_index\":385,\"name\":{\"687\":{},\"803\":{},\"852\":{},\"897\":{},\"996\":{},\"1041\":{},\"1128\":{}},\"comment\":{}}],[\"plugin\",{\"_index\":193,\"name\":{\"245\":{}},\"comment\":{}}],[\"pluginconfig\",{\"_index\":196,\"name\":{\"251\":{}},\"comment\":{}}],[\"pluginconfigs\",{\"_index\":205,\"name\":{\"267\":{},\"280\":{},\"303\":{},\"331\":{},\"360\":{},\"402\":{},\"696\":{}},\"comment\":{}}],[\"pluginloader\",{\"_index\":199,\"name\":{\"256\":{}},\"comment\":{}}],[\"pluginmanager\",{\"_index\":202,\"name\":{\"260\":{}},\"comment\":{}}],[\"pluginmanageroptions\",{\"_index\":200,\"name\":{\"257\":{}},\"comment\":{}}],[\"pluginmanagerwithlogging\",{\"_index\":210,\"name\":{\"274\":{}},\"comment\":{}}],[\"pluginmanagerwithloggingoptions\",{\"_index\":209,\"name\":{\"273\":{}},\"comment\":{}}],[\"pluginoptions\",{\"_index\":191,\"name\":{\"242\":{}},\"comment\":{}}],[\"plugins\",{\"_index\":201,\"name\":{\"259\":{},\"268\":{},\"281\":{},\"304\":{},\"332\":{},\"363\":{},\"403\":{},\"701\":{}},\"comment\":{}}],[\"postdata\",{\"_index\":497,\"name\":{\"1152\":{}},\"comment\":{}}],[\"processingresult\",{\"_index\":60,\"name\":{\"66\":{}},\"comment\":{}}],[\"projectid\",{\"_index\":327,\"name\":{\"554\":{},\"573\":{}},\"comment\":{}}],[\"prototype\",{\"_index\":55,\"name\":{\"60\":{}},\"comment\":{}}],[\"rand\",{\"_index\":116,\"name\":{\"147\":{}},\"comment\":{}}],[\"recentgroupappsresponse\",{\"_index\":463,\"name\":{\"1043\":{}},\"comment\":{}}],[\"refresh\",{\"_index\":416,\"name\":{\"799\":{},\"849\":{},\"894\":{}},\"comment\":{}}],[\"region\",{\"_index\":293,\"name\":{\"470\":{}},\"comment\":{}}],[\"reject\",{\"_index\":130,\"name\":{\"164\":{},\"178\":{}},\"comment\":{}}],[\"rejectifunsuccessful\",{\"_index\":140,\"name\":{\"185\":{}},\"comment\":{}}],[\"replacewith\",{\"_index\":71,\"name\":{\"80\":{}},\"comment\":{}}],[\"reporter\",{\"_index\":3,\"name\":{\"1\":{},\"5\":{}},\"comment\":{}}],[\"resize\",{\"_index\":417,\"name\":{\"800\":{},\"850\":{},\"895\":{}},\"comment\":{}}],[\"resolution\",{\"_index\":406,\"name\":{\"777\":{},\"794\":{},\"821\":{},\"844\":{},\"868\":{},\"889\":{},\"904\":{}},\"comment\":{}}],[\"result\",{\"_index\":120,\"name\":{\"152\":{},\"166\":{},\"416\":{}},\"comment\":{}}],[\"resultid\",{\"_index\":268,\"name\":{\"422\":{}},\"comment\":{}}],[\"resultmessage\",{\"_index\":267,\"name\":{\"420\":{}},\"comment\":{}}],[\"retry\",{\"_index\":117,\"name\":{\"148\":{},\"189\":{}},\"comment\":{}}],[\"retryable\",{\"_index\":119,\"name\":{\"151\":{},\"165\":{}},\"comment\":{}}],[\"retrybackofftype\",{\"_index\":68,\"name\":{\"76\":{}},\"comment\":{}}],[\"retrydelaybackoff\",{\"_index\":371,\"name\":{\"641\":{},\"651\":{},\"664\":{},\"723\":{},\"929\":{}},\"comment\":{}}],[\"retrydelayms\",{\"_index\":370,\"name\":{\"640\":{},\"650\":{},\"663\":{},\"722\":{},\"928\":{}},\"comment\":{}}],[\"returns\",{\"_index\":166,\"name\":{\"216\":{},\"757\":{},\"963\":{}},\"comment\":{}}],[\"safestringoption\",{\"_index\":69,\"name\":{\"77\":{},\"81\":{}},\"comment\":{}}],[\"safestropt\",{\"_index\":217,\"name\":{\"296\":{}},\"comment\":{}}],[\"saucelabsbrowsersession\",{\"_index\":438,\"name\":{\"877\":{}},\"comment\":{}}],[\"saucelabsbrowsersessiongeneratorplugin\",{\"_index\":430,\"name\":{\"855\":{}},\"comment\":{}}],[\"saucelabsbrowsersessiongeneratorpluginoptions\",{\"_index\":429,\"name\":{\"854\":{}},\"comment\":{}}],[\"saucelabsbrowsersessionoptions\",{\"_index\":437,\"name\":{\"876\":{}},\"comment\":{}}],[\"saucelabsmobileappsession\",{\"_index\":486,\"name\":{\"1114\":{}},\"comment\":{}}],[\"saucelabsmobileappsessiongeneratorplugin\",{\"_index\":484,\"name\":{\"1092\":{}},\"comment\":{}}],[\"saucelabsmobileappsessiongeneratorpluginoptions\",{\"_index\":483,\"name\":{\"1091\":{}},\"comment\":{}}],[\"saucelabsmobileappsessionoptions\",{\"_index\":485,\"name\":{\"1113\":{}},\"comment\":{}}],[\"searchdirectory\",{\"_index\":198,\"name\":{\"254\":{}},\"comment\":{}}],[\"secretaccesskey\",{\"_index\":291,\"name\":{\"468\":{}},\"comment\":{}}],[\"seleniumgridsessiongeneratorplugin\",{\"_index\":439,\"name\":{\"899\":{}},\"comment\":{}}],[\"sendcommand\",{\"_index\":453,\"name\":{\"983\":{},\"1017\":{},\"1106\":{},\"1135\":{}},\"comment\":{}}],[\"services\",{\"_index\":15,\"name\":{\"10\":{}},\"comment\":{}}],[\"session\",{\"_index\":368,\"name\":{\"637\":{},\"653\":{},\"712\":{},\"731\":{},\"918\":{},\"937\":{}},\"comment\":{}}],[\"sessiongeneratormanager\",{\"_index\":397,\"name\":{\"730\":{},\"936\":{}},\"comment\":{}}],[\"sessionid\",{\"_index\":473,\"name\":{\"1057\":{}},\"comment\":{}}],[\"sessionoptions\",{\"_index\":398,\"name\":{\"732\":{},\"940\":{}},\"comment\":{}}],[\"sessiontoken\",{\"_index\":292,\"name\":{\"469\":{}},\"comment\":{}}],[\"set\",{\"_index\":44,\"name\":{\"48\":{},\"130\":{}},\"comment\":{}}],[\"setactual\",{\"_index\":179,\"name\":{\"230\":{}},\"comment\":{}}],[\"setplanid\",{\"_index\":339,\"name\":{\"576\":{}},\"comment\":{}}],[\"setsessionstatus\",{\"_index\":481,\"name\":{\"1089\":{}},\"comment\":{}}],[\"setsessionstatusrequest\",{\"_index\":472,\"name\":{\"1055\":{}},\"comment\":{}}],[\"setverbosity\",{\"_index\":83,\"name\":{\"97\":{}},\"comment\":{}}],[\"shareable_id\",{\"_index\":471,\"name\":{\"1054\":{},\"1068\":{}},\"comment\":{}}],[\"short\",{\"_index\":92,\"name\":{\"108\":{}},\"comment\":{}}],[\"shouldrun\",{\"_index\":259,\"name\":{\"390\":{},\"398\":{},\"451\":{},\"537\":{},\"590\":{}},\"comment\":{}}],[\"size\",{\"_index\":45,\"name\":{\"49\":{},\"131\":{}},\"comment\":{}}],[\"specdone\",{\"_index\":276,\"name\":{\"433\":{}},\"comment\":{}}],[\"specstarted\",{\"_index\":275,\"name\":{\"432\":{}},\"comment\":{}}],[\"stack\",{\"_index\":85,\"name\":{\"100\":{}},\"comment\":{}}],[\"startdelay\",{\"_index\":131,\"name\":{\"167\":{}},\"comment\":{}}],[\"status\",{\"_index\":224,\"name\":{\"316\":{},\"415\":{},\"421\":{},\"1058\":{}},\"comment\":{}}],[\"statuscode\",{\"_index\":500,\"name\":{\"1159\":{}},\"comment\":{}}],[\"step\",{\"_index\":240,\"name\":{\"352\":{}},\"comment\":{}}],[\"success\",{\"_index\":62,\"name\":{\"69\":{},\"163\":{}},\"comment\":{}}],[\"suiteids\",{\"_index\":328,\"name\":{\"555\":{},\"574\":{}},\"comment\":{}}],[\"test\",{\"_index\":279,\"name\":{\"439\":{},\"457\":{},\"524\":{},\"542\":{}},\"comment\":{}}],[\"testcase\",{\"_index\":263,\"name\":{\"409\":{}},\"comment\":{}}],[\"testcasemanager\",{\"_index\":261,\"name\":{\"394\":{}},\"comment\":{}}],[\"testcasemanageroptions\",{\"_index\":260,\"name\":{\"393\":{}},\"comment\":{}}],[\"testcaseplugin\",{\"_index\":256,\"name\":{\"386\":{}},\"comment\":{}}],[\"testcasepluginoptions\",{\"_index\":255,\"name\":{\"385\":{}},\"comment\":{}}],[\"testcases\",{\"_index\":262,\"name\":{\"408\":{},\"446\":{},\"532\":{}},\"comment\":{}}],[\"testid\",{\"_index\":266,\"name\":{\"419\":{}},\"comment\":{}}],[\"testmgr\",{\"_index\":157,\"name\":{\"205\":{},\"747\":{},\"953\":{}},\"comment\":{}}],[\"testrail\",{\"_index\":9,\"name\":{\"6\":{}},\"comment\":{}}],[\"testrailconfig\",{\"_index\":331,\"name\":{\"558\":{}},\"comment\":{}}],[\"testrailconfigoptions\",{\"_index\":324,\"name\":{\"549\":{}},\"comment\":{}}],[\"testrailloggingplugin\",{\"_index\":351,\"name\":{\"598\":{}},\"comment\":{}}],[\"testrailloggingpluginoptions\",{\"_index\":350,\"name\":{\"597\":{}},\"comment\":{}}],[\"testrailtestcaseplugin\",{\"_index\":343,\"name\":{\"580\":{}},\"comment\":{}}],[\"testrailtestcasepluginoptions\",{\"_index\":342,\"name\":{\"579\":{}},\"comment\":{}}],[\"testresult\",{\"_index\":265,\"name\":{\"417\":{}},\"comment\":{}}],[\"testresults\",{\"_index\":319,\"name\":{\"513\":{}},\"comment\":{}}],[\"teststatus\",{\"_index\":270,\"name\":{\"426\":{}},\"comment\":{}}],[\"then\",{\"_index\":142,\"name\":{\"187\":{},\"208\":{},\"750\":{},\"956\":{}},\"comment\":{}}],[\"title\",{\"_index\":222,\"name\":{\"314\":{},\"413\":{}},\"comment\":{}}],[\"toconsole\",{\"_index\":248,\"name\":{\"370\":{}},\"comment\":{}}],[\"toobject\",{\"_index\":491,\"name\":{\"1144\":{}},\"comment\":{}}],[\"tostring\",{\"_index\":86,\"name\":{\"101\":{},\"631\":{}},\"comment\":{}}],[\"tostringtag\",{\"_index\":51,\"name\":{\"55\":{},\"138\":{}},\"comment\":{}}],[\"totalattempts\",{\"_index\":126,\"name\":{\"158\":{},\"172\":{}},\"comment\":{}}],[\"totalduration\",{\"_index\":129,\"name\":{\"162\":{},\"176\":{}},\"comment\":{}}],[\"tovalue\",{\"_index\":251,\"name\":{\"374\":{}},\"comment\":{}}],[\"trace\",{\"_index\":237,\"name\":{\"349\":{}},\"comment\":{}}],[\"trconfig\",{\"_index\":341,\"name\":{\"578\":{}},\"comment\":{}}],[\"tunnel\",{\"_index\":435,\"name\":{\"863\":{},\"885\":{},\"1101\":{},\"1122\":{}},\"comment\":{}}],[\"tunnelidentifier\",{\"_index\":436,\"name\":{\"864\":{},\"886\":{},\"1102\":{},\"1123\":{}},\"comment\":{}}],[\"type\",{\"_index\":84,\"name\":{\"98\":{}},\"comment\":{}}],[\"ui\",{\"_index\":10,\"name\":{\"7\":{},\"8\":{},\"9\":{}},\"comment\":{}}],[\"uielementoptions\",{\"_index\":377,\"name\":{\"659\":{}},\"comment\":{}}],[\"uifacet\",{\"_index\":372,\"name\":{\"642\":{}},\"comment\":{}}],[\"uifacetoptions\",{\"_index\":364,\"name\":{\"632\":{}},\"comment\":{}}],[\"uiplatform\",{\"_index\":361,\"name\":{\"622\":{},\"671\":{},\"678\":{},\"695\":{},\"783\":{},\"793\":{},\"826\":{},\"843\":{},\"873\":{},\"888\":{},\"909\":{},\"985\":{},\"1021\":{},\"1110\":{},\"1139\":{}},\"comment\":{}}],[\"uisession\",{\"_index\":384,\"name\":{\"680\":{}},\"comment\":{}}],[\"uisessiongeneratormanager\",{\"_index\":387,\"name\":{\"692\":{}},\"comment\":{}}],[\"uisessiongeneratormanageroptions\",{\"_index\":386,\"name\":{\"691\":{}},\"comment\":{}}],[\"uisessiongeneratorplugin\",{\"_index\":379,\"name\":{\"666\":{}},\"comment\":{}}],[\"uisessiongeneratorpluginoptions\",{\"_index\":378,\"name\":{\"665\":{}},\"comment\":{}}],[\"uisessionoptions\",{\"_index\":382,\"name\":{\"675\":{}},\"comment\":{}}],[\"uitestplatformoptions\",{\"_index\":355,\"name\":{\"615\":{}},\"comment\":{}}],[\"unlock\",{\"_index\":101,\"name\":{\"118\":{}},\"comment\":{}}],[\"until\",{\"_index\":136,\"name\":{\"181\":{}},\"comment\":{}}],[\"uploadapp\",{\"_index\":479,\"name\":{\"1087\":{}},\"comment\":{}}],[\"uploaded_at\",{\"_index\":469,\"name\":{\"1052\":{}},\"comment\":{}}],[\"uploadrequest\",{\"_index\":474,\"name\":{\"1060\":{}},\"comment\":{}}],[\"uploadresponse\",{\"_index\":476,\"name\":{\"1064\":{}},\"comment\":{}}],[\"url\",{\"_index\":325,\"name\":{\"551\":{},\"570\":{},\"776\":{},\"818\":{},\"865\":{},\"903\":{},\"1148\":{}},\"comment\":{}}],[\"user\",{\"_index\":114,\"name\":{\"145\":{},\"552\":{},\"571\":{},\"813\":{},\"837\":{},\"1010\":{},\"1032\":{},\"1072\":{},\"1084\":{}},\"comment\":{}}],[\"username\",{\"_index\":434,\"name\":{\"861\":{},\"883\":{},\"1099\":{},\"1120\":{}},\"comment\":{}}],[\"using\",{\"_index\":144,\"name\":{\"190\":{}},\"comment\":{}}],[\"validuntil\",{\"_index\":65,\"name\":{\"73\":{}},\"comment\":{}}],[\"values\",{\"_index\":48,\"name\":{\"52\":{},\"134\":{}},\"comment\":{}}],[\"varprefix\",{\"_index\":28,\"name\":{\"26\":{}},\"comment\":{}}],[\"verbosity\",{\"_index\":80,\"name\":{\"91\":{},\"96\":{}},\"comment\":{}}],[\"verifier\",{\"_index\":145,\"name\":{\"191\":{}},\"comment\":{}}],[\"verifiermatcher\",{\"_index\":177,\"name\":{\"228\":{}},\"comment\":{}}],[\"verify\",{\"_index\":162,\"name\":{\"212\":{},\"227\":{},\"753\":{},\"959\":{}},\"comment\":{}}],[\"verifywithbrowser\",{\"_index\":401,\"name\":{\"768\":{}},\"comment\":{}}],[\"verifywithmobileapp\",{\"_index\":447,\"name\":{\"974\":{}},\"comment\":{}}],[\"wait\",{\"_index\":190,\"name\":{\"241\":{}},\"comment\":{}}],[\"waitduration\",{\"_index\":98,\"name\":{\"115\":{}},\"comment\":{}}],[\"warn\",{\"_index\":241,\"name\":{\"353\":{}},\"comment\":{}}],[\"web\",{\"_index\":14,\"name\":{\"10\":{}},\"comment\":{}}],[\"webelementoptions\",{\"_index\":390,\"name\":{\"707\":{}},\"comment\":{}}],[\"withbackoff\",{\"_index\":135,\"name\":{\"180\":{}},\"comment\":{}}],[\"withbrowsersessiongeneratormanager\",{\"_index\":400,\"name\":{\"734\":{}},\"comment\":{}}],[\"withbrowsersessionoptions\",{\"_index\":399,\"name\":{\"733\":{}},\"comment\":{}}],[\"withbuildinfomanager\",{\"_index\":170,\"name\":{\"220\":{},\"761\":{},\"967\":{}},\"comment\":{}}],[\"withdefectmanager\",{\"_index\":169,\"name\":{\"219\":{},\"760\":{},\"966\":{}},\"comment\":{}}],[\"withdescription\",{\"_index\":163,\"name\":{\"213\":{},\"754\":{},\"960\":{}},\"comment\":{}}],[\"withfailaction\",{\"_index\":138,\"name\":{\"183\":{}},\"comment\":{}}],[\"withknowndefectids\",{\"_index\":165,\"name\":{\"215\":{},\"756\":{},\"962\":{}},\"comment\":{}}],[\"withlogmanager\",{\"_index\":167,\"name\":{\"217\":{},\"758\":{},\"964\":{}},\"comment\":{}}],[\"withmaxattempts\",{\"_index\":137,\"name\":{\"182\":{}},\"comment\":{}}],[\"withmaxduration\",{\"_index\":139,\"name\":{\"184\":{}},\"comment\":{}}],[\"withmobileappsessiongeneratormanager\",{\"_index\":446,\"name\":{\"939\":{}},\"comment\":{}}],[\"withmobileappsessionoptions\",{\"_index\":445,\"name\":{\"938\":{}},\"comment\":{}}],[\"withstartdelaybetweenattempts\",{\"_index\":134,\"name\":{\"179\":{}},\"comment\":{}}],[\"withtestcasemanager\",{\"_index\":168,\"name\":{\"218\":{},\"759\":{},\"965\":{}},\"comment\":{}}],[\"withtestids\",{\"_index\":164,\"name\":{\"214\":{},\"755\":{},\"961\":{}},\"comment\":{}}],[\"xml\",{\"_index\":490,\"name\":{\"1143\":{}},\"comment\":{}}]],\"pipeline\":[]}}"); \ No newline at end of file +window.searchData = JSON.parse("{\"kinds\":{\"2\":\"Module\",\"4\":\"Namespace\",\"32\":\"Variable\",\"64\":\"Function\",\"128\":\"Class\",\"256\":\"Interface\",\"512\":\"Constructor\",\"1024\":\"Property\",\"2048\":\"Method\",\"65536\":\"Type literal\",\"262144\":\"Accessor\",\"4194304\":\"Type alias\"},\"rows\":[{\"kind\":2,\"name\":\"aft-core\",\"url\":\"modules/aft_core.html\",\"classes\":\"tsd-kind-module\"},{\"kind\":2,\"name\":\"aft-jasmine-reporter\",\"url\":\"modules/aft_jasmine_reporter.html\",\"classes\":\"tsd-kind-module\"},{\"kind\":2,\"name\":\"aft-mocha-reporter\",\"url\":\"modules/aft_mocha_reporter.html\",\"classes\":\"tsd-kind-module\"},{\"kind\":2,\"name\":\"aft-reporting-aws-kinesis-firehose\",\"url\":\"modules/aft_reporting_aws_kinesis_firehose.html\",\"classes\":\"tsd-kind-module\"},{\"kind\":2,\"name\":\"aft-reporting-filesystem\",\"url\":\"modules/aft_reporting_filesystem.html\",\"classes\":\"tsd-kind-module\"},{\"kind\":2,\"name\":\"aft-reporting-html\",\"url\":\"modules/aft_reporting_html.html\",\"classes\":\"tsd-kind-module\"},{\"kind\":2,\"name\":\"aft-testrail\",\"url\":\"modules/aft_testrail.html\",\"classes\":\"tsd-kind-module\"},{\"kind\":2,\"name\":\"aft-ui\",\"url\":\"modules/aft_ui.html\",\"classes\":\"tsd-kind-module\"},{\"kind\":2,\"name\":\"aft-ui-selenium\",\"url\":\"modules/aft_ui_selenium.html\",\"classes\":\"tsd-kind-module\"},{\"kind\":2,\"name\":\"aft-ui-webdriverio\",\"url\":\"modules/aft_ui_webdriverio.html\",\"classes\":\"tsd-kind-module\"},{\"kind\":2,\"name\":\"aft-web-services\",\"url\":\"modules/aft_web_services.html\",\"classes\":\"tsd-kind-module\"},{\"kind\":128,\"name\":\"AftConfig\",\"url\":\"classes/aft_core.AftConfig.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_core.AftConfig.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-core.AftConfig\"},{\"kind\":1024,\"name\":\"_cfg\",\"url\":\"classes/aft_core.AftConfig.html#_cfg\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.AftConfig\"},{\"kind\":1024,\"name\":\"_valueCache\",\"url\":\"classes/aft_core.AftConfig.html#_valueCache\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.AftConfig\"},{\"kind\":1024,\"name\":\"_sectionCache\",\"url\":\"classes/aft_core.AftConfig.html#_sectionCache\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.AftConfig\"},{\"kind\":262144,\"name\":\"pluginsSearchDir\",\"url\":\"classes/aft_core.AftConfig.html#pluginsSearchDir\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.AftConfig\"},{\"kind\":262144,\"name\":\"pluginNames\",\"url\":\"classes/aft_core.AftConfig.html#pluginNames\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.AftConfig\"},{\"kind\":262144,\"name\":\"logLevel\",\"url\":\"classes/aft_core.AftConfig.html#logLevel\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.AftConfig\"},{\"kind\":262144,\"name\":\"fileLockMaxWait\",\"url\":\"classes/aft_core.AftConfig.html#fileLockMaxWait\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.AftConfig\"},{\"kind\":262144,\"name\":\"fileLockMaxHold\",\"url\":\"classes/aft_core.AftConfig.html#fileLockMaxHold\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.AftConfig\"},{\"kind\":262144,\"name\":\"fsMapDirectory\",\"url\":\"classes/aft_core.AftConfig.html#fsMapDirectory\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.AftConfig\"},{\"kind\":262144,\"name\":\"retryMaxAttempts\",\"url\":\"classes/aft_core.AftConfig.html#retryMaxAttempts\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.AftConfig\"},{\"kind\":262144,\"name\":\"retryBackOffType\",\"url\":\"classes/aft_core.AftConfig.html#retryBackOffType\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.AftConfig\"},{\"kind\":262144,\"name\":\"retryDelayMs\",\"url\":\"classes/aft_core.AftConfig.html#retryDelayMs\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.AftConfig\"},{\"kind\":262144,\"name\":\"retryMaxDurationMs\",\"url\":\"classes/aft_core.AftConfig.html#retryMaxDurationMs\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.AftConfig\"},{\"kind\":262144,\"name\":\"retryRejectOnFail\",\"url\":\"classes/aft_core.AftConfig.html#retryRejectOnFail\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.AftConfig\"},{\"kind\":2048,\"name\":\"get\",\"url\":\"classes/aft_core.AftConfig.html#get\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.AftConfig\"},{\"kind\":2048,\"name\":\"set\",\"url\":\"classes/aft_core.AftConfig.html#set\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.AftConfig\"},{\"kind\":2048,\"name\":\"getSection\",\"url\":\"classes/aft_core.AftConfig.html#getSection\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.AftConfig\"},{\"kind\":2048,\"name\":\"setSection\",\"url\":\"classes/aft_core.AftConfig.html#setSection\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.AftConfig\"},{\"kind\":2048,\"name\":\"processProperties\",\"url\":\"classes/aft_core.AftConfig.html#processProperties\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.AftConfig\"},{\"kind\":2048,\"name\":\"processEnvVars\",\"url\":\"classes/aft_core.AftConfig.html#processEnvVars\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.AftConfig\"},{\"kind\":32,\"name\":\"aftConfig\",\"url\":\"variables/aft_core.aftConfig-1.html\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":128,\"name\":\"CacheMap\",\"url\":\"classes/aft_core.CacheMap.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_core.CacheMap.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-core.CacheMap\"},{\"kind\":1024,\"name\":\"_internalMap\",\"url\":\"classes/aft_core.CacheMap.html#_internalMap\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.CacheMap\"},{\"kind\":1024,\"name\":\"_cacheDuration\",\"url\":\"classes/aft_core.CacheMap.html#_cacheDuration\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.CacheMap\"},{\"kind\":2048,\"name\":\"clear\",\"url\":\"classes/aft_core.CacheMap.html#clear\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.CacheMap\"},{\"kind\":2048,\"name\":\"delete\",\"url\":\"classes/aft_core.CacheMap.html#delete\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.CacheMap\"},{\"kind\":2048,\"name\":\"forEach\",\"url\":\"classes/aft_core.CacheMap.html#forEach\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.CacheMap\"},{\"kind\":2048,\"name\":\"get\",\"url\":\"classes/aft_core.CacheMap.html#get\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.CacheMap\"},{\"kind\":2048,\"name\":\"has\",\"url\":\"classes/aft_core.CacheMap.html#has\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.CacheMap\"},{\"kind\":2048,\"name\":\"set\",\"url\":\"classes/aft_core.CacheMap.html#set\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.CacheMap\"},{\"kind\":262144,\"name\":\"size\",\"url\":\"classes/aft_core.CacheMap.html#size\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.CacheMap\"},{\"kind\":2048,\"name\":\"entries\",\"url\":\"classes/aft_core.CacheMap.html#entries\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.CacheMap\"},{\"kind\":2048,\"name\":\"keys\",\"url\":\"classes/aft_core.CacheMap.html#keys\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.CacheMap\"},{\"kind\":2048,\"name\":\"values\",\"url\":\"classes/aft_core.CacheMap.html#values\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.CacheMap\"},{\"kind\":2048,\"name\":\"_isStillValid\",\"url\":\"classes/aft_core.CacheMap.html#_isStillValid\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.CacheMap\"},{\"kind\":2048,\"name\":\"[iterator]\",\"url\":\"classes/aft_core.CacheMap.html#_iterator_\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.CacheMap\"},{\"kind\":262144,\"name\":\"[toStringTag]\",\"url\":\"classes/aft_core.CacheMap.html#_toStringTag_\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.CacheMap\"},{\"kind\":4194304,\"name\":\"SafeStringOption\",\"url\":\"types/aft_core.SafeStringOption-1.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_core.SafeStringOption-1.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-core.SafeStringOption\"},{\"kind\":1024,\"name\":\"exclude\",\"url\":\"types/aft_core.SafeStringOption-1.html#__type.exclude\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.SafeStringOption.__type\"},{\"kind\":1024,\"name\":\"replaceWith\",\"url\":\"types/aft_core.SafeStringOption-1.html#__type.replaceWith\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.SafeStringOption.__type\"},{\"kind\":4,\"name\":\"SafeStringOption\",\"url\":\"modules/aft_core.SafeStringOption.html\",\"classes\":\"tsd-kind-namespace tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":32,\"name\":\"defaults\",\"url\":\"variables/aft_core.SafeStringOption.defaults.html\",\"classes\":\"tsd-kind-variable tsd-parent-kind-namespace\",\"parent\":\"aft-core.SafeStringOption\"},{\"kind\":32,\"name\":\"convert\",\"url\":\"variables/aft_core.convert.html\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":4194304,\"name\":\"Action\",\"url\":\"types/aft_core.Action.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_core.Action.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-core.Action\"},{\"kind\":4194304,\"name\":\"Class\",\"url\":\"types/aft_core.Class.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_core.Class.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-core.Class\"},{\"kind\":1024,\"name\":\"prototype\",\"url\":\"types/aft_core.Class.html#__type.prototype\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.Class.__type\"},{\"kind\":4194304,\"name\":\"Func\",\"url\":\"types/aft_core.Func.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_core.Func.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-core.Func\"},{\"kind\":4194304,\"name\":\"JsonKey\",\"url\":\"types/aft_core.JsonKey.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":4194304,\"name\":\"JsonValue\",\"url\":\"types/aft_core.JsonValue.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":4194304,\"name\":\"JsonObject\",\"url\":\"types/aft_core.JsonObject.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":4194304,\"name\":\"ProcessingResult\",\"url\":\"types/aft_core.ProcessingResult.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_core.ProcessingResult.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-core.ProcessingResult\"},{\"kind\":1024,\"name\":\"result\",\"url\":\"types/aft_core.ProcessingResult.html#__type.result\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.ProcessingResult.__type\"},{\"kind\":1024,\"name\":\"message\",\"url\":\"types/aft_core.ProcessingResult.html#__type.message\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.ProcessingResult.__type\"},{\"kind\":4194304,\"name\":\"CacheObject\",\"url\":\"types/aft_core.CacheObject.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_core.CacheObject.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-core.CacheObject\"},{\"kind\":1024,\"name\":\"validUntil\",\"url\":\"types/aft_core.CacheObject.html#__type.validUntil\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.CacheObject.__type\"},{\"kind\":1024,\"name\":\"data\",\"url\":\"types/aft_core.CacheObject.html#__type.data\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.CacheObject.__type\"},{\"kind\":4194304,\"name\":\"Merge\",\"url\":\"types/aft_core.Merge.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":4194304,\"name\":\"RetryBackOffType\",\"url\":\"types/aft_core.RetryBackOffType.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":4194304,\"name\":\"EllipsisLocation\",\"url\":\"types/aft_core.EllipsisLocation.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":64,\"name\":\"ellide\",\"url\":\"functions/aft_core.ellide.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":4194304,\"name\":\"ErrVerbosity\",\"url\":\"types/aft_core.ErrVerbosity.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":4194304,\"name\":\"ErrOptions\",\"url\":\"types/aft_core.ErrOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_core.ErrOptions.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-core.ErrOptions\"},{\"kind\":1024,\"name\":\"logger\",\"url\":\"types/aft_core.ErrOptions.html#__type.logger\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.ErrOptions.__type\"},{\"kind\":1024,\"name\":\"errLevel\",\"url\":\"types/aft_core.ErrOptions.html#__type.errLevel\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.ErrOptions.__type\"},{\"kind\":1024,\"name\":\"verbosity\",\"url\":\"types/aft_core.ErrOptions.html#__type.verbosity\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.ErrOptions.__type\"},{\"kind\":128,\"name\":\"Err\",\"url\":\"classes/aft_core.Err-1.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_core.Err-1.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-core.Err\"},{\"kind\":1024,\"name\":\"err\",\"url\":\"classes/aft_core.Err-1.html#err\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-core.Err\"},{\"kind\":1024,\"name\":\"_verbosity\",\"url\":\"classes/aft_core.Err-1.html#_verbosity\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Err\"},{\"kind\":262144,\"name\":\"verbosity\",\"url\":\"classes/aft_core.Err-1.html#verbosity\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Err\"},{\"kind\":2048,\"name\":\"setVerbosity\",\"url\":\"classes/aft_core.Err-1.html#setVerbosity\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Err\"},{\"kind\":262144,\"name\":\"type\",\"url\":\"classes/aft_core.Err-1.html#type\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Err\"},{\"kind\":262144,\"name\":\"message\",\"url\":\"classes/aft_core.Err-1.html#message\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Err\"},{\"kind\":262144,\"name\":\"stack\",\"url\":\"classes/aft_core.Err-1.html#stack\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Err\"},{\"kind\":2048,\"name\":\"toString\",\"url\":\"classes/aft_core.Err-1.html#toString\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Err\"},{\"kind\":2048,\"name\":\"_isError\",\"url\":\"classes/aft_core.Err-1.html#_isError\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Err\"},{\"kind\":2048,\"name\":\"_processMessage\",\"url\":\"classes/aft_core.Err-1.html#_processMessage\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Err\"},{\"kind\":2048,\"name\":\"_processStack\",\"url\":\"classes/aft_core.Err-1.html#_processStack\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Err\"},{\"kind\":2048,\"name\":\"_removeInternalStackLines\",\"url\":\"classes/aft_core.Err-1.html#_removeInternalStackLines\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Err\"},{\"kind\":2048,\"name\":\"_removeNewlinesAndExtraWhitespace\",\"url\":\"classes/aft_core.Err-1.html#_removeNewlinesAndExtraWhitespace\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Err\"},{\"kind\":4,\"name\":\"Err\",\"url\":\"modules/aft_core.Err.html\",\"classes\":\"tsd-kind-namespace tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":64,\"name\":\"short\",\"url\":\"functions/aft_core.Err.short.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-namespace\",\"parent\":\"aft-core.Err\"},{\"kind\":64,\"name\":\"full\",\"url\":\"functions/aft_core.Err.full.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-namespace\",\"parent\":\"aft-core.Err\"},{\"kind\":64,\"name\":\"handle\",\"url\":\"functions/aft_core.Err.handle.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-namespace\",\"parent\":\"aft-core.Err\"},{\"kind\":64,\"name\":\"handleAsync\",\"url\":\"functions/aft_core.Err.handleAsync.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-namespace\",\"parent\":\"aft-core.Err\"},{\"kind\":128,\"name\":\"ExpiringFileLock\",\"url\":\"classes/aft_core.ExpiringFileLock-1.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_core.ExpiringFileLock-1.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-core.ExpiringFileLock\"},{\"kind\":1024,\"name\":\"aftCfg\",\"url\":\"classes/aft_core.ExpiringFileLock-1.html#aftCfg\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-core.ExpiringFileLock\"},{\"kind\":1024,\"name\":\"lockName\",\"url\":\"classes/aft_core.ExpiringFileLock-1.html#lockName\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-core.ExpiringFileLock\"},{\"kind\":1024,\"name\":\"lockDuration\",\"url\":\"classes/aft_core.ExpiringFileLock-1.html#lockDuration\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-core.ExpiringFileLock\"},{\"kind\":1024,\"name\":\"waitDuration\",\"url\":\"classes/aft_core.ExpiringFileLock-1.html#waitDuration\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-core.ExpiringFileLock\"},{\"kind\":1024,\"name\":\"_lockFileDescriptor\",\"url\":\"classes/aft_core.ExpiringFileLock-1.html#_lockFileDescriptor\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.ExpiringFileLock\"},{\"kind\":1024,\"name\":\"_timeout\",\"url\":\"classes/aft_core.ExpiringFileLock-1.html#_timeout\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.ExpiringFileLock\"},{\"kind\":2048,\"name\":\"unlock\",\"url\":\"classes/aft_core.ExpiringFileLock-1.html#unlock\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.ExpiringFileLock\"},{\"kind\":2048,\"name\":\"_waitForLock\",\"url\":\"classes/aft_core.ExpiringFileLock-1.html#_waitForLock\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.ExpiringFileLock\"},{\"kind\":4,\"name\":\"ExpiringFileLock\",\"url\":\"modules/aft_core.ExpiringFileLock.html\",\"classes\":\"tsd-kind-namespace tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":64,\"name\":\"get\",\"url\":\"functions/aft_core.ExpiringFileLock.get.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-namespace\",\"parent\":\"aft-core.ExpiringFileLock\"},{\"kind\":32,\"name\":\"fileio\",\"url\":\"variables/aft_core.fileio.html\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":128,\"name\":\"FileSystemMap\",\"url\":\"classes/aft_core.FileSystemMap.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_core.FileSystemMap.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-core.FileSystemMap\"},{\"kind\":1024,\"name\":\"filename\",\"url\":\"classes/aft_core.FileSystemMap.html#filename\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-core.FileSystemMap\"},{\"kind\":1024,\"name\":\"_memoryMap\",\"url\":\"classes/aft_core.FileSystemMap.html#_memoryMap\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.FileSystemMap\"},{\"kind\":1024,\"name\":\"_aftCfg\",\"url\":\"classes/aft_core.FileSystemMap.html#_aftCfg\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.FileSystemMap\"},{\"kind\":2048,\"name\":\"clear\",\"url\":\"classes/aft_core.FileSystemMap.html#clear\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.FileSystemMap\"},{\"kind\":2048,\"name\":\"delete\",\"url\":\"classes/aft_core.FileSystemMap.html#delete\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.FileSystemMap\"},{\"kind\":2048,\"name\":\"forEach\",\"url\":\"classes/aft_core.FileSystemMap.html#forEach\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.FileSystemMap\"},{\"kind\":2048,\"name\":\"get\",\"url\":\"classes/aft_core.FileSystemMap.html#get\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.FileSystemMap\"},{\"kind\":2048,\"name\":\"has\",\"url\":\"classes/aft_core.FileSystemMap.html#has\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.FileSystemMap\"},{\"kind\":2048,\"name\":\"set\",\"url\":\"classes/aft_core.FileSystemMap.html#set\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.FileSystemMap\"},{\"kind\":262144,\"name\":\"size\",\"url\":\"classes/aft_core.FileSystemMap.html#size\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.FileSystemMap\"},{\"kind\":2048,\"name\":\"entries\",\"url\":\"classes/aft_core.FileSystemMap.html#entries\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.FileSystemMap\"},{\"kind\":2048,\"name\":\"keys\",\"url\":\"classes/aft_core.FileSystemMap.html#keys\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.FileSystemMap\"},{\"kind\":2048,\"name\":\"values\",\"url\":\"classes/aft_core.FileSystemMap.html#values\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.FileSystemMap\"},{\"kind\":2048,\"name\":\"_writeToFile\",\"url\":\"classes/aft_core.FileSystemMap.html#_writeToFile\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.FileSystemMap\"},{\"kind\":2048,\"name\":\"_updateMemoryMap\",\"url\":\"classes/aft_core.FileSystemMap.html#_updateMemoryMap\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.FileSystemMap\"},{\"kind\":2048,\"name\":\"[iterator]\",\"url\":\"classes/aft_core.FileSystemMap.html#_iterator_\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.FileSystemMap\"},{\"kind\":262144,\"name\":\"[toStringTag]\",\"url\":\"classes/aft_core.FileSystemMap.html#_toStringTag_\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.FileSystemMap\"},{\"kind\":4194304,\"name\":\"MachineInfoData\",\"url\":\"types/aft_core.MachineInfoData.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_core.MachineInfoData.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-core.MachineInfoData\"},{\"kind\":1024,\"name\":\"ip\",\"url\":\"types/aft_core.MachineInfoData.html#__type.ip\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.MachineInfoData.__type\"},{\"kind\":1024,\"name\":\"hostname\",\"url\":\"types/aft_core.MachineInfoData.html#__type.hostname\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.MachineInfoData.__type\"},{\"kind\":1024,\"name\":\"user\",\"url\":\"types/aft_core.MachineInfoData.html#__type.user\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.MachineInfoData.__type\"},{\"kind\":32,\"name\":\"machineInfo\",\"url\":\"variables/aft_core.machineInfo.html\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":32,\"name\":\"rand\",\"url\":\"variables/aft_core.rand.html\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":128,\"name\":\"Retry\",\"url\":\"classes/aft_core.Retry.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":2048,\"name\":\"calculateBackOffDelay\",\"url\":\"classes/aft_core.Retry.html#calculateBackOffDelay\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_core.Retry.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":1024,\"name\":\"_aftCfg\",\"url\":\"classes/aft_core.Retry.html#_aftCfg\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Retry\"},{\"kind\":1024,\"name\":\"_retryable\",\"url\":\"classes/aft_core.Retry.html#_retryable\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Retry\"},{\"kind\":1024,\"name\":\"_condition\",\"url\":\"classes/aft_core.Retry.html#_condition\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Retry\"},{\"kind\":1024,\"name\":\"_delay\",\"url\":\"classes/aft_core.Retry.html#_delay\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Retry\"},{\"kind\":1024,\"name\":\"_backOffType\",\"url\":\"classes/aft_core.Retry.html#_backOffType\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Retry\"},{\"kind\":1024,\"name\":\"_maxAttempts\",\"url\":\"classes/aft_core.Retry.html#_maxAttempts\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Retry\"},{\"kind\":1024,\"name\":\"_maxDuration\",\"url\":\"classes/aft_core.Retry.html#_maxDuration\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Retry\"},{\"kind\":1024,\"name\":\"_reject\",\"url\":\"classes/aft_core.Retry.html#_reject\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Retry\"},{\"kind\":1024,\"name\":\"_currentDelay\",\"url\":\"classes/aft_core.Retry.html#_currentDelay\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Retry\"},{\"kind\":1024,\"name\":\"_result\",\"url\":\"classes/aft_core.Retry.html#_result\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Retry\"},{\"kind\":1024,\"name\":\"_success\",\"url\":\"classes/aft_core.Retry.html#_success\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Retry\"},{\"kind\":1024,\"name\":\"_totalAttempts\",\"url\":\"classes/aft_core.Retry.html#_totalAttempts\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Retry\"},{\"kind\":1024,\"name\":\"_totalDuration\",\"url\":\"classes/aft_core.Retry.html#_totalDuration\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Retry\"},{\"kind\":1024,\"name\":\"_failAction\",\"url\":\"classes/aft_core.Retry.html#_failAction\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Retry\"},{\"kind\":1024,\"name\":\"_err\",\"url\":\"classes/aft_core.Retry.html#_err\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Retry\"},{\"kind\":262144,\"name\":\"result\",\"url\":\"classes/aft_core.Retry.html#result\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":262144,\"name\":\"totalAttempts\",\"url\":\"classes/aft_core.Retry.html#totalAttempts\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":262144,\"name\":\"lastError\",\"url\":\"classes/aft_core.Retry.html#lastError\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":262144,\"name\":\"totalDuration\",\"url\":\"classes/aft_core.Retry.html#totalDuration\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":262144,\"name\":\"isSuccessful\",\"url\":\"classes/aft_core.Retry.html#isSuccessful\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":2048,\"name\":\"until\",\"url\":\"classes/aft_core.Retry.html#until\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":2048,\"name\":\"withDelay\",\"url\":\"classes/aft_core.Retry.html#withDelay\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":2048,\"name\":\"withBackOff\",\"url\":\"classes/aft_core.Retry.html#withBackOff\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":2048,\"name\":\"withMaxDuration\",\"url\":\"classes/aft_core.Retry.html#withMaxDuration\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":2048,\"name\":\"withMaxAttempts\",\"url\":\"classes/aft_core.Retry.html#withMaxAttempts\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":2048,\"name\":\"withRejectOnFail\",\"url\":\"classes/aft_core.Retry.html#withRejectOnFail\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":2048,\"name\":\"withFailAction\",\"url\":\"classes/aft_core.Retry.html#withFailAction\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":2048,\"name\":\"_isConditionMet\",\"url\":\"classes/aft_core.Retry.html#_isConditionMet\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Retry\"},{\"kind\":2048,\"name\":\"then\",\"url\":\"classes/aft_core.Retry.html#then\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Retry\"},{\"kind\":2048,\"name\":\"_getInnerPromise\",\"url\":\"classes/aft_core.Retry.html#_getInnerPromise\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Retry\"},{\"kind\":64,\"name\":\"retry\",\"url\":\"functions/aft_core.retry-1.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":64,\"name\":\"using\",\"url\":\"functions/aft_core.using.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":256,\"name\":\"Disposable\",\"url\":\"interfaces/aft_core.Disposable.html\",\"classes\":\"tsd-kind-interface tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":2048,\"name\":\"dispose\",\"url\":\"interfaces/aft_core.Disposable.html#dispose\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"aft-core.Disposable\"},{\"kind\":32,\"name\":\"wait\",\"url\":\"variables/aft_core.wait.html\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":128,\"name\":\"AftLogger\",\"url\":\"classes/aft_core.AftLogger.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_core.AftLogger.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-core.AftLogger\"},{\"kind\":1024,\"name\":\"aftCfg\",\"url\":\"classes/aft_core.AftLogger.html#aftCfg\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-core.AftLogger\"},{\"kind\":262144,\"name\":\"logLevel\",\"url\":\"classes/aft_core.AftLogger.html#logLevel\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.AftLogger\"},{\"kind\":2048,\"name\":\"log\",\"url\":\"classes/aft_core.AftLogger.html#log\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.AftLogger\"},{\"kind\":2048,\"name\":\"format\",\"url\":\"classes/aft_core.AftLogger.html#format\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.AftLogger\"},{\"kind\":2048,\"name\":\"toConsole\",\"url\":\"classes/aft_core.AftLogger.html#toConsole\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.AftLogger\"},{\"kind\":32,\"name\":\"aftLogger\",\"url\":\"variables/aft_core.aftLogger-1.html\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":4194304,\"name\":\"LogLevel\",\"url\":\"types/aft_core.LogLevel-1.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":4,\"name\":\"LogLevel\",\"url\":\"modules/aft_core.LogLevel.html\",\"classes\":\"tsd-kind-namespace tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":64,\"name\":\"isType\",\"url\":\"functions/aft_core.LogLevel.isType.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-namespace\",\"parent\":\"aft-core.LogLevel\"},{\"kind\":64,\"name\":\"toValue\",\"url\":\"functions/aft_core.LogLevel.toValue.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-namespace\",\"parent\":\"aft-core.LogLevel\"},{\"kind\":4194304,\"name\":\"LogMessageData\",\"url\":\"types/aft_core.LogMessageData.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_core.LogMessageData.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-core.LogMessageData\"},{\"kind\":1024,\"name\":\"name\",\"url\":\"types/aft_core.LogMessageData.html#__type.name\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.LogMessageData.__type\"},{\"kind\":1024,\"name\":\"level\",\"url\":\"types/aft_core.LogMessageData.html#__type.level\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.LogMessageData.__type\"},{\"kind\":1024,\"name\":\"message\",\"url\":\"types/aft_core.LogMessageData.html#__type.message\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.LogMessageData.__type\"},{\"kind\":1024,\"name\":\"args\",\"url\":\"types/aft_core.LogMessageData.html#__type.args\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.LogMessageData.__type\"},{\"kind\":128,\"name\":\"PluginConfig\",\"url\":\"classes/aft_core.PluginConfig.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_core.PluginConfig.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-core.PluginConfig\"},{\"kind\":1024,\"name\":\"enabled\",\"url\":\"classes/aft_core.PluginConfig.html#enabled\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-core.PluginConfig\"},{\"kind\":128,\"name\":\"Plugin\",\"url\":\"classes/aft_core.Plugin.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_core.Plugin.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-core.Plugin\"},{\"kind\":1024,\"name\":\"_aftCfg\",\"url\":\"classes/aft_core.Plugin.html#_aftCfg\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Plugin\"},{\"kind\":1024,\"name\":\"_aftLogger\",\"url\":\"classes/aft_core.Plugin.html#_aftLogger\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Plugin\"},{\"kind\":262144,\"name\":\"aftCfg\",\"url\":\"classes/aft_core.Plugin.html#aftCfg\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Plugin\"},{\"kind\":262144,\"name\":\"aftLogger\",\"url\":\"classes/aft_core.Plugin.html#aftLogger\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Plugin\"},{\"kind\":262144,\"name\":\"enabled\",\"url\":\"classes/aft_core.Plugin.html#enabled\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Plugin\"},{\"kind\":32,\"name\":\"pluginLoader\",\"url\":\"variables/aft_core.pluginLoader.html\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":128,\"name\":\"BuildInfoManager\",\"url\":\"classes/aft_core.BuildInfoManager.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_core.BuildInfoManager.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-core.BuildInfoManager\"},{\"kind\":1024,\"name\":\"aftCfg\",\"url\":\"classes/aft_core.BuildInfoManager.html#aftCfg\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-core.BuildInfoManager\"},{\"kind\":1024,\"name\":\"plugins\",\"url\":\"classes/aft_core.BuildInfoManager.html#plugins\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-core.BuildInfoManager\"},{\"kind\":1024,\"name\":\"_safeStrOpt\",\"url\":\"classes/aft_core.BuildInfoManager.html#_safeStrOpt\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.BuildInfoManager\"},{\"kind\":1024,\"name\":\"_aftLogger\",\"url\":\"classes/aft_core.BuildInfoManager.html#_aftLogger\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.BuildInfoManager\"},{\"kind\":2048,\"name\":\"get\",\"url\":\"classes/aft_core.BuildInfoManager.html#get\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.BuildInfoManager\"},{\"kind\":2048,\"name\":\"buildName\",\"url\":\"classes/aft_core.BuildInfoManager.html#buildName\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.BuildInfoManager\"},{\"kind\":2048,\"name\":\"buildNumber\",\"url\":\"classes/aft_core.BuildInfoManager.html#buildNumber\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.BuildInfoManager\"},{\"kind\":128,\"name\":\"BuildInfoPlugin\",\"url\":\"classes/aft_core.BuildInfoPlugin.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_core.BuildInfoPlugin.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.BuildInfoPlugin\"},{\"kind\":2048,\"name\":\"buildName\",\"url\":\"classes/aft_core.BuildInfoPlugin.html#buildName\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.BuildInfoPlugin\"},{\"kind\":2048,\"name\":\"buildNumber\",\"url\":\"classes/aft_core.BuildInfoPlugin.html#buildNumber\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.BuildInfoPlugin\"},{\"kind\":262144,\"name\":\"aftCfg\",\"url\":\"classes/aft_core.BuildInfoPlugin.html#aftCfg\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.BuildInfoPlugin\"},{\"kind\":262144,\"name\":\"aftLogger\",\"url\":\"classes/aft_core.BuildInfoPlugin.html#aftLogger\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.BuildInfoPlugin\"},{\"kind\":262144,\"name\":\"enabled\",\"url\":\"classes/aft_core.BuildInfoPlugin.html#enabled\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.BuildInfoPlugin\"},{\"kind\":128,\"name\":\"ReportingPluginConfig\",\"url\":\"classes/aft_core.ReportingPluginConfig.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_core.ReportingPluginConfig.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.ReportingPluginConfig\"},{\"kind\":1024,\"name\":\"logLevel\",\"url\":\"classes/aft_core.ReportingPluginConfig.html#logLevel\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-core.ReportingPluginConfig\"},{\"kind\":1024,\"name\":\"enabled\",\"url\":\"classes/aft_core.ReportingPluginConfig.html#enabled\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.ReportingPluginConfig\"},{\"kind\":128,\"name\":\"ReportingPlugin\",\"url\":\"classes/aft_core.ReportingPlugin.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_core.ReportingPlugin.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.ReportingPlugin\"},{\"kind\":262144,\"name\":\"enabled\",\"url\":\"classes/aft_core.ReportingPlugin.html#enabled\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.ReportingPlugin\"},{\"kind\":262144,\"name\":\"logLevel\",\"url\":\"classes/aft_core.ReportingPlugin.html#logLevel\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.ReportingPlugin\"},{\"kind\":2048,\"name\":\"initialise\",\"url\":\"classes/aft_core.ReportingPlugin.html#initialise\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.ReportingPlugin\"},{\"kind\":2048,\"name\":\"log\",\"url\":\"classes/aft_core.ReportingPlugin.html#log\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.ReportingPlugin\"},{\"kind\":2048,\"name\":\"submitResult\",\"url\":\"classes/aft_core.ReportingPlugin.html#submitResult\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.ReportingPlugin\"},{\"kind\":2048,\"name\":\"finalise\",\"url\":\"classes/aft_core.ReportingPlugin.html#finalise\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.ReportingPlugin\"},{\"kind\":262144,\"name\":\"aftCfg\",\"url\":\"classes/aft_core.ReportingPlugin.html#aftCfg\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.ReportingPlugin\"},{\"kind\":262144,\"name\":\"aftLogger\",\"url\":\"classes/aft_core.ReportingPlugin.html#aftLogger\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.ReportingPlugin\"},{\"kind\":128,\"name\":\"Reporter\",\"url\":\"classes/aft_core.Reporter.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_core.Reporter.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-core.Reporter\"},{\"kind\":1024,\"name\":\"plugins\",\"url\":\"classes/aft_core.Reporter.html#plugins\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-core.Reporter\"},{\"kind\":1024,\"name\":\"_aftLogger\",\"url\":\"classes/aft_core.Reporter.html#_aftLogger\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Reporter\"},{\"kind\":1024,\"name\":\"_stepCount\",\"url\":\"classes/aft_core.Reporter.html#_stepCount\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.Reporter\"},{\"kind\":1024,\"name\":\"reporterName\",\"url\":\"classes/aft_core.Reporter.html#reporterName\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-core.Reporter\"},{\"kind\":1024,\"name\":\"logLevel\",\"url\":\"classes/aft_core.Reporter.html#logLevel\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-core.Reporter\"},{\"kind\":2048,\"name\":\"trace\",\"url\":\"classes/aft_core.Reporter.html#trace\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Reporter\"},{\"kind\":2048,\"name\":\"debug\",\"url\":\"classes/aft_core.Reporter.html#debug\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Reporter\"},{\"kind\":2048,\"name\":\"info\",\"url\":\"classes/aft_core.Reporter.html#info\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Reporter\"},{\"kind\":2048,\"name\":\"step\",\"url\":\"classes/aft_core.Reporter.html#step\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Reporter\"},{\"kind\":2048,\"name\":\"warn\",\"url\":\"classes/aft_core.Reporter.html#warn\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Reporter\"},{\"kind\":2048,\"name\":\"pass\",\"url\":\"classes/aft_core.Reporter.html#pass\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Reporter\"},{\"kind\":2048,\"name\":\"fail\",\"url\":\"classes/aft_core.Reporter.html#fail\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Reporter\"},{\"kind\":2048,\"name\":\"error\",\"url\":\"classes/aft_core.Reporter.html#error\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Reporter\"},{\"kind\":2048,\"name\":\"log\",\"url\":\"classes/aft_core.Reporter.html#log\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Reporter\"},{\"kind\":2048,\"name\":\"submitResult\",\"url\":\"classes/aft_core.Reporter.html#submitResult\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Reporter\"},{\"kind\":2048,\"name\":\"dispose\",\"url\":\"classes/aft_core.Reporter.html#dispose\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Reporter\"},{\"kind\":4194304,\"name\":\"TestResult\",\"url\":\"types/aft_core.TestResult.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_core.TestResult.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-core.TestResult\"},{\"kind\":1024,\"name\":\"testId\",\"url\":\"types/aft_core.TestResult.html#__type.testId\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.TestResult.__type\"},{\"kind\":1024,\"name\":\"testName\",\"url\":\"types/aft_core.TestResult.html#__type.testName\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.TestResult.__type\"},{\"kind\":1024,\"name\":\"resultMessage\",\"url\":\"types/aft_core.TestResult.html#__type.resultMessage\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.TestResult.__type\"},{\"kind\":1024,\"name\":\"status\",\"url\":\"types/aft_core.TestResult.html#__type.status\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.TestResult.__type\"},{\"kind\":1024,\"name\":\"resultId\",\"url\":\"types/aft_core.TestResult.html#__type.resultId\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.TestResult.__type\"},{\"kind\":1024,\"name\":\"created\",\"url\":\"types/aft_core.TestResult.html#__type.created\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.TestResult.__type\"},{\"kind\":1024,\"name\":\"metadata\",\"url\":\"types/aft_core.TestResult.html#__type.metadata\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.TestResult.__type\"},{\"kind\":4194304,\"name\":\"TestStatus\",\"url\":\"types/aft_core.TestStatus.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":128,\"name\":\"TestExecutionPolicyPlugin\",\"url\":\"classes/aft_core.TestExecutionPolicyPlugin.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_core.TestExecutionPolicyPlugin.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.TestExecutionPolicyPlugin\"},{\"kind\":2048,\"name\":\"shouldRun\",\"url\":\"classes/aft_core.TestExecutionPolicyPlugin.html#shouldRun\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.TestExecutionPolicyPlugin\"},{\"kind\":262144,\"name\":\"aftCfg\",\"url\":\"classes/aft_core.TestExecutionPolicyPlugin.html#aftCfg\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.TestExecutionPolicyPlugin\"},{\"kind\":262144,\"name\":\"aftLogger\",\"url\":\"classes/aft_core.TestExecutionPolicyPlugin.html#aftLogger\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.TestExecutionPolicyPlugin\"},{\"kind\":262144,\"name\":\"enabled\",\"url\":\"classes/aft_core.TestExecutionPolicyPlugin.html#enabled\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-core.TestExecutionPolicyPlugin\"},{\"kind\":128,\"name\":\"TestExecutionPolicyManager\",\"url\":\"classes/aft_core.TestExecutionPolicyManager.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_core.TestExecutionPolicyManager.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-core.TestExecutionPolicyManager\"},{\"kind\":1024,\"name\":\"aftCfg\",\"url\":\"classes/aft_core.TestExecutionPolicyManager.html#aftCfg\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-core.TestExecutionPolicyManager\"},{\"kind\":1024,\"name\":\"plugins\",\"url\":\"classes/aft_core.TestExecutionPolicyManager.html#plugins\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-core.TestExecutionPolicyManager\"},{\"kind\":1024,\"name\":\"_aftLogger\",\"url\":\"classes/aft_core.TestExecutionPolicyManager.html#_aftLogger\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.TestExecutionPolicyManager\"},{\"kind\":2048,\"name\":\"shouldRun\",\"url\":\"classes/aft_core.TestExecutionPolicyManager.html#shouldRun\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.TestExecutionPolicyManager\"},{\"kind\":2048,\"name\":\"_getEnabledPlugins\",\"url\":\"classes/aft_core.TestExecutionPolicyManager.html#_getEnabledPlugins\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-core.TestExecutionPolicyManager\"},{\"kind\":4194304,\"name\":\"VerifierEvent\",\"url\":\"types/aft_core.VerifierEvent.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":128,\"name\":\"Verifier\",\"url\":\"classes/aft_core.Verifier.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_core.Verifier.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-core.Verifier\"},{\"kind\":1024,\"name\":\"_aftCfg\",\"url\":\"classes/aft_core.Verifier.html#_aftCfg\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-core.Verifier\"},{\"kind\":1024,\"name\":\"_assertion\",\"url\":\"classes/aft_core.Verifier.html#_assertion\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-core.Verifier\"},{\"kind\":1024,\"name\":\"_matcher\",\"url\":\"classes/aft_core.Verifier.html#_matcher\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-core.Verifier\"},{\"kind\":1024,\"name\":\"_description\",\"url\":\"classes/aft_core.Verifier.html#_description\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-core.Verifier\"},{\"kind\":1024,\"name\":\"_startTime\",\"url\":\"classes/aft_core.Verifier.html#_startTime\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-core.Verifier\"},{\"kind\":1024,\"name\":\"_innerPromise\",\"url\":\"classes/aft_core.Verifier.html#_innerPromise\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-core.Verifier\"},{\"kind\":1024,\"name\":\"_testIds\",\"url\":\"classes/aft_core.Verifier.html#_testIds\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-core.Verifier\"},{\"kind\":1024,\"name\":\"_reporter\",\"url\":\"classes/aft_core.Verifier.html#_reporter\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-core.Verifier\"},{\"kind\":1024,\"name\":\"_policyEngMgr\",\"url\":\"classes/aft_core.Verifier.html#_policyEngMgr\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-core.Verifier\"},{\"kind\":1024,\"name\":\"_buildInfoMgr\",\"url\":\"classes/aft_core.Verifier.html#_buildInfoMgr\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-core.Verifier\"},{\"kind\":1024,\"name\":\"_actionMap\",\"url\":\"classes/aft_core.Verifier.html#_actionMap\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-core.Verifier\"},{\"kind\":262144,\"name\":\"aftCfg\",\"url\":\"classes/aft_core.Verifier.html#aftCfg\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Verifier\"},{\"kind\":262144,\"name\":\"reporter\",\"url\":\"classes/aft_core.Verifier.html#reporter\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Verifier\"},{\"kind\":262144,\"name\":\"policyEngMgr\",\"url\":\"classes/aft_core.Verifier.html#policyEngMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Verifier\"},{\"kind\":262144,\"name\":\"buildInfoMgr\",\"url\":\"classes/aft_core.Verifier.html#buildInfoMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Verifier\"},{\"kind\":2048,\"name\":\"then\",\"url\":\"classes/aft_core.Verifier.html#then\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Verifier\"},{\"kind\":2048,\"name\":\"_getInnerPromise\",\"url\":\"classes/aft_core.Verifier.html#_getInnerPromise\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-core.Verifier\"},{\"kind\":2048,\"name\":\"_resolveAssertion\",\"url\":\"classes/aft_core.Verifier.html#_resolveAssertion\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-core.Verifier\"},{\"kind\":262144,\"name\":\"and\",\"url\":\"classes/aft_core.Verifier.html#and\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Verifier\"},{\"kind\":2048,\"name\":\"on\",\"url\":\"classes/aft_core.Verifier.html#on\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Verifier\"},{\"kind\":2048,\"name\":\"verify\",\"url\":\"classes/aft_core.Verifier.html#verify\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Verifier\"},{\"kind\":2048,\"name\":\"withDescription\",\"url\":\"classes/aft_core.Verifier.html#withDescription\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Verifier\"},{\"kind\":2048,\"name\":\"withTestIds\",\"url\":\"classes/aft_core.Verifier.html#withTestIds\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Verifier\"},{\"kind\":2048,\"name\":\"returns\",\"url\":\"classes/aft_core.Verifier.html#returns\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Verifier\"},{\"kind\":262144,\"name\":\"internals\",\"url\":\"classes/aft_core.Verifier.html#internals\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-core.Verifier\"},{\"kind\":2048,\"name\":\"shouldRun\",\"url\":\"classes/aft_core.Verifier.html#shouldRun\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-core.Verifier\"},{\"kind\":2048,\"name\":\"_logResult\",\"url\":\"classes/aft_core.Verifier.html#_logResult\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-core.Verifier\"},{\"kind\":2048,\"name\":\"_logMessage\",\"url\":\"classes/aft_core.Verifier.html#_logMessage\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-core.Verifier\"},{\"kind\":2048,\"name\":\"_generateTestResults\",\"url\":\"classes/aft_core.Verifier.html#_generateTestResults\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-core.Verifier\"},{\"kind\":2048,\"name\":\"_generateTestResult\",\"url\":\"classes/aft_core.Verifier.html#_generateTestResult\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-core.Verifier\"},{\"kind\":64,\"name\":\"verify\",\"url\":\"functions/aft_core.verify.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":4194304,\"name\":\"VerifierInternals\",\"url\":\"types/aft_core.VerifierInternals.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_core.VerifierInternals.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-core.VerifierInternals\"},{\"kind\":1024,\"name\":\"usingAftConfig\",\"url\":\"types/aft_core.VerifierInternals.html#__type.usingAftConfig\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.VerifierInternals.__type\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_core.VerifierInternals.html#__type.__type-1\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-literal\",\"parent\":\"aft-core.VerifierInternals.__type\"},{\"kind\":1024,\"name\":\"usingBuildInfoManager\",\"url\":\"types/aft_core.VerifierInternals.html#__type.usingBuildInfoManager\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.VerifierInternals.__type\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_core.VerifierInternals.html#__type.__type-3\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-literal\",\"parent\":\"aft-core.VerifierInternals.__type\"},{\"kind\":1024,\"name\":\"usingReporter\",\"url\":\"types/aft_core.VerifierInternals.html#__type.usingReporter\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.VerifierInternals.__type\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_core.VerifierInternals.html#__type.__type-5\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-literal\",\"parent\":\"aft-core.VerifierInternals.__type\"},{\"kind\":1024,\"name\":\"usingTestExecutionPolicyManager\",\"url\":\"types/aft_core.VerifierInternals.html#__type.usingTestExecutionPolicyManager\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-core.VerifierInternals.__type\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_core.VerifierInternals.html#__type.__type-7\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-literal\",\"parent\":\"aft-core.VerifierInternals.__type\"},{\"kind\":256,\"name\":\"VerifierMatcher\",\"url\":\"interfaces/aft_core.VerifierMatcher.html\",\"classes\":\"tsd-kind-interface tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":1024,\"name\":\"expected\",\"url\":\"interfaces/aft_core.VerifierMatcher.html#expected\",\"classes\":\"tsd-kind-property tsd-parent-kind-interface\",\"parent\":\"aft-core.VerifierMatcher\"},{\"kind\":2048,\"name\":\"setActual\",\"url\":\"interfaces/aft_core.VerifierMatcher.html#setActual\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"aft-core.VerifierMatcher\"},{\"kind\":2048,\"name\":\"compare\",\"url\":\"interfaces/aft_core.VerifierMatcher.html#compare\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"aft-core.VerifierMatcher\"},{\"kind\":2048,\"name\":\"failureString\",\"url\":\"interfaces/aft_core.VerifierMatcher.html#failureString\",\"classes\":\"tsd-kind-method tsd-parent-kind-interface\",\"parent\":\"aft-core.VerifierMatcher\"},{\"kind\":64,\"name\":\"equaling\",\"url\":\"functions/aft_core.equaling.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":64,\"name\":\"exactly\",\"url\":\"functions/aft_core.exactly.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":64,\"name\":\"between\",\"url\":\"functions/aft_core.between.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":64,\"name\":\"containing\",\"url\":\"functions/aft_core.containing.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":64,\"name\":\"havingValue\",\"url\":\"functions/aft_core.havingValue.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":64,\"name\":\"greaterThan\",\"url\":\"functions/aft_core.greaterThan.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":64,\"name\":\"lessThan\",\"url\":\"functions/aft_core.lessThan.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":64,\"name\":\"not\",\"url\":\"functions/aft_core.not.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"aft-core\"},{\"kind\":128,\"name\":\"AftJasmineReporter\",\"url\":\"classes/aft_jasmine_reporter.AftJasmineReporter.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-jasmine-reporter\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_jasmine_reporter.AftJasmineReporter.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-jasmine-reporter.AftJasmineReporter\"},{\"kind\":1024,\"name\":\"_async2Sync\",\"url\":\"classes/aft_jasmine_reporter.AftJasmineReporter.html#_async2Sync\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-jasmine-reporter.AftJasmineReporter\"},{\"kind\":1024,\"name\":\"_testNames\",\"url\":\"classes/aft_jasmine_reporter.AftJasmineReporter.html#_testNames\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-jasmine-reporter.AftJasmineReporter\"},{\"kind\":2048,\"name\":\"jasmineStarted\",\"url\":\"classes/aft_jasmine_reporter.AftJasmineReporter.html#jasmineStarted\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-jasmine-reporter.AftJasmineReporter\"},{\"kind\":2048,\"name\":\"specStarted\",\"url\":\"classes/aft_jasmine_reporter.AftJasmineReporter.html#specStarted\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-jasmine-reporter.AftJasmineReporter\"},{\"kind\":2048,\"name\":\"specDone\",\"url\":\"classes/aft_jasmine_reporter.AftJasmineReporter.html#specDone\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-jasmine-reporter.AftJasmineReporter\"},{\"kind\":2048,\"name\":\"_asyncSpecDone\",\"url\":\"classes/aft_jasmine_reporter.AftJasmineReporter.html#_asyncSpecDone\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-jasmine-reporter.AftJasmineReporter\"},{\"kind\":128,\"name\":\"AftLog\",\"url\":\"classes/aft_jasmine_reporter.AftLog.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-jasmine-reporter\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_jasmine_reporter.AftLog.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-jasmine-reporter.AftLog\"},{\"kind\":1024,\"name\":\"_rep\",\"url\":\"classes/aft_jasmine_reporter.AftLog.html#_rep\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-jasmine-reporter.AftLog\"},{\"kind\":1024,\"name\":\"_aftCfg\",\"url\":\"classes/aft_jasmine_reporter.AftLog.html#_aftCfg\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-jasmine-reporter.AftLog\"},{\"kind\":1024,\"name\":\"_testNames\",\"url\":\"classes/aft_jasmine_reporter.AftLog.html#_testNames\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-jasmine-reporter.AftLog\"},{\"kind\":1024,\"name\":\"test\",\"url\":\"classes/aft_jasmine_reporter.AftLog.html#test\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-jasmine-reporter.AftLog\"},{\"kind\":262144,\"name\":\"fullName\",\"url\":\"classes/aft_jasmine_reporter.AftLog.html#fullName\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-jasmine-reporter.AftLog\"},{\"kind\":262144,\"name\":\"aftCfg\",\"url\":\"classes/aft_jasmine_reporter.AftLog.html#aftCfg\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-jasmine-reporter.AftLog\"},{\"kind\":262144,\"name\":\"reporter\",\"url\":\"classes/aft_jasmine_reporter.AftLog.html#reporter\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-jasmine-reporter.AftLog\"},{\"kind\":128,\"name\":\"AftTest\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-jasmine-reporter\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-jasmine-reporter.AftTest\"},{\"kind\":1024,\"name\":\"_testcases\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html#_testcases\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-jasmine-reporter.AftTest\"},{\"kind\":1024,\"name\":\"_buildMgr\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html#_buildMgr\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-jasmine-reporter.AftTest\"},{\"kind\":262144,\"name\":\"buildInfoMgr\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html#buildInfoMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-jasmine-reporter.AftTest\"},{\"kind\":262144,\"name\":\"testcases\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html#testcases\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-jasmine-reporter.AftTest\"},{\"kind\":2048,\"name\":\"pass\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html#pass\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-jasmine-reporter.AftTest\"},{\"kind\":2048,\"name\":\"fail\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html#fail\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-jasmine-reporter.AftTest\"},{\"kind\":2048,\"name\":\"pending\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html#pending\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-jasmine-reporter.AftTest\"},{\"kind\":2048,\"name\":\"shouldRun\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html#shouldRun\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-jasmine-reporter.AftTest\"},{\"kind\":2048,\"name\":\"verify\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html#verify\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-jasmine-reporter.AftTest\"},{\"kind\":2048,\"name\":\"_getVerifier\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html#_getVerifier\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-jasmine-reporter.AftTest\"},{\"kind\":2048,\"name\":\"dispose\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html#dispose\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-jasmine-reporter.AftTest\"},{\"kind\":2048,\"name\":\"_logResult\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html#_logResult\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-jasmine-reporter.AftTest\"},{\"kind\":2048,\"name\":\"_logMessage\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html#_logMessage\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-jasmine-reporter.AftTest\"},{\"kind\":2048,\"name\":\"_generateTestResults\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html#_generateTestResults\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-jasmine-reporter.AftTest\"},{\"kind\":2048,\"name\":\"_generateTestResult\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html#_generateTestResult\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-jasmine-reporter.AftTest\"},{\"kind\":1024,\"name\":\"test\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html#test\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-jasmine-reporter.AftTest\"},{\"kind\":262144,\"name\":\"fullName\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html#fullName\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-jasmine-reporter.AftTest\"},{\"kind\":262144,\"name\":\"aftCfg\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html#aftCfg\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-jasmine-reporter.AftTest\"},{\"kind\":262144,\"name\":\"reporter\",\"url\":\"classes/aft_jasmine_reporter.AftTest.html#reporter\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-jasmine-reporter.AftTest\"},{\"kind\":128,\"name\":\"AftLog\",\"url\":\"classes/aft_mocha_reporter.AftLog.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-mocha-reporter\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_mocha_reporter.AftLog.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-mocha-reporter.AftLog\"},{\"kind\":1024,\"name\":\"_rep\",\"url\":\"classes/aft_mocha_reporter.AftLog.html#_rep\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-mocha-reporter.AftLog\"},{\"kind\":1024,\"name\":\"test\",\"url\":\"classes/aft_mocha_reporter.AftLog.html#test\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-mocha-reporter.AftLog\"},{\"kind\":1024,\"name\":\"aftCfg\",\"url\":\"classes/aft_mocha_reporter.AftLog.html#aftCfg\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-mocha-reporter.AftLog\"},{\"kind\":262144,\"name\":\"fullTitle\",\"url\":\"classes/aft_mocha_reporter.AftLog.html#fullTitle\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-mocha-reporter.AftLog\"},{\"kind\":262144,\"name\":\"reporter\",\"url\":\"classes/aft_mocha_reporter.AftLog.html#reporter\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-mocha-reporter.AftLog\"},{\"kind\":2048,\"name\":\"dispose\",\"url\":\"classes/aft_mocha_reporter.AftLog.html#dispose\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-mocha-reporter.AftLog\"},{\"kind\":128,\"name\":\"AftTest\",\"url\":\"classes/aft_mocha_reporter.AftTest.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-mocha-reporter\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_mocha_reporter.AftTest.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-mocha-reporter.AftTest\"},{\"kind\":1024,\"name\":\"_testcases\",\"url\":\"classes/aft_mocha_reporter.AftTest.html#_testcases\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-mocha-reporter.AftTest\"},{\"kind\":1024,\"name\":\"_buildMgr\",\"url\":\"classes/aft_mocha_reporter.AftTest.html#_buildMgr\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-mocha-reporter.AftTest\"},{\"kind\":262144,\"name\":\"testcases\",\"url\":\"classes/aft_mocha_reporter.AftTest.html#testcases\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-mocha-reporter.AftTest\"},{\"kind\":2048,\"name\":\"pass\",\"url\":\"classes/aft_mocha_reporter.AftTest.html#pass\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-mocha-reporter.AftTest\"},{\"kind\":2048,\"name\":\"fail\",\"url\":\"classes/aft_mocha_reporter.AftTest.html#fail\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-mocha-reporter.AftTest\"},{\"kind\":2048,\"name\":\"pending\",\"url\":\"classes/aft_mocha_reporter.AftTest.html#pending\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-mocha-reporter.AftTest\"},{\"kind\":2048,\"name\":\"shouldRun\",\"url\":\"classes/aft_mocha_reporter.AftTest.html#shouldRun\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-mocha-reporter.AftTest\"},{\"kind\":2048,\"name\":\"verify\",\"url\":\"classes/aft_mocha_reporter.AftTest.html#verify\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-mocha-reporter.AftTest\"},{\"kind\":2048,\"name\":\"_getVerifier\",\"url\":\"classes/aft_mocha_reporter.AftTest.html#_getVerifier\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-mocha-reporter.AftTest\"},{\"kind\":2048,\"name\":\"_logResult\",\"url\":\"classes/aft_mocha_reporter.AftTest.html#_logResult\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-mocha-reporter.AftTest\"},{\"kind\":2048,\"name\":\"_logMessage\",\"url\":\"classes/aft_mocha_reporter.AftTest.html#_logMessage\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-mocha-reporter.AftTest\"},{\"kind\":2048,\"name\":\"_generateTestResults\",\"url\":\"classes/aft_mocha_reporter.AftTest.html#_generateTestResults\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-mocha-reporter.AftTest\"},{\"kind\":2048,\"name\":\"_generateTestResult\",\"url\":\"classes/aft_mocha_reporter.AftTest.html#_generateTestResult\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-mocha-reporter.AftTest\"},{\"kind\":1024,\"name\":\"test\",\"url\":\"classes/aft_mocha_reporter.AftTest.html#test\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-mocha-reporter.AftTest\"},{\"kind\":1024,\"name\":\"aftCfg\",\"url\":\"classes/aft_mocha_reporter.AftTest.html#aftCfg\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-mocha-reporter.AftTest\"},{\"kind\":262144,\"name\":\"fullTitle\",\"url\":\"classes/aft_mocha_reporter.AftTest.html#fullTitle\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-mocha-reporter.AftTest\"},{\"kind\":262144,\"name\":\"reporter\",\"url\":\"classes/aft_mocha_reporter.AftTest.html#reporter\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-mocha-reporter.AftTest\"},{\"kind\":2048,\"name\":\"dispose\",\"url\":\"classes/aft_mocha_reporter.AftTest.html#dispose\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-mocha-reporter.AftTest\"},{\"kind\":128,\"name\":\"AftMochaReporter\",\"url\":\"classes/aft_mocha_reporter.AftMochaReporter.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-mocha-reporter\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_mocha_reporter.AftMochaReporter.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-mocha-reporter.AftMochaReporter\"},{\"kind\":2048,\"name\":\"addListeners\",\"url\":\"classes/aft_mocha_reporter.AftMochaReporter.html#addListeners\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-mocha-reporter.AftMochaReporter\"},{\"kind\":128,\"name\":\"KinesisReportingPluginConfig\",\"url\":\"classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPluginConfig.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-reporting-aws-kinesis-firehose\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPluginConfig.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-reporting-aws-kinesis-firehose.KinesisReportingPluginConfig\"},{\"kind\":1024,\"name\":\"region\",\"url\":\"classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPluginConfig.html#region\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-reporting-aws-kinesis-firehose.KinesisReportingPluginConfig\"},{\"kind\":1024,\"name\":\"deliveryStream\",\"url\":\"classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPluginConfig.html#deliveryStream\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-reporting-aws-kinesis-firehose.KinesisReportingPluginConfig\"},{\"kind\":1024,\"name\":\"batch\",\"url\":\"classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPluginConfig.html#batch\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-reporting-aws-kinesis-firehose.KinesisReportingPluginConfig\"},{\"kind\":1024,\"name\":\"batchSize\",\"url\":\"classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPluginConfig.html#batchSize\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-reporting-aws-kinesis-firehose.KinesisReportingPluginConfig\"},{\"kind\":1024,\"name\":\"logLevel\",\"url\":\"classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPluginConfig.html#logLevel\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-reporting-aws-kinesis-firehose.KinesisReportingPluginConfig\"},{\"kind\":1024,\"name\":\"enabled\",\"url\":\"classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPluginConfig.html#enabled\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-reporting-aws-kinesis-firehose.KinesisReportingPluginConfig\"},{\"kind\":128,\"name\":\"KinesisReportingPlugin\",\"url\":\"classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPlugin.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-reporting-aws-kinesis-firehose\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPlugin.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-reporting-aws-kinesis-firehose.KinesisReportingPlugin\"},{\"kind\":1024,\"name\":\"_logs\",\"url\":\"classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPlugin.html#_logs\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-reporting-aws-kinesis-firehose.KinesisReportingPlugin\"},{\"kind\":1024,\"name\":\"_buildInfo\",\"url\":\"classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPlugin.html#_buildInfo\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-reporting-aws-kinesis-firehose.KinesisReportingPlugin\"},{\"kind\":1024,\"name\":\"_level\",\"url\":\"classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPlugin.html#_level\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-reporting-aws-kinesis-firehose.KinesisReportingPlugin\"},{\"kind\":1024,\"name\":\"_client\",\"url\":\"classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPlugin.html#_client\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-reporting-aws-kinesis-firehose.KinesisReportingPlugin\"},{\"kind\":262144,\"name\":\"logLevel\",\"url\":\"classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPlugin.html#logLevel\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-reporting-aws-kinesis-firehose.KinesisReportingPlugin\"},{\"kind\":2048,\"name\":\"client\",\"url\":\"classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPlugin.html#client\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-reporting-aws-kinesis-firehose.KinesisReportingPlugin\"},{\"kind\":262144,\"name\":\"region\",\"url\":\"classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPlugin.html#region\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-reporting-aws-kinesis-firehose.KinesisReportingPlugin\"},{\"kind\":262144,\"name\":\"deliveryStream\",\"url\":\"classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPlugin.html#deliveryStream\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-reporting-aws-kinesis-firehose.KinesisReportingPlugin\"},{\"kind\":262144,\"name\":\"batch\",\"url\":\"classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPlugin.html#batch\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-reporting-aws-kinesis-firehose.KinesisReportingPlugin\"},{\"kind\":262144,\"name\":\"batchSize\",\"url\":\"classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPlugin.html#batchSize\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-reporting-aws-kinesis-firehose.KinesisReportingPlugin\"},{\"kind\":2048,\"name\":\"credentials\",\"url\":\"classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPlugin.html#credentials\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-reporting-aws-kinesis-firehose.KinesisReportingPlugin\"},{\"kind\":2048,\"name\":\"logs\",\"url\":\"classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPlugin.html#logs\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-reporting-aws-kinesis-firehose.KinesisReportingPlugin\"},{\"kind\":2048,\"name\":\"initialise\",\"url\":\"classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPlugin.html#initialise\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-reporting-aws-kinesis-firehose.KinesisReportingPlugin\"},{\"kind\":2048,\"name\":\"log\",\"url\":\"classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPlugin.html#log\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-reporting-aws-kinesis-firehose.KinesisReportingPlugin\"},{\"kind\":2048,\"name\":\"submitResult\",\"url\":\"classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPlugin.html#submitResult\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-reporting-aws-kinesis-firehose.KinesisReportingPlugin\"},{\"kind\":2048,\"name\":\"finalise\",\"url\":\"classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPlugin.html#finalise\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-reporting-aws-kinesis-firehose.KinesisReportingPlugin\"},{\"kind\":2048,\"name\":\"_createKinesisLogRecord\",\"url\":\"classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPlugin.html#_createKinesisLogRecord\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-reporting-aws-kinesis-firehose.KinesisReportingPlugin\"},{\"kind\":2048,\"name\":\"_checkAndSendLogs\",\"url\":\"classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPlugin.html#_checkAndSendLogs\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-reporting-aws-kinesis-firehose.KinesisReportingPlugin\"},{\"kind\":2048,\"name\":\"_sendBatch\",\"url\":\"classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPlugin.html#_sendBatch\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-reporting-aws-kinesis-firehose.KinesisReportingPlugin\"},{\"kind\":2048,\"name\":\"_send\",\"url\":\"classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPlugin.html#_send\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-reporting-aws-kinesis-firehose.KinesisReportingPlugin\"},{\"kind\":262144,\"name\":\"enabled\",\"url\":\"classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPlugin.html#enabled\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-reporting-aws-kinesis-firehose.KinesisReportingPlugin\"},{\"kind\":262144,\"name\":\"aftCfg\",\"url\":\"classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPlugin.html#aftCfg\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-reporting-aws-kinesis-firehose.KinesisReportingPlugin\"},{\"kind\":262144,\"name\":\"aftLogger\",\"url\":\"classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPlugin.html#aftLogger\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-reporting-aws-kinesis-firehose.KinesisReportingPlugin\"},{\"kind\":128,\"name\":\"FilesystemReportingPluginConfig\",\"url\":\"classes/aft_reporting_filesystem.FilesystemReportingPluginConfig.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-reporting-filesystem\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_reporting_filesystem.FilesystemReportingPluginConfig.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-reporting-filesystem.FilesystemReportingPluginConfig\"},{\"kind\":1024,\"name\":\"logLevel\",\"url\":\"classes/aft_reporting_filesystem.FilesystemReportingPluginConfig.html#logLevel\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-reporting-filesystem.FilesystemReportingPluginConfig\"},{\"kind\":1024,\"name\":\"outputPath\",\"url\":\"classes/aft_reporting_filesystem.FilesystemReportingPluginConfig.html#outputPath\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-reporting-filesystem.FilesystemReportingPluginConfig\"},{\"kind\":1024,\"name\":\"includeResults\",\"url\":\"classes/aft_reporting_filesystem.FilesystemReportingPluginConfig.html#includeResults\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-reporting-filesystem.FilesystemReportingPluginConfig\"},{\"kind\":1024,\"name\":\"dateFormat\",\"url\":\"classes/aft_reporting_filesystem.FilesystemReportingPluginConfig.html#dateFormat\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-reporting-filesystem.FilesystemReportingPluginConfig\"},{\"kind\":1024,\"name\":\"enabled\",\"url\":\"classes/aft_reporting_filesystem.FilesystemReportingPluginConfig.html#enabled\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-reporting-filesystem.FilesystemReportingPluginConfig\"},{\"kind\":128,\"name\":\"FilesystemReportingPlugin\",\"url\":\"classes/aft_reporting_filesystem.FilesystemReportingPlugin.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-reporting-filesystem\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_reporting_filesystem.FilesystemReportingPlugin.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-reporting-filesystem.FilesystemReportingPlugin\"},{\"kind\":262144,\"name\":\"logLevel\",\"url\":\"classes/aft_reporting_filesystem.FilesystemReportingPlugin.html#logLevel\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-reporting-filesystem.FilesystemReportingPlugin\"},{\"kind\":1024,\"name\":\"_outputPath\",\"url\":\"classes/aft_reporting_filesystem.FilesystemReportingPlugin.html#_outputPath\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-reporting-filesystem.FilesystemReportingPlugin\"},{\"kind\":1024,\"name\":\"_includeResults\",\"url\":\"classes/aft_reporting_filesystem.FilesystemReportingPlugin.html#_includeResults\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-reporting-filesystem.FilesystemReportingPlugin\"},{\"kind\":1024,\"name\":\"_dateFormat\",\"url\":\"classes/aft_reporting_filesystem.FilesystemReportingPlugin.html#_dateFormat\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-reporting-filesystem.FilesystemReportingPlugin\"},{\"kind\":1024,\"name\":\"_level\",\"url\":\"classes/aft_reporting_filesystem.FilesystemReportingPlugin.html#_level\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-reporting-filesystem.FilesystemReportingPlugin\"},{\"kind\":2048,\"name\":\"initialise\",\"url\":\"classes/aft_reporting_filesystem.FilesystemReportingPlugin.html#initialise\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-reporting-filesystem.FilesystemReportingPlugin\"},{\"kind\":2048,\"name\":\"log\",\"url\":\"classes/aft_reporting_filesystem.FilesystemReportingPlugin.html#log\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-reporting-filesystem.FilesystemReportingPlugin\"},{\"kind\":2048,\"name\":\"submitResult\",\"url\":\"classes/aft_reporting_filesystem.FilesystemReportingPlugin.html#submitResult\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-reporting-filesystem.FilesystemReportingPlugin\"},{\"kind\":2048,\"name\":\"finalise\",\"url\":\"classes/aft_reporting_filesystem.FilesystemReportingPlugin.html#finalise\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-reporting-filesystem.FilesystemReportingPlugin\"},{\"kind\":2048,\"name\":\"_appendToFile\",\"url\":\"classes/aft_reporting_filesystem.FilesystemReportingPlugin.html#_appendToFile\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-reporting-filesystem.FilesystemReportingPlugin\"},{\"kind\":2048,\"name\":\"_format\",\"url\":\"classes/aft_reporting_filesystem.FilesystemReportingPlugin.html#_format\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-reporting-filesystem.FilesystemReportingPlugin\"},{\"kind\":262144,\"name\":\"enabled\",\"url\":\"classes/aft_reporting_filesystem.FilesystemReportingPlugin.html#enabled\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-reporting-filesystem.FilesystemReportingPlugin\"},{\"kind\":262144,\"name\":\"aftCfg\",\"url\":\"classes/aft_reporting_filesystem.FilesystemReportingPlugin.html#aftCfg\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-reporting-filesystem.FilesystemReportingPlugin\"},{\"kind\":262144,\"name\":\"aftLogger\",\"url\":\"classes/aft_reporting_filesystem.FilesystemReportingPlugin.html#aftLogger\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-reporting-filesystem.FilesystemReportingPlugin\"},{\"kind\":128,\"name\":\"HtmlReportingPluginConfig\",\"url\":\"classes/aft_reporting_html.HtmlReportingPluginConfig.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-reporting-html\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_reporting_html.HtmlReportingPluginConfig.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-reporting-html.HtmlReportingPluginConfig\"},{\"kind\":1024,\"name\":\"fileName\",\"url\":\"classes/aft_reporting_html.HtmlReportingPluginConfig.html#fileName\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-reporting-html.HtmlReportingPluginConfig\"},{\"kind\":1024,\"name\":\"outputDir\",\"url\":\"classes/aft_reporting_html.HtmlReportingPluginConfig.html#outputDir\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-reporting-html.HtmlReportingPluginConfig\"},{\"kind\":1024,\"name\":\"maxLogLines\",\"url\":\"classes/aft_reporting_html.HtmlReportingPluginConfig.html#maxLogLines\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-reporting-html.HtmlReportingPluginConfig\"},{\"kind\":1024,\"name\":\"logLevel\",\"url\":\"classes/aft_reporting_html.HtmlReportingPluginConfig.html#logLevel\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-reporting-html.HtmlReportingPluginConfig\"},{\"kind\":1024,\"name\":\"enabled\",\"url\":\"classes/aft_reporting_html.HtmlReportingPluginConfig.html#enabled\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-reporting-html.HtmlReportingPluginConfig\"},{\"kind\":128,\"name\":\"HtmlReportingPlugin\",\"url\":\"classes/aft_reporting_html.HtmlReportingPlugin.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-reporting-html\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_reporting_html.HtmlReportingPlugin.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-reporting-html.HtmlReportingPlugin\"},{\"kind\":262144,\"name\":\"logLevel\",\"url\":\"classes/aft_reporting_html.HtmlReportingPlugin.html#logLevel\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-reporting-html.HtmlReportingPlugin\"},{\"kind\":1024,\"name\":\"_results\",\"url\":\"classes/aft_reporting_html.HtmlReportingPlugin.html#_results\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-reporting-html.HtmlReportingPlugin\"},{\"kind\":1024,\"name\":\"_logs\",\"url\":\"classes/aft_reporting_html.HtmlReportingPlugin.html#_logs\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-reporting-html.HtmlReportingPlugin\"},{\"kind\":1024,\"name\":\"_fileName\",\"url\":\"classes/aft_reporting_html.HtmlReportingPlugin.html#_fileName\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-reporting-html.HtmlReportingPlugin\"},{\"kind\":1024,\"name\":\"_outputDir\",\"url\":\"classes/aft_reporting_html.HtmlReportingPlugin.html#_outputDir\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-reporting-html.HtmlReportingPlugin\"},{\"kind\":1024,\"name\":\"_maxLogLines\",\"url\":\"classes/aft_reporting_html.HtmlReportingPlugin.html#_maxLogLines\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-reporting-html.HtmlReportingPlugin\"},{\"kind\":1024,\"name\":\"_level\",\"url\":\"classes/aft_reporting_html.HtmlReportingPlugin.html#_level\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-reporting-html.HtmlReportingPlugin\"},{\"kind\":262144,\"name\":\"fullPathAndFile\",\"url\":\"classes/aft_reporting_html.HtmlReportingPlugin.html#fullPathAndFile\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-reporting-html.HtmlReportingPlugin\"},{\"kind\":2048,\"name\":\"logs\",\"url\":\"classes/aft_reporting_html.HtmlReportingPlugin.html#logs\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-reporting-html.HtmlReportingPlugin\"},{\"kind\":2048,\"name\":\"testResults\",\"url\":\"classes/aft_reporting_html.HtmlReportingPlugin.html#testResults\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-reporting-html.HtmlReportingPlugin\"},{\"kind\":2048,\"name\":\"initialise\",\"url\":\"classes/aft_reporting_html.HtmlReportingPlugin.html#initialise\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-reporting-html.HtmlReportingPlugin\"},{\"kind\":2048,\"name\":\"log\",\"url\":\"classes/aft_reporting_html.HtmlReportingPlugin.html#log\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-reporting-html.HtmlReportingPlugin\"},{\"kind\":2048,\"name\":\"submitResult\",\"url\":\"classes/aft_reporting_html.HtmlReportingPlugin.html#submitResult\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-reporting-html.HtmlReportingPlugin\"},{\"kind\":2048,\"name\":\"finalise\",\"url\":\"classes/aft_reporting_html.HtmlReportingPlugin.html#finalise\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-reporting-html.HtmlReportingPlugin\"},{\"kind\":2048,\"name\":\"_regenerateHtmlFile\",\"url\":\"classes/aft_reporting_html.HtmlReportingPlugin.html#_regenerateHtmlFile\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-reporting-html.HtmlReportingPlugin\"},{\"kind\":262144,\"name\":\"enabled\",\"url\":\"classes/aft_reporting_html.HtmlReportingPlugin.html#enabled\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-reporting-html.HtmlReportingPlugin\"},{\"kind\":262144,\"name\":\"aftCfg\",\"url\":\"classes/aft_reporting_html.HtmlReportingPlugin.html#aftCfg\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-reporting-html.HtmlReportingPlugin\"},{\"kind\":262144,\"name\":\"aftLogger\",\"url\":\"classes/aft_reporting_html.HtmlReportingPlugin.html#aftLogger\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-reporting-html.HtmlReportingPlugin\"},{\"kind\":128,\"name\":\"TestRailConfig\",\"url\":\"classes/aft_testrail.TestRailConfig.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-testrail\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_testrail.TestRailConfig.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-testrail.TestRailConfig\"},{\"kind\":1024,\"name\":\"url\",\"url\":\"classes/aft_testrail.TestRailConfig.html#url\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailConfig\"},{\"kind\":1024,\"name\":\"user\",\"url\":\"classes/aft_testrail.TestRailConfig.html#user\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailConfig\"},{\"kind\":1024,\"name\":\"accessKey\",\"url\":\"classes/aft_testrail.TestRailConfig.html#accessKey\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailConfig\"},{\"kind\":1024,\"name\":\"projectId\",\"url\":\"classes/aft_testrail.TestRailConfig.html#projectId\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailConfig\"},{\"kind\":1024,\"name\":\"suiteIds\",\"url\":\"classes/aft_testrail.TestRailConfig.html#suiteIds\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailConfig\"},{\"kind\":1024,\"name\":\"planId\",\"url\":\"classes/aft_testrail.TestRailConfig.html#planId\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailConfig\"},{\"kind\":1024,\"name\":\"cacheDuration\",\"url\":\"classes/aft_testrail.TestRailConfig.html#cacheDuration\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailConfig\"},{\"kind\":1024,\"name\":\"logLevel\",\"url\":\"classes/aft_testrail.TestRailConfig.html#logLevel\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailConfig\"},{\"kind\":1024,\"name\":\"maxLogCharacters\",\"url\":\"classes/aft_testrail.TestRailConfig.html#maxLogCharacters\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailConfig\"},{\"kind\":1024,\"name\":\"policyEngineEnabled\",\"url\":\"classes/aft_testrail.TestRailConfig.html#policyEngineEnabled\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailConfig\"},{\"kind\":1024,\"name\":\"enabled\",\"url\":\"classes/aft_testrail.TestRailConfig.html#enabled\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-testrail.TestRailConfig\"},{\"kind\":128,\"name\":\"TestRailTestExecutionPolicyPlugin\",\"url\":\"classes/aft_testrail.TestRailTestExecutionPolicyPlugin.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-testrail\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_testrail.TestRailTestExecutionPolicyPlugin.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailTestExecutionPolicyPlugin\"},{\"kind\":1024,\"name\":\"_enabled\",\"url\":\"classes/aft_testrail.TestRailTestExecutionPolicyPlugin.html#_enabled\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-testrail.TestRailTestExecutionPolicyPlugin\"},{\"kind\":262144,\"name\":\"enabled\",\"url\":\"classes/aft_testrail.TestRailTestExecutionPolicyPlugin.html#enabled\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailTestExecutionPolicyPlugin\"},{\"kind\":1024,\"name\":\"_api\",\"url\":\"classes/aft_testrail.TestRailTestExecutionPolicyPlugin.html#_api\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-testrail.TestRailTestExecutionPolicyPlugin\"},{\"kind\":2048,\"name\":\"getTestCase\",\"url\":\"classes/aft_testrail.TestRailTestExecutionPolicyPlugin.html#getTestCase\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailTestExecutionPolicyPlugin\"},{\"kind\":2048,\"name\":\"findTestCases\",\"url\":\"classes/aft_testrail.TestRailTestExecutionPolicyPlugin.html#findTestCases\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailTestExecutionPolicyPlugin\"},{\"kind\":2048,\"name\":\"shouldRun\",\"url\":\"classes/aft_testrail.TestRailTestExecutionPolicyPlugin.html#shouldRun\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailTestExecutionPolicyPlugin\"},{\"kind\":2048,\"name\":\"_findTestsByField\",\"url\":\"classes/aft_testrail.TestRailTestExecutionPolicyPlugin.html#_findTestsByField\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-testrail.TestRailTestExecutionPolicyPlugin\"},{\"kind\":262144,\"name\":\"aftCfg\",\"url\":\"classes/aft_testrail.TestRailTestExecutionPolicyPlugin.html#aftCfg\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-testrail.TestRailTestExecutionPolicyPlugin\"},{\"kind\":262144,\"name\":\"aftLogger\",\"url\":\"classes/aft_testrail.TestRailTestExecutionPolicyPlugin.html#aftLogger\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-testrail.TestRailTestExecutionPolicyPlugin\"},{\"kind\":128,\"name\":\"TestRailReportingPlugin\",\"url\":\"classes/aft_testrail.TestRailReportingPlugin.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-testrail\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_testrail.TestRailReportingPlugin.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailReportingPlugin\"},{\"kind\":1024,\"name\":\"_level\",\"url\":\"classes/aft_testrail.TestRailReportingPlugin.html#_level\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-testrail.TestRailReportingPlugin\"},{\"kind\":262144,\"name\":\"logLevel\",\"url\":\"classes/aft_testrail.TestRailReportingPlugin.html#logLevel\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailReportingPlugin\"},{\"kind\":1024,\"name\":\"_logs\",\"url\":\"classes/aft_testrail.TestRailReportingPlugin.html#_logs\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-testrail.TestRailReportingPlugin\"},{\"kind\":1024,\"name\":\"_api\",\"url\":\"classes/aft_testrail.TestRailReportingPlugin.html#_api\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-testrail.TestRailReportingPlugin\"},{\"kind\":1024,\"name\":\"_maxLogChars\",\"url\":\"classes/aft_testrail.TestRailReportingPlugin.html#_maxLogChars\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-testrail.TestRailReportingPlugin\"},{\"kind\":2048,\"name\":\"logs\",\"url\":\"classes/aft_testrail.TestRailReportingPlugin.html#logs\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailReportingPlugin\"},{\"kind\":2048,\"name\":\"log\",\"url\":\"classes/aft_testrail.TestRailReportingPlugin.html#log\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailReportingPlugin\"},{\"kind\":2048,\"name\":\"submitResult\",\"url\":\"classes/aft_testrail.TestRailReportingPlugin.html#submitResult\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailReportingPlugin\"},{\"kind\":2048,\"name\":\"finalise\",\"url\":\"classes/aft_testrail.TestRailReportingPlugin.html#finalise\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailReportingPlugin\"},{\"kind\":2048,\"name\":\"_getTestRailResultForTestResult\",\"url\":\"classes/aft_testrail.TestRailReportingPlugin.html#_getTestRailResultForTestResult\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-testrail.TestRailReportingPlugin\"},{\"kind\":262144,\"name\":\"enabled\",\"url\":\"classes/aft_testrail.TestRailReportingPlugin.html#enabled\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-testrail.TestRailReportingPlugin\"},{\"kind\":1024,\"name\":\"initialise\",\"url\":\"classes/aft_testrail.TestRailReportingPlugin.html#initialise\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-testrail.TestRailReportingPlugin\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"classes/aft_testrail.TestRailReportingPlugin.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-class\",\"parent\":\"aft-testrail.TestRailReportingPlugin\"},{\"kind\":262144,\"name\":\"aftCfg\",\"url\":\"classes/aft_testrail.TestRailReportingPlugin.html#aftCfg\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-testrail.TestRailReportingPlugin\"},{\"kind\":262144,\"name\":\"aftLogger\",\"url\":\"classes/aft_testrail.TestRailReportingPlugin.html#aftLogger\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-testrail.TestRailReportingPlugin\"},{\"kind\":128,\"name\":\"UiSessionConfig\",\"url\":\"classes/aft_ui.UiSessionConfig.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-ui\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_ui.UiSessionConfig.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-ui.UiSessionConfig\"},{\"kind\":1024,\"name\":\"generatorName\",\"url\":\"classes/aft_ui.UiSessionConfig.html#generatorName\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-ui.UiSessionConfig\"},{\"kind\":1024,\"name\":\"options\",\"url\":\"classes/aft_ui.UiSessionConfig.html#options\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-ui.UiSessionConfig\"},{\"kind\":4194304,\"name\":\"UiComponentOptions\",\"url\":\"types/aft_ui.UiComponentOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-ui\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_ui.UiComponentOptions.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-ui.UiComponentOptions\"},{\"kind\":1024,\"name\":\"driver\",\"url\":\"types/aft_ui.UiComponentOptions.html#__type.driver\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui.UiComponentOptions.__type\"},{\"kind\":1024,\"name\":\"aftCfg\",\"url\":\"types/aft_ui.UiComponentOptions.html#__type.aftCfg\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui.UiComponentOptions.__type\"},{\"kind\":1024,\"name\":\"locator\",\"url\":\"types/aft_ui.UiComponentOptions.html#__type.locator\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui.UiComponentOptions.__type\"},{\"kind\":1024,\"name\":\"parent\",\"url\":\"types/aft_ui.UiComponentOptions.html#__type.parent\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui.UiComponentOptions.__type\"},{\"kind\":1024,\"name\":\"reporter\",\"url\":\"types/aft_ui.UiComponentOptions.html#__type.reporter\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-ui.UiComponentOptions.__type\"},{\"kind\":128,\"name\":\"UiComponent\",\"url\":\"classes/aft_ui.UiComponent.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-ui\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_ui.UiComponent.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-ui.UiComponent\"},{\"kind\":1024,\"name\":\"aftCfg\",\"url\":\"classes/aft_ui.UiComponent.html#aftCfg\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-ui.UiComponent\"},{\"kind\":1024,\"name\":\"reporter\",\"url\":\"classes/aft_ui.UiComponent.html#reporter\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-ui.UiComponent\"},{\"kind\":1024,\"name\":\"_driver\",\"url\":\"classes/aft_ui.UiComponent.html#_driver\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-ui.UiComponent\"},{\"kind\":1024,\"name\":\"_parent\",\"url\":\"classes/aft_ui.UiComponent.html#_parent\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-ui.UiComponent\"},{\"kind\":1024,\"name\":\"_locator\",\"url\":\"classes/aft_ui.UiComponent.html#_locator\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-ui.UiComponent\"},{\"kind\":262144,\"name\":\"driver\",\"url\":\"classes/aft_ui.UiComponent.html#driver\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui.UiComponent\"},{\"kind\":262144,\"name\":\"parent\",\"url\":\"classes/aft_ui.UiComponent.html#parent\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui.UiComponent\"},{\"kind\":262144,\"name\":\"locator\",\"url\":\"classes/aft_ui.UiComponent.html#locator\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui.UiComponent\"},{\"kind\":2048,\"name\":\"getRoot\",\"url\":\"classes/aft_ui.UiComponent.html#getRoot\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui.UiComponent\"},{\"kind\":2048,\"name\":\"getComponent\",\"url\":\"classes/aft_ui.UiComponent.html#getComponent\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui.UiComponent\"},{\"kind\":128,\"name\":\"UiSessionGeneratorPlugin\",\"url\":\"classes/aft_ui.UiSessionGeneratorPlugin.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-ui\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_ui.UiSessionGeneratorPlugin.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui.UiSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"enabled\",\"url\":\"classes/aft_ui.UiSessionGeneratorPlugin.html#enabled\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui.UiSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"getSession\",\"url\":\"classes/aft_ui.UiSessionGeneratorPlugin.html#getSession\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui.UiSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"aftCfg\",\"url\":\"classes/aft_ui.UiSessionGeneratorPlugin.html#aftCfg\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui.UiSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"aftLogger\",\"url\":\"classes/aft_ui.UiSessionGeneratorPlugin.html#aftLogger\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui.UiSessionGeneratorPlugin\"},{\"kind\":128,\"name\":\"UiSessionGeneratorManager\",\"url\":\"classes/aft_ui.UiSessionGeneratorManager.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-ui\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_ui.UiSessionGeneratorManager.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-ui.UiSessionGeneratorManager\"},{\"kind\":1024,\"name\":\"aftCfg\",\"url\":\"classes/aft_ui.UiSessionGeneratorManager.html#aftCfg\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-ui.UiSessionGeneratorManager\"},{\"kind\":1024,\"name\":\"plugins\",\"url\":\"classes/aft_ui.UiSessionGeneratorManager.html#plugins\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-ui.UiSessionGeneratorManager\"},{\"kind\":2048,\"name\":\"getSession\",\"url\":\"classes/aft_ui.UiSessionGeneratorManager.html#getSession\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui.UiSessionGeneratorManager\"},{\"kind\":128,\"name\":\"SeleniumComponent\",\"url\":\"classes/aft_ui_selenium.SeleniumComponent.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-ui-selenium\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_ui_selenium.SeleniumComponent.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-selenium.SeleniumComponent\"},{\"kind\":262144,\"name\":\"driver\",\"url\":\"classes/aft_ui_selenium.SeleniumComponent.html#driver\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-selenium.SeleniumComponent\"},{\"kind\":262144,\"name\":\"parent\",\"url\":\"classes/aft_ui_selenium.SeleniumComponent.html#parent\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-selenium.SeleniumComponent\"},{\"kind\":262144,\"name\":\"locator\",\"url\":\"classes/aft_ui_selenium.SeleniumComponent.html#locator\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-selenium.SeleniumComponent\"},{\"kind\":2048,\"name\":\"getRoot\",\"url\":\"classes/aft_ui_selenium.SeleniumComponent.html#getRoot\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-selenium.SeleniumComponent\"},{\"kind\":1024,\"name\":\"aftCfg\",\"url\":\"classes/aft_ui_selenium.SeleniumComponent.html#aftCfg\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-selenium.SeleniumComponent\"},{\"kind\":1024,\"name\":\"reporter\",\"url\":\"classes/aft_ui_selenium.SeleniumComponent.html#reporter\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-selenium.SeleniumComponent\"},{\"kind\":1024,\"name\":\"_driver\",\"url\":\"classes/aft_ui_selenium.SeleniumComponent.html#_driver\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-selenium.SeleniumComponent\"},{\"kind\":1024,\"name\":\"_parent\",\"url\":\"classes/aft_ui_selenium.SeleniumComponent.html#_parent\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-selenium.SeleniumComponent\"},{\"kind\":1024,\"name\":\"_locator\",\"url\":\"classes/aft_ui_selenium.SeleniumComponent.html#_locator\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-selenium.SeleniumComponent\"},{\"kind\":2048,\"name\":\"getComponent\",\"url\":\"classes/aft_ui_selenium.SeleniumComponent.html#getComponent\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-selenium.SeleniumComponent\"},{\"kind\":128,\"name\":\"SeleniumVerifier\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-ui-selenium\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-selenium.SeleniumVerifier\"},{\"kind\":1024,\"name\":\"_assertion\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html#_assertion\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-ui-selenium.SeleniumVerifier\"},{\"kind\":1024,\"name\":\"_driver\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html#_driver\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-ui-selenium.SeleniumVerifier\"},{\"kind\":1024,\"name\":\"_sessionMgr\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html#_sessionMgr\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-ui-selenium.SeleniumVerifier\"},{\"kind\":1024,\"name\":\"_sessionOptions\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html#_sessionOptions\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-selenium.SeleniumVerifier\"},{\"kind\":262144,\"name\":\"sessionGeneratorManager\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html#sessionGeneratorManager\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-selenium.SeleniumVerifier\"},{\"kind\":262144,\"name\":\"driver\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html#driver\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-selenium.SeleniumVerifier\"},{\"kind\":262144,\"name\":\"internals\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html#internals\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-selenium.SeleniumVerifier\"},{\"kind\":2048,\"name\":\"withAdditionalSessionOptions\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html#withAdditionalSessionOptions\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-selenium.SeleniumVerifier\"},{\"kind\":2048,\"name\":\"getComponent\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html#getComponent\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-selenium.SeleniumVerifier\"},{\"kind\":2048,\"name\":\"_resolveAssertion\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html#_resolveAssertion\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-ui-selenium.SeleniumVerifier\"},{\"kind\":1024,\"name\":\"_aftCfg\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html#_aftCfg\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-selenium.SeleniumVerifier\"},{\"kind\":1024,\"name\":\"_matcher\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html#_matcher\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-selenium.SeleniumVerifier\"},{\"kind\":1024,\"name\":\"_description\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html#_description\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-selenium.SeleniumVerifier\"},{\"kind\":1024,\"name\":\"_startTime\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html#_startTime\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-selenium.SeleniumVerifier\"},{\"kind\":1024,\"name\":\"_innerPromise\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html#_innerPromise\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-selenium.SeleniumVerifier\"},{\"kind\":1024,\"name\":\"_testIds\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html#_testIds\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-selenium.SeleniumVerifier\"},{\"kind\":1024,\"name\":\"_reporter\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html#_reporter\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-selenium.SeleniumVerifier\"},{\"kind\":1024,\"name\":\"_policyEngMgr\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html#_policyEngMgr\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-selenium.SeleniumVerifier\"},{\"kind\":1024,\"name\":\"_buildInfoMgr\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html#_buildInfoMgr\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-selenium.SeleniumVerifier\"},{\"kind\":1024,\"name\":\"_actionMap\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html#_actionMap\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-selenium.SeleniumVerifier\"},{\"kind\":262144,\"name\":\"aftCfg\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html#aftCfg\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-selenium.SeleniumVerifier\"},{\"kind\":262144,\"name\":\"reporter\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html#reporter\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-selenium.SeleniumVerifier\"},{\"kind\":262144,\"name\":\"policyEngMgr\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html#policyEngMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-selenium.SeleniumVerifier\"},{\"kind\":262144,\"name\":\"buildInfoMgr\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html#buildInfoMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-selenium.SeleniumVerifier\"},{\"kind\":2048,\"name\":\"then\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html#then\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-selenium.SeleniumVerifier\"},{\"kind\":2048,\"name\":\"_getInnerPromise\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html#_getInnerPromise\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-selenium.SeleniumVerifier\"},{\"kind\":262144,\"name\":\"and\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html#and\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-selenium.SeleniumVerifier\"},{\"kind\":2048,\"name\":\"on\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html#on\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-selenium.SeleniumVerifier\"},{\"kind\":2048,\"name\":\"verify\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html#verify\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-selenium.SeleniumVerifier\"},{\"kind\":2048,\"name\":\"withDescription\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html#withDescription\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-selenium.SeleniumVerifier\"},{\"kind\":2048,\"name\":\"withTestIds\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html#withTestIds\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-selenium.SeleniumVerifier\"},{\"kind\":2048,\"name\":\"returns\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html#returns\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-selenium.SeleniumVerifier\"},{\"kind\":2048,\"name\":\"shouldRun\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html#shouldRun\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-selenium.SeleniumVerifier\"},{\"kind\":2048,\"name\":\"_logResult\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html#_logResult\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-selenium.SeleniumVerifier\"},{\"kind\":2048,\"name\":\"_logMessage\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html#_logMessage\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-selenium.SeleniumVerifier\"},{\"kind\":2048,\"name\":\"_generateTestResults\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html#_generateTestResults\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-selenium.SeleniumVerifier\"},{\"kind\":2048,\"name\":\"_generateTestResult\",\"url\":\"classes/aft_ui_selenium.SeleniumVerifier.html#_generateTestResult\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-selenium.SeleniumVerifier\"},{\"kind\":64,\"name\":\"verifyWithSelenium\",\"url\":\"functions/aft_ui_selenium.verifyWithSelenium.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"aft-ui-selenium\"},{\"kind\":4194304,\"name\":\"SeleniumVerifierInternals\",\"url\":\"types/aft_ui_selenium.SeleniumVerifierInternals.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-ui-selenium\"},{\"kind\":128,\"name\":\"LocalSessionGeneratorPlugin\",\"url\":\"classes/aft_ui_selenium.LocalSessionGeneratorPlugin.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-ui-selenium\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_ui_selenium.LocalSessionGeneratorPlugin.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-selenium.LocalSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"getSession\",\"url\":\"classes/aft_ui_selenium.LocalSessionGeneratorPlugin.html#getSession\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-selenium.LocalSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"enabled\",\"url\":\"classes/aft_ui_selenium.LocalSessionGeneratorPlugin.html#enabled\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-selenium.LocalSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"aftCfg\",\"url\":\"classes/aft_ui_selenium.LocalSessionGeneratorPlugin.html#aftCfg\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-selenium.LocalSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"aftLogger\",\"url\":\"classes/aft_ui_selenium.LocalSessionGeneratorPlugin.html#aftLogger\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-selenium.LocalSessionGeneratorPlugin\"},{\"kind\":128,\"name\":\"GridSessionGeneratorPlugin\",\"url\":\"classes/aft_ui_selenium.GridSessionGeneratorPlugin.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-ui-selenium\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_ui_selenium.GridSessionGeneratorPlugin.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-selenium.GridSessionGeneratorPlugin\"},{\"kind\":1024,\"name\":\"_reporter\",\"url\":\"classes/aft_ui_selenium.GridSessionGeneratorPlugin.html#_reporter\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-ui-selenium.GridSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"reporter\",\"url\":\"classes/aft_ui_selenium.GridSessionGeneratorPlugin.html#reporter\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-selenium.GridSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"getSession\",\"url\":\"classes/aft_ui_selenium.GridSessionGeneratorPlugin.html#getSession\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-selenium.GridSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"enabled\",\"url\":\"classes/aft_ui_selenium.GridSessionGeneratorPlugin.html#enabled\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-selenium.GridSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"aftCfg\",\"url\":\"classes/aft_ui_selenium.GridSessionGeneratorPlugin.html#aftCfg\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-selenium.GridSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"aftLogger\",\"url\":\"classes/aft_ui_selenium.GridSessionGeneratorPlugin.html#aftLogger\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-selenium.GridSessionGeneratorPlugin\"},{\"kind\":128,\"name\":\"WebdriverIoComponent\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoComponent.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-ui-webdriverio\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoComponent.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoComponent\"},{\"kind\":262144,\"name\":\"driver\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoComponent.html#driver\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-webdriverio.WebdriverIoComponent\"},{\"kind\":262144,\"name\":\"locator\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoComponent.html#locator\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-webdriverio.WebdriverIoComponent\"},{\"kind\":262144,\"name\":\"parent\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoComponent.html#parent\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-webdriverio.WebdriverIoComponent\"},{\"kind\":2048,\"name\":\"getRoot\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoComponent.html#getRoot\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-webdriverio.WebdriverIoComponent\"},{\"kind\":1024,\"name\":\"aftCfg\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoComponent.html#aftCfg\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoComponent\"},{\"kind\":1024,\"name\":\"reporter\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoComponent.html#reporter\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoComponent\"},{\"kind\":1024,\"name\":\"_driver\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoComponent.html#_driver\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoComponent\"},{\"kind\":1024,\"name\":\"_parent\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoComponent.html#_parent\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoComponent\"},{\"kind\":1024,\"name\":\"_locator\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoComponent.html#_locator\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoComponent\"},{\"kind\":2048,\"name\":\"getComponent\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoComponent.html#getComponent\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoComponent\"},{\"kind\":4194304,\"name\":\"WebdriverIoVerifierInternals\",\"url\":\"types/aft_ui_webdriverio.WebdriverIoVerifierInternals.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-ui-webdriverio\"},{\"kind\":128,\"name\":\"WebdriverIoVerifier\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-ui-webdriverio\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoVerifier\"},{\"kind\":1024,\"name\":\"_assertion\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html#_assertion\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-ui-webdriverio.WebdriverIoVerifier\"},{\"kind\":1024,\"name\":\"_sessionMgr\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html#_sessionMgr\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-ui-webdriverio.WebdriverIoVerifier\"},{\"kind\":1024,\"name\":\"_browser\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html#_browser\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-ui-webdriverio.WebdriverIoVerifier\"},{\"kind\":1024,\"name\":\"_sessionOptions\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html#_sessionOptions\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-ui-webdriverio.WebdriverIoVerifier\"},{\"kind\":262144,\"name\":\"sessionGeneratorManager\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html#sessionGeneratorManager\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-webdriverio.WebdriverIoVerifier\"},{\"kind\":262144,\"name\":\"browser\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html#browser\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-webdriverio.WebdriverIoVerifier\"},{\"kind\":262144,\"name\":\"internals\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html#internals\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class\",\"parent\":\"aft-ui-webdriverio.WebdriverIoVerifier\"},{\"kind\":2048,\"name\":\"withAdditionalSessionOptions\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html#withAdditionalSessionOptions\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-webdriverio.WebdriverIoVerifier\"},{\"kind\":2048,\"name\":\"getComponent\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html#getComponent\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-webdriverio.WebdriverIoVerifier\"},{\"kind\":2048,\"name\":\"_resolveAssertion\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html#_resolveAssertion\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected\",\"parent\":\"aft-ui-webdriverio.WebdriverIoVerifier\"},{\"kind\":1024,\"name\":\"_aftCfg\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html#_aftCfg\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoVerifier\"},{\"kind\":1024,\"name\":\"_matcher\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html#_matcher\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoVerifier\"},{\"kind\":1024,\"name\":\"_description\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html#_description\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoVerifier\"},{\"kind\":1024,\"name\":\"_startTime\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html#_startTime\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoVerifier\"},{\"kind\":1024,\"name\":\"_innerPromise\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html#_innerPromise\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoVerifier\"},{\"kind\":1024,\"name\":\"_testIds\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html#_testIds\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoVerifier\"},{\"kind\":1024,\"name\":\"_reporter\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html#_reporter\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoVerifier\"},{\"kind\":1024,\"name\":\"_policyEngMgr\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html#_policyEngMgr\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoVerifier\"},{\"kind\":1024,\"name\":\"_buildInfoMgr\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html#_buildInfoMgr\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoVerifier\"},{\"kind\":1024,\"name\":\"_actionMap\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html#_actionMap\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoVerifier\"},{\"kind\":262144,\"name\":\"aftCfg\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html#aftCfg\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoVerifier\"},{\"kind\":262144,\"name\":\"reporter\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html#reporter\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoVerifier\"},{\"kind\":262144,\"name\":\"policyEngMgr\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html#policyEngMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoVerifier\"},{\"kind\":262144,\"name\":\"buildInfoMgr\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html#buildInfoMgr\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoVerifier\"},{\"kind\":2048,\"name\":\"then\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html#then\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoVerifier\"},{\"kind\":2048,\"name\":\"_getInnerPromise\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html#_getInnerPromise\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoVerifier\"},{\"kind\":262144,\"name\":\"and\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html#and\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoVerifier\"},{\"kind\":2048,\"name\":\"on\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html#on\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoVerifier\"},{\"kind\":2048,\"name\":\"verify\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html#verify\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoVerifier\"},{\"kind\":2048,\"name\":\"withDescription\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html#withDescription\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoVerifier\"},{\"kind\":2048,\"name\":\"withTestIds\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html#withTestIds\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoVerifier\"},{\"kind\":2048,\"name\":\"returns\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html#returns\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoVerifier\"},{\"kind\":2048,\"name\":\"shouldRun\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html#shouldRun\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoVerifier\"},{\"kind\":2048,\"name\":\"_logResult\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html#_logResult\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoVerifier\"},{\"kind\":2048,\"name\":\"_logMessage\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html#_logMessage\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoVerifier\"},{\"kind\":2048,\"name\":\"_generateTestResults\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html#_generateTestResults\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoVerifier\"},{\"kind\":2048,\"name\":\"_generateTestResult\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoVerifier.html#_generateTestResult\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-protected tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoVerifier\"},{\"kind\":64,\"name\":\"verifyWithWebdriverIO\",\"url\":\"functions/aft_ui_webdriverio.verifyWithWebdriverIO.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-module\",\"parent\":\"aft-ui-webdriverio\"},{\"kind\":128,\"name\":\"WebdriverIoRemoteSessionGeneratorPlugin\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoRemoteSessionGeneratorPlugin.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-ui-webdriverio\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoRemoteSessionGeneratorPlugin.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoRemoteSessionGeneratorPlugin\"},{\"kind\":2048,\"name\":\"getSession\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoRemoteSessionGeneratorPlugin.html#getSession\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-ui-webdriverio.WebdriverIoRemoteSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"enabled\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoRemoteSessionGeneratorPlugin.html#enabled\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoRemoteSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"aftCfg\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoRemoteSessionGeneratorPlugin.html#aftCfg\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoRemoteSessionGeneratorPlugin\"},{\"kind\":262144,\"name\":\"aftLogger\",\"url\":\"classes/aft_ui_webdriverio.WebdriverIoRemoteSessionGeneratorPlugin.html#aftLogger\",\"classes\":\"tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited\",\"parent\":\"aft-ui-webdriverio.WebdriverIoRemoteSessionGeneratorPlugin\"},{\"kind\":4,\"name\":\"XML\",\"url\":\"modules/aft_web_services.XML.html\",\"classes\":\"tsd-kind-namespace tsd-parent-kind-module\",\"parent\":\"aft-web-services\"},{\"kind\":64,\"name\":\"toObject\",\"url\":\"functions/aft_web_services.XML.toObject.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-namespace\",\"parent\":\"aft-web-services.XML\"},{\"kind\":4194304,\"name\":\"HttpMethod\",\"url\":\"types/aft_web_services.HttpMethod.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-web-services\"},{\"kind\":4194304,\"name\":\"HttpRequest\",\"url\":\"types/aft_web_services.HttpRequest.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-web-services\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_web_services.HttpRequest.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-web-services.HttpRequest\"},{\"kind\":1024,\"name\":\"url\",\"url\":\"types/aft_web_services.HttpRequest.html#__type.url\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpRequest.__type\"},{\"kind\":1024,\"name\":\"allowAutoRedirect\",\"url\":\"types/aft_web_services.HttpRequest.html#__type.allowAutoRedirect\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpRequest.__type\"},{\"kind\":1024,\"name\":\"headers\",\"url\":\"types/aft_web_services.HttpRequest.html#__type.headers\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpRequest.__type\"},{\"kind\":1024,\"name\":\"method\",\"url\":\"types/aft_web_services.HttpRequest.html#__type.method\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpRequest.__type\"},{\"kind\":1024,\"name\":\"postData\",\"url\":\"types/aft_web_services.HttpRequest.html#__type.postData\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpRequest.__type\"},{\"kind\":1024,\"name\":\"multipart\",\"url\":\"types/aft_web_services.HttpRequest.html#__type.multipart\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpRequest.__type\"},{\"kind\":1024,\"name\":\"reporter\",\"url\":\"types/aft_web_services.HttpRequest.html#__type.reporter\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpRequest.__type\"},{\"kind\":4194304,\"name\":\"HttpResponse\",\"url\":\"types/aft_web_services.HttpResponse.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-module\",\"parent\":\"aft-web-services\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_web_services.HttpResponse.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-web-services.HttpResponse\"},{\"kind\":1024,\"name\":\"headers\",\"url\":\"types/aft_web_services.HttpResponse.html#__type.headers\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpResponse.__type\"},{\"kind\":1024,\"name\":\"data\",\"url\":\"types/aft_web_services.HttpResponse.html#__type.data\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpResponse.__type\"},{\"kind\":1024,\"name\":\"statusCode\",\"url\":\"types/aft_web_services.HttpResponse.html#__type.statusCode\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpResponse.__type\"},{\"kind\":32,\"name\":\"httpData\",\"url\":\"variables/aft_web_services.httpData.html\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"aft-web-services\"},{\"kind\":4,\"name\":\"HttpHeaders\",\"url\":\"modules/aft_web_services.HttpHeaders.html\",\"classes\":\"tsd-kind-namespace tsd-parent-kind-module\",\"parent\":\"aft-web-services\"},{\"kind\":4,\"name\":\"MimeType\",\"url\":\"modules/aft_web_services.HttpHeaders.MimeType.html\",\"classes\":\"tsd-kind-namespace tsd-parent-kind-namespace\",\"parent\":\"aft-web-services.HttpHeaders\"},{\"kind\":32,\"name\":\"applicationOctetstream\",\"url\":\"variables/aft_web_services.HttpHeaders.MimeType.applicationOctetstream.html\",\"classes\":\"tsd-kind-variable tsd-parent-kind-namespace\",\"parent\":\"aft-web-services.HttpHeaders.MimeType\"},{\"kind\":32,\"name\":\"textPlain\",\"url\":\"variables/aft_web_services.HttpHeaders.MimeType.textPlain.html\",\"classes\":\"tsd-kind-variable tsd-parent-kind-namespace\",\"parent\":\"aft-web-services.HttpHeaders.MimeType\"},{\"kind\":32,\"name\":\"textCss\",\"url\":\"variables/aft_web_services.HttpHeaders.MimeType.textCss.html\",\"classes\":\"tsd-kind-variable tsd-parent-kind-namespace\",\"parent\":\"aft-web-services.HttpHeaders.MimeType\"},{\"kind\":32,\"name\":\"textHtml\",\"url\":\"variables/aft_web_services.HttpHeaders.MimeType.textHtml.html\",\"classes\":\"tsd-kind-variable tsd-parent-kind-namespace\",\"parent\":\"aft-web-services.HttpHeaders.MimeType\"},{\"kind\":32,\"name\":\"textXml\",\"url\":\"variables/aft_web_services.HttpHeaders.MimeType.textXml.html\",\"classes\":\"tsd-kind-variable tsd-parent-kind-namespace\",\"parent\":\"aft-web-services.HttpHeaders.MimeType\"},{\"kind\":32,\"name\":\"textJavascript\",\"url\":\"variables/aft_web_services.HttpHeaders.MimeType.textJavascript.html\",\"classes\":\"tsd-kind-variable tsd-parent-kind-namespace\",\"parent\":\"aft-web-services.HttpHeaders.MimeType\"},{\"kind\":32,\"name\":\"multipartFormData\",\"url\":\"variables/aft_web_services.HttpHeaders.MimeType.multipartFormData.html\",\"classes\":\"tsd-kind-variable tsd-parent-kind-namespace\",\"parent\":\"aft-web-services.HttpHeaders.MimeType\"},{\"kind\":32,\"name\":\"applicationJson\",\"url\":\"variables/aft_web_services.HttpHeaders.MimeType.applicationJson.html\",\"classes\":\"tsd-kind-variable tsd-parent-kind-namespace\",\"parent\":\"aft-web-services.HttpHeaders.MimeType\"},{\"kind\":4,\"name\":\"ContentType\",\"url\":\"modules/aft_web_services.HttpHeaders.ContentType.html\",\"classes\":\"tsd-kind-namespace tsd-parent-kind-namespace\",\"parent\":\"aft-web-services.HttpHeaders\"},{\"kind\":64,\"name\":\"get\",\"url\":\"functions/aft_web_services.HttpHeaders.ContentType.get.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-namespace\",\"parent\":\"aft-web-services.HttpHeaders.ContentType\"},{\"kind\":4194304,\"name\":\"CT\",\"url\":\"types/aft_web_services.HttpHeaders.ContentType.CT.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-namespace\",\"parent\":\"aft-web-services.HttpHeaders.ContentType\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_web_services.HttpHeaders.ContentType.CT.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-web-services.HttpHeaders.ContentType.CT\"},{\"kind\":1024,\"name\":\"Content-Type\",\"url\":\"types/aft_web_services.HttpHeaders.ContentType.CT.html#__type.Content_Type\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpHeaders.ContentType.CT.__type\"},{\"kind\":4,\"name\":\"Accept\",\"url\":\"modules/aft_web_services.HttpHeaders.Accept.html\",\"classes\":\"tsd-kind-namespace tsd-parent-kind-namespace\",\"parent\":\"aft-web-services.HttpHeaders\"},{\"kind\":64,\"name\":\"get\",\"url\":\"functions/aft_web_services.HttpHeaders.Accept.get.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-namespace\",\"parent\":\"aft-web-services.HttpHeaders.Accept\"},{\"kind\":4194304,\"name\":\"Acc\",\"url\":\"types/aft_web_services.HttpHeaders.Accept.Acc.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-namespace\",\"parent\":\"aft-web-services.HttpHeaders.Accept\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_web_services.HttpHeaders.Accept.Acc.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-web-services.HttpHeaders.Accept.Acc\"},{\"kind\":1024,\"name\":\"Accept\",\"url\":\"types/aft_web_services.HttpHeaders.Accept.Acc.html#__type.Accept\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpHeaders.Accept.Acc.__type\"},{\"kind\":4,\"name\":\"Authorization\",\"url\":\"modules/aft_web_services.HttpHeaders.Authorization.html\",\"classes\":\"tsd-kind-namespace tsd-parent-kind-namespace\",\"parent\":\"aft-web-services.HttpHeaders\"},{\"kind\":64,\"name\":\"basic\",\"url\":\"functions/aft_web_services.HttpHeaders.Authorization.basic.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-namespace\",\"parent\":\"aft-web-services.HttpHeaders.Authorization\"},{\"kind\":64,\"name\":\"digest\",\"url\":\"functions/aft_web_services.HttpHeaders.Authorization.digest.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-namespace\",\"parent\":\"aft-web-services.HttpHeaders.Authorization\"},{\"kind\":4194304,\"name\":\"Auth\",\"url\":\"types/aft_web_services.HttpHeaders.Authorization.Auth.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-namespace\",\"parent\":\"aft-web-services.HttpHeaders.Authorization\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_web_services.HttpHeaders.Authorization.Auth.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-web-services.HttpHeaders.Authorization.Auth\"},{\"kind\":1024,\"name\":\"Authorization\",\"url\":\"types/aft_web_services.HttpHeaders.Authorization.Auth.html#__type.Authorization\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpHeaders.Authorization.Auth.__type\"},{\"kind\":4194304,\"name\":\"DigestOptions\",\"url\":\"types/aft_web_services.HttpHeaders.Authorization.DigestOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-namespace\",\"parent\":\"aft-web-services.HttpHeaders.Authorization\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_web_services.HttpHeaders.Authorization.DigestOptions.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-web-services.HttpHeaders.Authorization.DigestOptions\"},{\"kind\":1024,\"name\":\"username\",\"url\":\"types/aft_web_services.HttpHeaders.Authorization.DigestOptions.html#__type.username\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpHeaders.Authorization.DigestOptions.__type\"},{\"kind\":1024,\"name\":\"realm\",\"url\":\"types/aft_web_services.HttpHeaders.Authorization.DigestOptions.html#__type.realm\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpHeaders.Authorization.DigestOptions.__type\"},{\"kind\":1024,\"name\":\"uri\",\"url\":\"types/aft_web_services.HttpHeaders.Authorization.DigestOptions.html#__type.uri\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpHeaders.Authorization.DigestOptions.__type\"},{\"kind\":1024,\"name\":\"algorithm\",\"url\":\"types/aft_web_services.HttpHeaders.Authorization.DigestOptions.html#__type.algorithm\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpHeaders.Authorization.DigestOptions.__type\"},{\"kind\":1024,\"name\":\"nonce\",\"url\":\"types/aft_web_services.HttpHeaders.Authorization.DigestOptions.html#__type.nonce\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpHeaders.Authorization.DigestOptions.__type\"},{\"kind\":1024,\"name\":\"nc\",\"url\":\"types/aft_web_services.HttpHeaders.Authorization.DigestOptions.html#__type.nc\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpHeaders.Authorization.DigestOptions.__type\"},{\"kind\":1024,\"name\":\"cnonce\",\"url\":\"types/aft_web_services.HttpHeaders.Authorization.DigestOptions.html#__type.cnonce\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpHeaders.Authorization.DigestOptions.__type\"},{\"kind\":1024,\"name\":\"qop\",\"url\":\"types/aft_web_services.HttpHeaders.Authorization.DigestOptions.html#__type.qop\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpHeaders.Authorization.DigestOptions.__type\"},{\"kind\":1024,\"name\":\"response\",\"url\":\"types/aft_web_services.HttpHeaders.Authorization.DigestOptions.html#__type.response\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpHeaders.Authorization.DigestOptions.__type\"},{\"kind\":1024,\"name\":\"opaque\",\"url\":\"types/aft_web_services.HttpHeaders.Authorization.DigestOptions.html#__type.opaque\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpHeaders.Authorization.DigestOptions.__type\"},{\"kind\":4,\"name\":\"Cookies\",\"url\":\"modules/aft_web_services.HttpHeaders.Cookies.html\",\"classes\":\"tsd-kind-namespace tsd-parent-kind-namespace\",\"parent\":\"aft-web-services.HttpHeaders\"},{\"kind\":64,\"name\":\"cookie\",\"url\":\"functions/aft_web_services.HttpHeaders.Cookies.cookie-1.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-namespace\",\"parent\":\"aft-web-services.HttpHeaders.Cookies\"},{\"kind\":64,\"name\":\"setCookie\",\"url\":\"functions/aft_web_services.HttpHeaders.Cookies.setCookie-1.html\",\"classes\":\"tsd-kind-function tsd-parent-kind-namespace\",\"parent\":\"aft-web-services.HttpHeaders.Cookies\"},{\"kind\":4194304,\"name\":\"Cookie\",\"url\":\"types/aft_web_services.HttpHeaders.Cookies.Cookie.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-namespace\",\"parent\":\"aft-web-services.HttpHeaders.Cookies\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_web_services.HttpHeaders.Cookies.Cookie.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-web-services.HttpHeaders.Cookies.Cookie\"},{\"kind\":1024,\"name\":\"Cookie\",\"url\":\"types/aft_web_services.HttpHeaders.Cookies.Cookie.html#__type.Cookie\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpHeaders.Cookies.Cookie.__type\"},{\"kind\":4194304,\"name\":\"SetCookie\",\"url\":\"types/aft_web_services.HttpHeaders.Cookies.SetCookie.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-namespace\",\"parent\":\"aft-web-services.HttpHeaders.Cookies\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_web_services.HttpHeaders.Cookies.SetCookie.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-web-services.HttpHeaders.Cookies.SetCookie\"},{\"kind\":1024,\"name\":\"Set-Cookie\",\"url\":\"types/aft_web_services.HttpHeaders.Cookies.SetCookie.html#__type.Set_Cookie\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpHeaders.Cookies.SetCookie.__type\"},{\"kind\":4194304,\"name\":\"SetCookieOptions\",\"url\":\"types/aft_web_services.HttpHeaders.Cookies.SetCookieOptions.html\",\"classes\":\"tsd-kind-type-alias tsd-parent-kind-namespace\",\"parent\":\"aft-web-services.HttpHeaders.Cookies\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"types/aft_web_services.HttpHeaders.Cookies.SetCookieOptions.html#__type\",\"classes\":\"tsd-kind-type-literal tsd-parent-kind-type-alias\",\"parent\":\"aft-web-services.HttpHeaders.Cookies.SetCookieOptions\"},{\"kind\":1024,\"name\":\"key\",\"url\":\"types/aft_web_services.HttpHeaders.Cookies.SetCookieOptions.html#__type.key\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpHeaders.Cookies.SetCookieOptions.__type\"},{\"kind\":1024,\"name\":\"val\",\"url\":\"types/aft_web_services.HttpHeaders.Cookies.SetCookieOptions.html#__type.val\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpHeaders.Cookies.SetCookieOptions.__type\"},{\"kind\":1024,\"name\":\"expires\",\"url\":\"types/aft_web_services.HttpHeaders.Cookies.SetCookieOptions.html#__type.expires\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpHeaders.Cookies.SetCookieOptions.__type\"},{\"kind\":1024,\"name\":\"secure\",\"url\":\"types/aft_web_services.HttpHeaders.Cookies.SetCookieOptions.html#__type.secure\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpHeaders.Cookies.SetCookieOptions.__type\"},{\"kind\":1024,\"name\":\"httpOnly\",\"url\":\"types/aft_web_services.HttpHeaders.Cookies.SetCookieOptions.html#__type.httpOnly\",\"classes\":\"tsd-kind-property tsd-parent-kind-type-literal\",\"parent\":\"aft-web-services.HttpHeaders.Cookies.SetCookieOptions.__type\"},{\"kind\":128,\"name\":\"HttpServiceConfig\",\"url\":\"classes/aft_web_services.HttpServiceConfig.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-web-services\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_web_services.HttpServiceConfig.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-web-services.HttpServiceConfig\"},{\"kind\":1024,\"name\":\"defaultUrl\",\"url\":\"classes/aft_web_services.HttpServiceConfig.html#defaultUrl\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-web-services.HttpServiceConfig\"},{\"kind\":1024,\"name\":\"defaultHeaders\",\"url\":\"classes/aft_web_services.HttpServiceConfig.html#defaultHeaders\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-web-services.HttpServiceConfig\"},{\"kind\":1024,\"name\":\"defaultMethod\",\"url\":\"classes/aft_web_services.HttpServiceConfig.html#defaultMethod\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-web-services.HttpServiceConfig\"},{\"kind\":1024,\"name\":\"defaultAllowRedirect\",\"url\":\"classes/aft_web_services.HttpServiceConfig.html#defaultAllowRedirect\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-web-services.HttpServiceConfig\"},{\"kind\":1024,\"name\":\"defaultPostData\",\"url\":\"classes/aft_web_services.HttpServiceConfig.html#defaultPostData\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-web-services.HttpServiceConfig\"},{\"kind\":1024,\"name\":\"defaultMultipart\",\"url\":\"classes/aft_web_services.HttpServiceConfig.html#defaultMultipart\",\"classes\":\"tsd-kind-property tsd-parent-kind-class\",\"parent\":\"aft-web-services.HttpServiceConfig\"},{\"kind\":128,\"name\":\"HttpService\",\"url\":\"classes/aft_web_services.HttpService.html\",\"classes\":\"tsd-kind-class tsd-parent-kind-module\",\"parent\":\"aft-web-services\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/aft_web_services.HttpService.html#constructor\",\"classes\":\"tsd-kind-constructor tsd-parent-kind-class\",\"parent\":\"aft-web-services.HttpService\"},{\"kind\":1024,\"name\":\"aftCfg\",\"url\":\"classes/aft_web_services.HttpService.html#aftCfg\",\"classes\":\"tsd-kind-property tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-web-services.HttpService\"},{\"kind\":2048,\"name\":\"performRequest\",\"url\":\"classes/aft_web_services.HttpService.html#performRequest\",\"classes\":\"tsd-kind-method tsd-parent-kind-class\",\"parent\":\"aft-web-services.HttpService\"},{\"kind\":2048,\"name\":\"setRequestDefaults\",\"url\":\"classes/aft_web_services.HttpService.html#setRequestDefaults\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-web-services.HttpService\"},{\"kind\":2048,\"name\":\"_request\",\"url\":\"classes/aft_web_services.HttpService.html#_request\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-web-services.HttpService\"},{\"kind\":2048,\"name\":\"_response\",\"url\":\"classes/aft_web_services.HttpService.html#_response\",\"classes\":\"tsd-kind-method tsd-parent-kind-class tsd-is-private\",\"parent\":\"aft-web-services.HttpService\"},{\"kind\":32,\"name\":\"httpService\",\"url\":\"variables/aft_web_services.httpService-1.html\",\"classes\":\"tsd-kind-variable tsd-parent-kind-module\",\"parent\":\"aft-web-services\"}],\"index\":{\"version\":\"2.3.9\",\"fields\":[\"name\",\"comment\"],\"fieldVectors\":[[\"name/0\",[0,30.451,1,45.15]],[\"comment/0\",[]],[\"name/1\",[0,23.664,2,35.088,3,21.64]],[\"comment/1\",[]],[\"name/2\",[0,23.664,3,21.64,4,35.088]],[\"comment/2\",[]],[\"name/3\",[0,16.368,5,20.983,6,24.27,7,24.27,8,24.27]],[\"comment/3\",[]],[\"name/4\",[0,23.664,5,30.336,9,35.088]],[\"comment/4\",[]],[\"name/5\",[0,23.664,5,30.336,10,35.088]],[\"comment/5\",[]],[\"name/6\",[0,30.451,11,45.15]],[\"comment/6\",[]],[\"name/7\",[0,30.451,12,39.036]],[\"comment/7\",[]],[\"name/8\",[0,23.664,12,30.336,13,35.088]],[\"comment/8\",[]],[\"name/9\",[0,23.664,12,30.336,14,35.088]],[\"comment/9\",[]],[\"name/10\",[0,23.664,15,35.088,16,35.088]],[\"comment/10\",[]],[\"name/11\",[17,58.136]],[\"comment/11\",[]],[\"name/12\",[18,28.778]],[\"comment/12\",[]],[\"name/13\",[19,63.305]],[\"comment/13\",[]],[\"name/14\",[20,63.305]],[\"comment/14\",[]],[\"name/15\",[21,63.305]],[\"comment/15\",[]],[\"name/16\",[22,63.305]],[\"comment/16\",[]],[\"name/17\",[23,63.305]],[\"comment/17\",[]],[\"name/18\",[24,39.674]],[\"comment/18\",[]],[\"name/19\",[25,63.305]],[\"comment/19\",[]],[\"name/20\",[26,63.305]],[\"comment/20\",[]],[\"name/21\",[27,63.305]],[\"comment/21\",[]],[\"name/22\",[28,63.305]],[\"comment/22\",[]],[\"name/23\",[29,58.136]],[\"comment/23\",[]],[\"name/24\",[30,63.305]],[\"comment/24\",[]],[\"name/25\",[31,63.305]],[\"comment/25\",[]],[\"name/26\",[32,63.305]],[\"comment/26\",[]],[\"name/27\",[33,47.02]],[\"comment/27\",[]],[\"name/28\",[34,52.189]],[\"comment/28\",[]],[\"name/29\",[35,63.305]],[\"comment/29\",[]],[\"name/30\",[36,63.305]],[\"comment/30\",[]],[\"name/31\",[37,63.305]],[\"comment/31\",[]],[\"name/32\",[38,63.305]],[\"comment/32\",[]],[\"name/33\",[17,58.136]],[\"comment/33\",[]],[\"name/34\",[39,63.305]],[\"comment/34\",[]],[\"name/35\",[18,28.778]],[\"comment/35\",[]],[\"name/36\",[40,63.305]],[\"comment/36\",[]],[\"name/37\",[41,63.305]],[\"comment/37\",[]],[\"name/38\",[42,58.136]],[\"comment/38\",[]],[\"name/39\",[43,58.136]],[\"comment/39\",[]],[\"name/40\",[44,58.136]],[\"comment/40\",[]],[\"name/41\",[33,47.02]],[\"comment/41\",[]],[\"name/42\",[45,58.136]],[\"comment/42\",[]],[\"name/43\",[34,52.189]],[\"comment/43\",[]],[\"name/44\",[46,58.136]],[\"comment/44\",[]],[\"name/45\",[47,58.136]],[\"comment/45\",[]],[\"name/46\",[48,58.136]],[\"comment/46\",[]],[\"name/47\",[49,58.136]],[\"comment/47\",[]],[\"name/48\",[50,63.305]],[\"comment/48\",[]],[\"name/49\",[51,58.136]],[\"comment/49\",[]],[\"name/50\",[52,58.136]],[\"comment/50\",[]],[\"name/51\",[53,58.136]],[\"comment/51\",[]],[\"name/52\",[54,34.248]],[\"comment/52\",[]],[\"name/53\",[55,63.305]],[\"comment/53\",[]],[\"name/54\",[56,63.305]],[\"comment/54\",[]],[\"name/55\",[53,58.136]],[\"comment/55\",[]],[\"name/56\",[57,63.305]],[\"comment/56\",[]],[\"name/57\",[58,63.305]],[\"comment/57\",[]],[\"name/58\",[59,63.305]],[\"comment/58\",[]],[\"name/59\",[54,34.248]],[\"comment/59\",[]],[\"name/60\",[60,63.305]],[\"comment/60\",[]],[\"name/61\",[54,34.248]],[\"comment/61\",[]],[\"name/62\",[61,63.305]],[\"comment/62\",[]],[\"name/63\",[62,63.305]],[\"comment/63\",[]],[\"name/64\",[54,34.248]],[\"comment/64\",[]],[\"name/65\",[63,63.305]],[\"comment/65\",[]],[\"name/66\",[64,63.305]],[\"comment/66\",[]],[\"name/67\",[65,63.305]],[\"comment/67\",[]],[\"name/68\",[66,63.305]],[\"comment/68\",[]],[\"name/69\",[54,34.248]],[\"comment/69\",[]],[\"name/70\",[67,58.136]],[\"comment/70\",[]],[\"name/71\",[68,54.731]],[\"comment/71\",[]],[\"name/72\",[69,63.305]],[\"comment/72\",[]],[\"name/73\",[54,34.248]],[\"comment/73\",[]],[\"name/74\",[70,63.305]],[\"comment/74\",[]],[\"name/75\",[71,58.136]],[\"comment/75\",[]],[\"name/76\",[72,63.305]],[\"comment/76\",[]],[\"name/77\",[29,58.136]],[\"comment/77\",[]],[\"name/78\",[73,63.305]],[\"comment/78\",[]],[\"name/79\",[74,63.305]],[\"comment/79\",[]],[\"name/80\",[75,63.305]],[\"comment/80\",[]],[\"name/81\",[76,63.305]],[\"comment/81\",[]],[\"name/82\",[54,34.248]],[\"comment/82\",[]],[\"name/83\",[77,63.305]],[\"comment/83\",[]],[\"name/84\",[78,63.305]],[\"comment/84\",[]],[\"name/85\",[79,58.136]],[\"comment/85\",[]],[\"name/86\",[80,54.731]],[\"comment/86\",[]],[\"name/87\",[18,28.778]],[\"comment/87\",[]],[\"name/88\",[80,54.731]],[\"comment/88\",[]],[\"name/89\",[81,63.305]],[\"comment/89\",[]],[\"name/90\",[79,58.136]],[\"comment/90\",[]],[\"name/91\",[82,63.305]],[\"comment/91\",[]],[\"name/92\",[83,58.136]],[\"comment/92\",[]],[\"name/93\",[68,54.731]],[\"comment/93\",[]],[\"name/94\",[84,63.305]],[\"comment/94\",[]],[\"name/95\",[85,63.305]],[\"comment/95\",[]],[\"name/96\",[86,63.305]],[\"comment/96\",[]],[\"name/97\",[87,63.305]],[\"comment/97\",[]],[\"name/98\",[88,63.305]],[\"comment/98\",[]],[\"name/99\",[89,63.305]],[\"comment/99\",[]],[\"name/100\",[90,63.305]],[\"comment/100\",[]],[\"name/101\",[80,54.731]],[\"comment/101\",[]],[\"name/102\",[91,63.305]],[\"comment/102\",[]],[\"name/103\",[92,63.305]],[\"comment/103\",[]],[\"name/104\",[93,63.305]],[\"comment/104\",[]],[\"name/105\",[94,63.305]],[\"comment/105\",[]],[\"name/106\",[95,58.136]],[\"comment/106\",[]],[\"name/107\",[18,28.778]],[\"comment/107\",[]],[\"name/108\",[96,32.825]],[\"comment/108\",[]],[\"name/109\",[97,63.305]],[\"comment/109\",[]],[\"name/110\",[98,63.305]],[\"comment/110\",[]],[\"name/111\",[99,63.305]],[\"comment/111\",[]],[\"name/112\",[100,63.305]],[\"comment/112\",[]],[\"name/113\",[101,63.305]],[\"comment/113\",[]],[\"name/114\",[102,63.305]],[\"comment/114\",[]],[\"name/115\",[103,63.305]],[\"comment/115\",[]],[\"name/116\",[95,58.136]],[\"comment/116\",[]],[\"name/117\",[33,47.02]],[\"comment/117\",[]],[\"name/118\",[104,63.305]],[\"comment/118\",[]],[\"name/119\",[105,63.305]],[\"comment/119\",[]],[\"name/120\",[18,28.778]],[\"comment/120\",[]],[\"name/121\",[106,58.136]],[\"comment/121\",[]],[\"name/122\",[107,63.305]],[\"comment/122\",[]],[\"name/123\",[108,47.02]],[\"comment/123\",[]],[\"name/124\",[42,58.136]],[\"comment/124\",[]],[\"name/125\",[43,58.136]],[\"comment/125\",[]],[\"name/126\",[44,58.136]],[\"comment/126\",[]],[\"name/127\",[33,47.02]],[\"comment/127\",[]],[\"name/128\",[45,58.136]],[\"comment/128\",[]],[\"name/129\",[34,52.189]],[\"comment/129\",[]],[\"name/130\",[46,58.136]],[\"comment/130\",[]],[\"name/131\",[47,58.136]],[\"comment/131\",[]],[\"name/132\",[48,58.136]],[\"comment/132\",[]],[\"name/133\",[49,58.136]],[\"comment/133\",[]],[\"name/134\",[109,63.305]],[\"comment/134\",[]],[\"name/135\",[110,63.305]],[\"comment/135\",[]],[\"name/136\",[51,58.136]],[\"comment/136\",[]],[\"name/137\",[52,58.136]],[\"comment/137\",[]],[\"name/138\",[111,63.305]],[\"comment/138\",[]],[\"name/139\",[54,34.248]],[\"comment/139\",[]],[\"name/140\",[112,63.305]],[\"comment/140\",[]],[\"name/141\",[113,63.305]],[\"comment/141\",[]],[\"name/142\",[114,58.136]],[\"comment/142\",[]],[\"name/143\",[115,63.305]],[\"comment/143\",[]],[\"name/144\",[116,63.305]],[\"comment/144\",[]],[\"name/145\",[117,58.136]],[\"comment/145\",[]],[\"name/146\",[118,63.305]],[\"comment/146\",[]],[\"name/147\",[18,28.778]],[\"comment/147\",[]],[\"name/148\",[108,47.02]],[\"comment/148\",[]],[\"name/149\",[119,63.305]],[\"comment/149\",[]],[\"name/150\",[120,63.305]],[\"comment/150\",[]],[\"name/151\",[121,63.305]],[\"comment/151\",[]],[\"name/152\",[122,63.305]],[\"comment/152\",[]],[\"name/153\",[123,63.305]],[\"comment/153\",[]],[\"name/154\",[124,63.305]],[\"comment/154\",[]],[\"name/155\",[125,63.305]],[\"comment/155\",[]],[\"name/156\",[126,63.305]],[\"comment/156\",[]],[\"name/157\",[127,63.305]],[\"comment/157\",[]],[\"name/158\",[128,63.305]],[\"comment/158\",[]],[\"name/159\",[129,63.305]],[\"comment/159\",[]],[\"name/160\",[130,63.305]],[\"comment/160\",[]],[\"name/161\",[131,63.305]],[\"comment/161\",[]],[\"name/162\",[132,63.305]],[\"comment/162\",[]],[\"name/163\",[67,58.136]],[\"comment/163\",[]],[\"name/164\",[133,63.305]],[\"comment/164\",[]],[\"name/165\",[134,63.305]],[\"comment/165\",[]],[\"name/166\",[135,63.305]],[\"comment/166\",[]],[\"name/167\",[136,63.305]],[\"comment/167\",[]],[\"name/168\",[137,63.305]],[\"comment/168\",[]],[\"name/169\",[138,63.305]],[\"comment/169\",[]],[\"name/170\",[139,63.305]],[\"comment/170\",[]],[\"name/171\",[140,63.305]],[\"comment/171\",[]],[\"name/172\",[141,63.305]],[\"comment/172\",[]],[\"name/173\",[142,63.305]],[\"comment/173\",[]],[\"name/174\",[143,63.305]],[\"comment/174\",[]],[\"name/175\",[144,63.305]],[\"comment/175\",[]],[\"name/176\",[145,52.189]],[\"comment/176\",[]],[\"name/177\",[146,52.189]],[\"comment/177\",[]],[\"name/178\",[117,58.136]],[\"comment/178\",[]],[\"name/179\",[147,63.305]],[\"comment/179\",[]],[\"name/180\",[148,63.305]],[\"comment/180\",[]],[\"name/181\",[149,50.158]],[\"comment/181\",[]],[\"name/182\",[150,63.305]],[\"comment/182\",[]],[\"name/183\",[151,39.674]],[\"comment/183\",[]],[\"name/184\",[18,28.778]],[\"comment/184\",[]],[\"name/185\",[96,32.825]],[\"comment/185\",[]],[\"name/186\",[24,39.674]],[\"comment/186\",[]],[\"name/187\",[152,47.02]],[\"comment/187\",[]],[\"name/188\",[153,63.305]],[\"comment/188\",[]],[\"name/189\",[154,63.305]],[\"comment/189\",[]],[\"name/190\",[151,39.674]],[\"comment/190\",[]],[\"name/191\",[24,39.674]],[\"comment/191\",[]],[\"name/192\",[24,39.674]],[\"comment/192\",[]],[\"name/193\",[155,63.305]],[\"comment/193\",[]],[\"name/194\",[156,63.305]],[\"comment/194\",[]],[\"name/195\",[157,63.305]],[\"comment/195\",[]],[\"name/196\",[54,34.248]],[\"comment/196\",[]],[\"name/197\",[158,63.305]],[\"comment/197\",[]],[\"name/198\",[159,63.305]],[\"comment/198\",[]],[\"name/199\",[68,54.731]],[\"comment/199\",[]],[\"name/200\",[160,63.305]],[\"comment/200\",[]],[\"name/201\",[161,63.305]],[\"comment/201\",[]],[\"name/202\",[18,28.778]],[\"comment/202\",[]],[\"name/203\",[162,37.352]],[\"comment/203\",[]],[\"name/204\",[163,63.305]],[\"comment/204\",[]],[\"name/205\",[18,28.778]],[\"comment/205\",[]],[\"name/206\",[108,47.02]],[\"comment/206\",[]],[\"name/207\",[164,52.189]],[\"comment/207\",[]],[\"name/208\",[96,32.825]],[\"comment/208\",[]],[\"name/209\",[151,39.674]],[\"comment/209\",[]],[\"name/210\",[162,37.352]],[\"comment/210\",[]],[\"name/211\",[165,63.305]],[\"comment/211\",[]],[\"name/212\",[166,63.305]],[\"comment/212\",[]],[\"name/213\",[18,28.778]],[\"comment/213\",[]],[\"name/214\",[96,32.825]],[\"comment/214\",[]],[\"name/215\",[167,52.189]],[\"comment/215\",[]],[\"name/216\",[168,63.305]],[\"comment/216\",[]],[\"name/217\",[164,52.189]],[\"comment/217\",[]],[\"name/218\",[33,47.02]],[\"comment/218\",[]],[\"name/219\",[169,58.136]],[\"comment/219\",[]],[\"name/220\",[170,58.136]],[\"comment/220\",[]],[\"name/221\",[171,63.305]],[\"comment/221\",[]],[\"name/222\",[18,28.778]],[\"comment/222\",[]],[\"name/223\",[169,58.136]],[\"comment/223\",[]],[\"name/224\",[170,58.136]],[\"comment/224\",[]],[\"name/225\",[96,32.825]],[\"comment/225\",[]],[\"name/226\",[151,39.674]],[\"comment/226\",[]],[\"name/227\",[162,37.352]],[\"comment/227\",[]],[\"name/228\",[172,63.305]],[\"comment/228\",[]],[\"name/229\",[18,28.778]],[\"comment/229\",[]],[\"name/230\",[24,39.674]],[\"comment/230\",[]],[\"name/231\",[162,37.352]],[\"comment/231\",[]],[\"name/232\",[173,63.305]],[\"comment/232\",[]],[\"name/233\",[18,28.778]],[\"comment/233\",[]],[\"name/234\",[162,37.352]],[\"comment/234\",[]],[\"name/235\",[24,39.674]],[\"comment/235\",[]],[\"name/236\",[174,50.158]],[\"comment/236\",[]],[\"name/237\",[152,47.02]],[\"comment/237\",[]],[\"name/238\",[175,48.468]],[\"comment/238\",[]],[\"name/239\",[176,50.158]],[\"comment/239\",[]],[\"name/240\",[96,32.825]],[\"comment/240\",[]],[\"name/241\",[151,39.674]],[\"comment/241\",[]],[\"name/242\",[3,39.042]],[\"comment/242\",[]],[\"name/243\",[18,28.778]],[\"comment/243\",[]],[\"name/244\",[167,52.189]],[\"comment/244\",[]],[\"name/245\",[164,52.189]],[\"comment/245\",[]],[\"name/246\",[177,63.305]],[\"comment/246\",[]],[\"name/247\",[178,63.305]],[\"comment/247\",[]],[\"name/248\",[24,39.674]],[\"comment/248\",[]],[\"name/249\",[179,63.305]],[\"comment/249\",[]],[\"name/250\",[180,63.305]],[\"comment/250\",[]],[\"name/251\",[181,63.305]],[\"comment/251\",[]],[\"name/252\",[182,63.305]],[\"comment/252\",[]],[\"name/253\",[183,63.305]],[\"comment/253\",[]],[\"name/254\",[184,54.731]],[\"comment/254\",[]],[\"name/255\",[185,54.731]],[\"comment/255\",[]],[\"name/256\",[186,63.305]],[\"comment/256\",[]],[\"name/257\",[152,47.02]],[\"comment/257\",[]],[\"name/258\",[175,48.468]],[\"comment/258\",[]],[\"name/259\",[149,50.158]],[\"comment/259\",[]],[\"name/260\",[187,63.305]],[\"comment/260\",[]],[\"name/261\",[54,34.248]],[\"comment/261\",[]],[\"name/262\",[188,63.305]],[\"comment/262\",[]],[\"name/263\",[189,63.305]],[\"comment/263\",[]],[\"name/264\",[190,63.305]],[\"comment/264\",[]],[\"name/265\",[191,63.305]],[\"comment/265\",[]],[\"name/266\",[192,63.305]],[\"comment/266\",[]],[\"name/267\",[193,63.305]],[\"comment/267\",[]],[\"name/268\",[194,63.305]],[\"comment/268\",[]],[\"name/269\",[195,63.305]],[\"comment/269\",[]],[\"name/270\",[196,63.305]],[\"comment/270\",[]],[\"name/271\",[18,28.778]],[\"comment/271\",[]],[\"name/272\",[197,45.753]],[\"comment/272\",[]],[\"name/273\",[96,32.825]],[\"comment/273\",[]],[\"name/274\",[151,39.674]],[\"comment/274\",[]],[\"name/275\",[162,37.352]],[\"comment/275\",[]],[\"name/276\",[198,63.305]],[\"comment/276\",[]],[\"name/277\",[18,28.778]],[\"comment/277\",[]],[\"name/278\",[96,32.825]],[\"comment/278\",[]],[\"name/279\",[167,52.189]],[\"comment/279\",[]],[\"name/280\",[164,52.189]],[\"comment/280\",[]],[\"name/281\",[197,45.753]],[\"comment/281\",[]],[\"name/282\",[199,63.305]],[\"comment/282\",[]],[\"name/283\",[200,63.305]],[\"comment/283\",[]],[\"name/284\",[201,63.305]],[\"comment/284\",[]],[\"name/285\",[18,28.778]],[\"comment/285\",[]],[\"name/286\",[108,47.02]],[\"comment/286\",[]],[\"name/287\",[202,54.731]],[\"comment/287\",[]],[\"name/288\",[203,54.731]],[\"comment/288\",[]],[\"name/289\",[204,54.731]],[\"comment/289\",[]],[\"name/290\",[205,54.731]],[\"comment/290\",[]],[\"name/291\",[206,54.731]],[\"comment/291\",[]],[\"name/292\",[207,54.731]],[\"comment/292\",[]],[\"name/293\",[208,52.189]],[\"comment/293\",[]],[\"name/294\",[209,54.731]],[\"comment/294\",[]],[\"name/295\",[210,54.731]],[\"comment/295\",[]],[\"name/296\",[211,54.731]],[\"comment/296\",[]],[\"name/297\",[96,32.825]],[\"comment/297\",[]],[\"name/298\",[3,39.042]],[\"comment/298\",[]],[\"name/299\",[212,54.731]],[\"comment/299\",[]],[\"name/300\",[213,52.189]],[\"comment/300\",[]],[\"name/301\",[145,52.189]],[\"comment/301\",[]],[\"name/302\",[146,52.189]],[\"comment/302\",[]],[\"name/303\",[214,54.731]],[\"comment/303\",[]],[\"name/304\",[215,54.731]],[\"comment/304\",[]],[\"name/305\",[216,54.731]],[\"comment/305\",[]],[\"name/306\",[217,48.468]],[\"comment/306\",[]],[\"name/307\",[218,54.731]],[\"comment/307\",[]],[\"name/308\",[219,54.731]],[\"comment/308\",[]],[\"name/309\",[220,54.731]],[\"comment/309\",[]],[\"name/310\",[221,54.731]],[\"comment/310\",[]],[\"name/311\",[197,45.753]],[\"comment/311\",[]],[\"name/312\",[222,50.158]],[\"comment/312\",[]],[\"name/313\",[223,50.158]],[\"comment/313\",[]],[\"name/314\",[224,50.158]],[\"comment/314\",[]],[\"name/315\",[225,50.158]],[\"comment/315\",[]],[\"name/316\",[217,48.468]],[\"comment/316\",[]],[\"name/317\",[226,63.305]],[\"comment/317\",[]],[\"name/318\",[54,34.248]],[\"comment/318\",[]],[\"name/319\",[227,63.305]],[\"comment/319\",[]],[\"name/320\",[54,34.248]],[\"comment/320\",[]],[\"name/321\",[228,63.305]],[\"comment/321\",[]],[\"name/322\",[54,34.248]],[\"comment/322\",[]],[\"name/323\",[229,63.305]],[\"comment/323\",[]],[\"name/324\",[54,34.248]],[\"comment/324\",[]],[\"name/325\",[230,63.305]],[\"comment/325\",[]],[\"name/326\",[54,34.248]],[\"comment/326\",[]],[\"name/327\",[231,63.305]],[\"comment/327\",[]],[\"name/328\",[232,63.305]],[\"comment/328\",[]],[\"name/329\",[233,63.305]],[\"comment/329\",[]],[\"name/330\",[234,63.305]],[\"comment/330\",[]],[\"name/331\",[235,63.305]],[\"comment/331\",[]],[\"name/332\",[236,63.305]],[\"comment/332\",[]],[\"name/333\",[237,63.305]],[\"comment/333\",[]],[\"name/334\",[238,63.305]],[\"comment/334\",[]],[\"name/335\",[239,63.305]],[\"comment/335\",[]],[\"name/336\",[240,63.305]],[\"comment/336\",[]],[\"name/337\",[241,63.305]],[\"comment/337\",[]],[\"name/338\",[242,63.305]],[\"comment/338\",[]],[\"name/339\",[243,63.305]],[\"comment/339\",[]],[\"name/340\",[244,63.305]],[\"comment/340\",[]],[\"name/341\",[18,28.778]],[\"comment/341\",[]],[\"name/342\",[245,63.305]],[\"comment/342\",[]],[\"name/343\",[246,58.136]],[\"comment/343\",[]],[\"name/344\",[247,63.305]],[\"comment/344\",[]],[\"name/345\",[248,63.305]],[\"comment/345\",[]],[\"name/346\",[249,63.305]],[\"comment/346\",[]],[\"name/347\",[250,63.305]],[\"comment/347\",[]],[\"name/348\",[251,58.136]],[\"comment/348\",[]],[\"name/349\",[18,28.778]],[\"comment/349\",[]],[\"name/350\",[252,58.136]],[\"comment/350\",[]],[\"name/351\",[108,47.02]],[\"comment/351\",[]],[\"name/352\",[246,58.136]],[\"comment/352\",[]],[\"name/353\",[253,52.189]],[\"comment/353\",[]],[\"name/354\",[254,58.136]],[\"comment/354\",[]],[\"name/355\",[96,32.825]],[\"comment/355\",[]],[\"name/356\",[3,39.042]],[\"comment/356\",[]],[\"name/357\",[255,58.136]],[\"comment/357\",[]],[\"name/358\",[18,28.778]],[\"comment/358\",[]],[\"name/359\",[256,58.136]],[\"comment/359\",[]],[\"name/360\",[257,58.136]],[\"comment/360\",[]],[\"name/361\",[213,52.189]],[\"comment/361\",[]],[\"name/362\",[258,58.136]],[\"comment/362\",[]],[\"name/363\",[184,54.731]],[\"comment/363\",[]],[\"name/364\",[185,54.731]],[\"comment/364\",[]],[\"name/365\",[259,58.136]],[\"comment/365\",[]],[\"name/366\",[197,45.753]],[\"comment/366\",[]],[\"name/367\",[217,48.468]],[\"comment/367\",[]],[\"name/368\",[260,58.136]],[\"comment/368\",[]],[\"name/369\",[149,50.158]],[\"comment/369\",[]],[\"name/370\",[222,50.158]],[\"comment/370\",[]],[\"name/371\",[223,50.158]],[\"comment/371\",[]],[\"name/372\",[224,50.158]],[\"comment/372\",[]],[\"name/373\",[225,50.158]],[\"comment/373\",[]],[\"name/374\",[253,52.189]],[\"comment/374\",[]],[\"name/375\",[254,58.136]],[\"comment/375\",[]],[\"name/376\",[96,32.825]],[\"comment/376\",[]],[\"name/377\",[3,39.042]],[\"comment/377\",[]],[\"name/378\",[251,58.136]],[\"comment/378\",[]],[\"name/379\",[18,28.778]],[\"comment/379\",[]],[\"name/380\",[252,58.136]],[\"comment/380\",[]],[\"name/381\",[253,52.189]],[\"comment/381\",[]],[\"name/382\",[96,32.825]],[\"comment/382\",[]],[\"name/383\",[261,58.136]],[\"comment/383\",[]],[\"name/384\",[3,39.042]],[\"comment/384\",[]],[\"name/385\",[149,50.158]],[\"comment/385\",[]],[\"name/386\",[255,58.136]],[\"comment/386\",[]],[\"name/387\",[18,28.778]],[\"comment/387\",[]],[\"name/388\",[256,58.136]],[\"comment/388\",[]],[\"name/389\",[257,58.136]],[\"comment/389\",[]],[\"name/390\",[258,58.136]],[\"comment/390\",[]],[\"name/391\",[184,54.731]],[\"comment/391\",[]],[\"name/392\",[185,54.731]],[\"comment/392\",[]],[\"name/393\",[259,58.136]],[\"comment/393\",[]],[\"name/394\",[197,45.753]],[\"comment/394\",[]],[\"name/395\",[217,48.468]],[\"comment/395\",[]],[\"name/396\",[260,58.136]],[\"comment/396\",[]],[\"name/397\",[222,50.158]],[\"comment/397\",[]],[\"name/398\",[223,50.158]],[\"comment/398\",[]],[\"name/399\",[224,50.158]],[\"comment/399\",[]],[\"name/400\",[225,50.158]],[\"comment/400\",[]],[\"name/401\",[253,52.189]],[\"comment/401\",[]],[\"name/402\",[96,32.825]],[\"comment/402\",[]],[\"name/403\",[261,58.136]],[\"comment/403\",[]],[\"name/404\",[3,39.042]],[\"comment/404\",[]],[\"name/405\",[149,50.158]],[\"comment/405\",[]],[\"name/406\",[262,63.305]],[\"comment/406\",[]],[\"name/407\",[18,28.778]],[\"comment/407\",[]],[\"name/408\",[263,63.305]],[\"comment/408\",[]],[\"name/409\",[264,63.305]],[\"comment/409\",[]],[\"name/410\",[18,28.778]],[\"comment/410\",[]],[\"name/411\",[265,58.136]],[\"comment/411\",[]],[\"name/412\",[266,58.136]],[\"comment/412\",[]],[\"name/413\",[267,58.136]],[\"comment/413\",[]],[\"name/414\",[268,58.136]],[\"comment/414\",[]],[\"name/415\",[24,39.674]],[\"comment/415\",[]],[\"name/416\",[162,37.352]],[\"comment/416\",[]],[\"name/417\",[269,63.305]],[\"comment/417\",[]],[\"name/418\",[18,28.778]],[\"comment/418\",[]],[\"name/419\",[270,54.731]],[\"comment/419\",[]],[\"name/420\",[271,63.305]],[\"comment/420\",[]],[\"name/421\",[272,52.189]],[\"comment/421\",[]],[\"name/422\",[273,63.305]],[\"comment/422\",[]],[\"name/423\",[24,39.674]],[\"comment/423\",[]],[\"name/424\",[274,63.305]],[\"comment/424\",[]],[\"name/425\",[265,58.136]],[\"comment/425\",[]],[\"name/426\",[266,58.136]],[\"comment/426\",[]],[\"name/427\",[267,58.136]],[\"comment/427\",[]],[\"name/428\",[268,58.136]],[\"comment/428\",[]],[\"name/429\",[275,63.305]],[\"comment/429\",[]],[\"name/430\",[276,54.731]],[\"comment/430\",[]],[\"name/431\",[174,50.158]],[\"comment/431\",[]],[\"name/432\",[152,47.02]],[\"comment/432\",[]],[\"name/433\",[175,48.468]],[\"comment/433\",[]],[\"name/434\",[176,50.158]],[\"comment/434\",[]],[\"name/435\",[277,63.305]],[\"comment/435\",[]],[\"name/436\",[278,63.305]],[\"comment/436\",[]],[\"name/437\",[279,63.305]],[\"comment/437\",[]],[\"name/438\",[280,63.305]],[\"comment/438\",[]],[\"name/439\",[162,37.352]],[\"comment/439\",[]],[\"name/440\",[96,32.825]],[\"comment/440\",[]],[\"name/441\",[151,39.674]],[\"comment/441\",[]],[\"name/442\",[281,63.305]],[\"comment/442\",[]],[\"name/443\",[18,28.778]],[\"comment/443\",[]],[\"name/444\",[24,39.674]],[\"comment/444\",[]],[\"name/445\",[282,63.305]],[\"comment/445\",[]],[\"name/446\",[283,63.305]],[\"comment/446\",[]],[\"name/447\",[284,63.305]],[\"comment/447\",[]],[\"name/448\",[162,37.352]],[\"comment/448\",[]],[\"name/449\",[285,63.305]],[\"comment/449\",[]],[\"name/450\",[18,28.778]],[\"comment/450\",[]],[\"name/451\",[24,39.674]],[\"comment/451\",[]],[\"name/452\",[286,63.305]],[\"comment/452\",[]],[\"name/453\",[287,63.305]],[\"comment/453\",[]],[\"name/454\",[288,63.305]],[\"comment/454\",[]],[\"name/455\",[272,52.189]],[\"comment/455\",[]],[\"name/456\",[174,50.158]],[\"comment/456\",[]],[\"name/457\",[152,47.02]],[\"comment/457\",[]],[\"name/458\",[175,48.468]],[\"comment/458\",[]],[\"name/459\",[176,50.158]],[\"comment/459\",[]],[\"name/460\",[289,63.305]],[\"comment/460\",[]],[\"name/461\",[290,63.305]],[\"comment/461\",[]],[\"name/462\",[162,37.352]],[\"comment/462\",[]],[\"name/463\",[96,32.825]],[\"comment/463\",[]],[\"name/464\",[151,39.674]],[\"comment/464\",[]],[\"name/465\",[291,63.305]],[\"comment/465\",[]],[\"name/466\",[18,28.778]],[\"comment/466\",[]],[\"name/467\",[106,58.136]],[\"comment/467\",[]],[\"name/468\",[292,63.305]],[\"comment/468\",[]],[\"name/469\",[293,63.305]],[\"comment/469\",[]],[\"name/470\",[24,39.674]],[\"comment/470\",[]],[\"name/471\",[162,37.352]],[\"comment/471\",[]],[\"name/472\",[294,63.305]],[\"comment/472\",[]],[\"name/473\",[18,28.778]],[\"comment/473\",[]],[\"name/474\",[24,39.674]],[\"comment/474\",[]],[\"name/475\",[295,63.305]],[\"comment/475\",[]],[\"name/476\",[270,54.731]],[\"comment/476\",[]],[\"name/477\",[296,63.305]],[\"comment/477\",[]],[\"name/478\",[297,63.305]],[\"comment/478\",[]],[\"name/479\",[298,63.305]],[\"comment/479\",[]],[\"name/480\",[272,52.189]],[\"comment/480\",[]],[\"name/481\",[299,63.305]],[\"comment/481\",[]],[\"name/482\",[276,54.731]],[\"comment/482\",[]],[\"name/483\",[300,63.305]],[\"comment/483\",[]],[\"name/484\",[174,50.158]],[\"comment/484\",[]],[\"name/485\",[152,47.02]],[\"comment/485\",[]],[\"name/486\",[175,48.468]],[\"comment/486\",[]],[\"name/487\",[176,50.158]],[\"comment/487\",[]],[\"name/488\",[301,63.305]],[\"comment/488\",[]],[\"name/489\",[162,37.352]],[\"comment/489\",[]],[\"name/490\",[96,32.825]],[\"comment/490\",[]],[\"name/491\",[151,39.674]],[\"comment/491\",[]],[\"name/492\",[302,63.305]],[\"comment/492\",[]],[\"name/493\",[18,28.778]],[\"comment/493\",[]],[\"name/494\",[303,58.136]],[\"comment/494\",[]],[\"name/495\",[114,58.136]],[\"comment/495\",[]],[\"name/496\",[304,63.305]],[\"comment/496\",[]],[\"name/497\",[305,63.305]],[\"comment/497\",[]],[\"name/498\",[306,63.305]],[\"comment/498\",[]],[\"name/499\",[307,63.305]],[\"comment/499\",[]],[\"name/500\",[308,63.305]],[\"comment/500\",[]],[\"name/501\",[24,39.674]],[\"comment/501\",[]],[\"name/502\",[309,63.305]],[\"comment/502\",[]],[\"name/503\",[310,63.305]],[\"comment/503\",[]],[\"name/504\",[162,37.352]],[\"comment/504\",[]],[\"name/505\",[311,63.305]],[\"comment/505\",[]],[\"name/506\",[18,28.778]],[\"comment/506\",[]],[\"name/507\",[312,63.305]],[\"comment/507\",[]],[\"name/508\",[162,37.352]],[\"comment/508\",[]],[\"name/509\",[313,58.136]],[\"comment/509\",[]],[\"name/510\",[314,63.305]],[\"comment/510\",[]],[\"name/511\",[315,63.305]],[\"comment/511\",[]],[\"name/512\",[197,45.753]],[\"comment/512\",[]],[\"name/513\",[316,63.305]],[\"comment/513\",[]],[\"name/514\",[96,32.825]],[\"comment/514\",[]],[\"name/515\",[151,39.674]],[\"comment/515\",[]],[\"name/516\",[317,63.305]],[\"comment/516\",[]],[\"name/517\",[18,28.778]],[\"comment/517\",[]],[\"name/518\",[272,52.189]],[\"comment/518\",[]],[\"name/519\",[24,39.674]],[\"comment/519\",[]],[\"name/520\",[270,54.731]],[\"comment/520\",[]],[\"name/521\",[313,58.136]],[\"comment/521\",[]],[\"name/522\",[318,63.305]],[\"comment/522\",[]],[\"name/523\",[276,54.731]],[\"comment/523\",[]],[\"name/524\",[152,47.02]],[\"comment/524\",[]],[\"name/525\",[175,48.468]],[\"comment/525\",[]],[\"name/526\",[176,50.158]],[\"comment/526\",[]],[\"name/527\",[319,63.305]],[\"comment/527\",[]],[\"name/528\",[162,37.352]],[\"comment/528\",[]],[\"name/529\",[174,50.158]],[\"comment/529\",[]],[\"name/530\",[54,34.248]],[\"comment/530\",[]],[\"name/531\",[96,32.825]],[\"comment/531\",[]],[\"name/532\",[151,39.674]],[\"comment/532\",[]],[\"name/533\",[320,63.305]],[\"comment/533\",[]],[\"name/534\",[18,28.778]],[\"comment/534\",[]],[\"name/535\",[321,63.305]],[\"comment/535\",[]],[\"name/536\",[322,63.305]],[\"comment/536\",[]],[\"name/537\",[323,63.305]],[\"comment/537\",[]],[\"name/538\",[54,34.248]],[\"comment/538\",[]],[\"name/539\",[324,50.158]],[\"comment/539\",[]],[\"name/540\",[96,32.825]],[\"comment/540\",[]],[\"name/541\",[325,52.189]],[\"comment/541\",[]],[\"name/542\",[326,52.189]],[\"comment/542\",[]],[\"name/543\",[3,39.042]],[\"comment/543\",[]],[\"name/544\",[327,63.305]],[\"comment/544\",[]],[\"name/545\",[18,28.778]],[\"comment/545\",[]],[\"name/546\",[96,32.825]],[\"comment/546\",[]],[\"name/547\",[3,39.042]],[\"comment/547\",[]],[\"name/548\",[328,52.189]],[\"comment/548\",[]],[\"name/549\",[329,54.731]],[\"comment/549\",[]],[\"name/550\",[330,54.731]],[\"comment/550\",[]],[\"name/551\",[324,50.158]],[\"comment/551\",[]],[\"name/552\",[326,52.189]],[\"comment/552\",[]],[\"name/553\",[325,52.189]],[\"comment/553\",[]],[\"name/554\",[331,54.731]],[\"comment/554\",[]],[\"name/555\",[332,50.158]],[\"comment/555\",[]],[\"name/556\",[333,63.305]],[\"comment/556\",[]],[\"name/557\",[18,28.778]],[\"comment/557\",[]],[\"name/558\",[162,37.352]],[\"comment/558\",[]],[\"name/559\",[334,50.158]],[\"comment/559\",[]],[\"name/560\",[96,32.825]],[\"comment/560\",[]],[\"name/561\",[151,39.674]],[\"comment/561\",[]],[\"name/562\",[335,63.305]],[\"comment/562\",[]],[\"name/563\",[18,28.778]],[\"comment/563\",[]],[\"name/564\",[96,32.825]],[\"comment/564\",[]],[\"name/565\",[167,52.189]],[\"comment/565\",[]],[\"name/566\",[334,50.158]],[\"comment/566\",[]],[\"name/567\",[336,63.305]],[\"comment/567\",[]],[\"name/568\",[18,28.778]],[\"comment/568\",[]],[\"name/569\",[324,50.158]],[\"comment/569\",[]],[\"name/570\",[326,52.189]],[\"comment/570\",[]],[\"name/571\",[325,52.189]],[\"comment/571\",[]],[\"name/572\",[331,54.731]],[\"comment/572\",[]],[\"name/573\",[96,32.825]],[\"comment/573\",[]],[\"name/574\",[3,39.042]],[\"comment/574\",[]],[\"name/575\",[328,52.189]],[\"comment/575\",[]],[\"name/576\",[329,54.731]],[\"comment/576\",[]],[\"name/577\",[330,54.731]],[\"comment/577\",[]],[\"name/578\",[332,50.158]],[\"comment/578\",[]],[\"name/579\",[337,63.305]],[\"comment/579\",[]],[\"name/580\",[18,28.778]],[\"comment/580\",[]],[\"name/581\",[202,54.731]],[\"comment/581\",[]],[\"name/582\",[328,52.189]],[\"comment/582\",[]],[\"name/583\",[338,58.136]],[\"comment/583\",[]],[\"name/584\",[339,58.136]],[\"comment/584\",[]],[\"name/585\",[340,58.136]],[\"comment/585\",[]],[\"name/586\",[324,50.158]],[\"comment/586\",[]],[\"name/587\",[221,54.731]],[\"comment/587\",[]],[\"name/588\",[341,58.136]],[\"comment/588\",[]],[\"name/589\",[332,50.158]],[\"comment/589\",[]],[\"name/590\",[214,54.731]],[\"comment/590\",[]],[\"name/591\",[108,47.02]],[\"comment/591\",[]],[\"name/592\",[203,54.731]],[\"comment/592\",[]],[\"name/593\",[204,54.731]],[\"comment/593\",[]],[\"name/594\",[205,54.731]],[\"comment/594\",[]],[\"name/595\",[206,54.731]],[\"comment/595\",[]],[\"name/596\",[207,54.731]],[\"comment/596\",[]],[\"name/597\",[208,52.189]],[\"comment/597\",[]],[\"name/598\",[209,54.731]],[\"comment/598\",[]],[\"name/599\",[210,54.731]],[\"comment/599\",[]],[\"name/600\",[211,54.731]],[\"comment/600\",[]],[\"name/601\",[96,32.825]],[\"comment/601\",[]],[\"name/602\",[3,39.042]],[\"comment/602\",[]],[\"name/603\",[212,54.731]],[\"comment/603\",[]],[\"name/604\",[213,52.189]],[\"comment/604\",[]],[\"name/605\",[145,52.189]],[\"comment/605\",[]],[\"name/606\",[146,52.189]],[\"comment/606\",[]],[\"name/607\",[215,54.731]],[\"comment/607\",[]],[\"name/608\",[216,54.731]],[\"comment/608\",[]],[\"name/609\",[217,48.468]],[\"comment/609\",[]],[\"name/610\",[218,54.731]],[\"comment/610\",[]],[\"name/611\",[219,54.731]],[\"comment/611\",[]],[\"name/612\",[220,54.731]],[\"comment/612\",[]],[\"name/613\",[197,45.753]],[\"comment/613\",[]],[\"name/614\",[222,50.158]],[\"comment/614\",[]],[\"name/615\",[223,50.158]],[\"comment/615\",[]],[\"name/616\",[224,50.158]],[\"comment/616\",[]],[\"name/617\",[225,50.158]],[\"comment/617\",[]],[\"name/618\",[342,63.305]],[\"comment/618\",[]],[\"name/619\",[343,63.305]],[\"comment/619\",[]],[\"name/620\",[344,63.305]],[\"comment/620\",[]],[\"name/621\",[18,28.778]],[\"comment/621\",[]],[\"name/622\",[334,50.158]],[\"comment/622\",[]],[\"name/623\",[162,37.352]],[\"comment/623\",[]],[\"name/624\",[96,32.825]],[\"comment/624\",[]],[\"name/625\",[151,39.674]],[\"comment/625\",[]],[\"name/626\",[345,63.305]],[\"comment/626\",[]],[\"name/627\",[18,28.778]],[\"comment/627\",[]],[\"name/628\",[208,52.189]],[\"comment/628\",[]],[\"name/629\",[3,39.042]],[\"comment/629\",[]],[\"name/630\",[334,50.158]],[\"comment/630\",[]],[\"name/631\",[162,37.352]],[\"comment/631\",[]],[\"name/632\",[96,32.825]],[\"comment/632\",[]],[\"name/633\",[151,39.674]],[\"comment/633\",[]],[\"name/634\",[346,63.305]],[\"comment/634\",[]],[\"name/635\",[18,28.778]],[\"comment/635\",[]],[\"name/636\",[324,50.158]],[\"comment/636\",[]],[\"name/637\",[325,52.189]],[\"comment/637\",[]],[\"name/638\",[326,52.189]],[\"comment/638\",[]],[\"name/639\",[331,54.731]],[\"comment/639\",[]],[\"name/640\",[96,32.825]],[\"comment/640\",[]],[\"name/641\",[3,39.042]],[\"comment/641\",[]],[\"name/642\",[328,52.189]],[\"comment/642\",[]],[\"name/643\",[329,54.731]],[\"comment/643\",[]],[\"name/644\",[330,54.731]],[\"comment/644\",[]],[\"name/645\",[332,50.158]],[\"comment/645\",[]],[\"name/646\",[347,63.305]],[\"comment/646\",[]],[\"name/647\",[348,63.305]],[\"comment/647\",[]],[\"name/648\",[18,28.778]],[\"comment/648\",[]],[\"name/649\",[202,54.731]],[\"comment/649\",[]],[\"name/650\",[338,58.136]],[\"comment/650\",[]],[\"name/651\",[349,63.305]],[\"comment/651\",[]],[\"name/652\",[339,58.136]],[\"comment/652\",[]],[\"name/653\",[340,58.136]],[\"comment/653\",[]],[\"name/654\",[350,63.305]],[\"comment/654\",[]],[\"name/655\",[221,54.731]],[\"comment/655\",[]],[\"name/656\",[341,58.136]],[\"comment/656\",[]],[\"name/657\",[332,50.158]],[\"comment/657\",[]],[\"name/658\",[214,54.731]],[\"comment/658\",[]],[\"name/659\",[108,47.02]],[\"comment/659\",[]],[\"name/660\",[203,54.731]],[\"comment/660\",[]],[\"name/661\",[204,54.731]],[\"comment/661\",[]],[\"name/662\",[205,54.731]],[\"comment/662\",[]],[\"name/663\",[206,54.731]],[\"comment/663\",[]],[\"name/664\",[207,54.731]],[\"comment/664\",[]],[\"name/665\",[208,52.189]],[\"comment/665\",[]],[\"name/666\",[209,54.731]],[\"comment/666\",[]],[\"name/667\",[210,54.731]],[\"comment/667\",[]],[\"name/668\",[211,54.731]],[\"comment/668\",[]],[\"name/669\",[96,32.825]],[\"comment/669\",[]],[\"name/670\",[3,39.042]],[\"comment/670\",[]],[\"name/671\",[212,54.731]],[\"comment/671\",[]],[\"name/672\",[213,52.189]],[\"comment/672\",[]],[\"name/673\",[145,52.189]],[\"comment/673\",[]],[\"name/674\",[146,52.189]],[\"comment/674\",[]],[\"name/675\",[215,54.731]],[\"comment/675\",[]],[\"name/676\",[216,54.731]],[\"comment/676\",[]],[\"name/677\",[217,48.468]],[\"comment/677\",[]],[\"name/678\",[218,54.731]],[\"comment/678\",[]],[\"name/679\",[219,54.731]],[\"comment/679\",[]],[\"name/680\",[220,54.731]],[\"comment/680\",[]],[\"name/681\",[197,45.753]],[\"comment/681\",[]],[\"name/682\",[222,50.158]],[\"comment/682\",[]],[\"name/683\",[223,50.158]],[\"comment/683\",[]],[\"name/684\",[224,50.158]],[\"comment/684\",[]],[\"name/685\",[225,50.158]],[\"comment/685\",[]],[\"name/686\",[351,63.305]],[\"comment/686\",[]],[\"name/687\",[352,63.305]],[\"comment/687\",[]],[\"name/688\",[18,28.778]],[\"comment/688\",[]],[\"name/689\",[334,50.158]],[\"comment/689\",[]],[\"name/690\",[162,37.352]],[\"comment/690\",[]],[\"name/691\",[96,32.825]],[\"comment/691\",[]],[\"name/692\",[151,39.674]],[\"comment/692\",[]],[\"name/693\",[353,63.305]],[\"comment/693\",[]],[\"name/694\",[354,63.305]],[\"comment/694\",[]],[\"name/695\",[355,63.305]],[\"comment/695\",[]],[\"name/696\",[356,63.305]],[\"comment/696\",[]],[\"name/697\",[54,34.248]],[\"comment/697\",[]],[\"name/698\",[303,58.136]],[\"comment/698\",[]],[\"name/699\",[357,63.305]],[\"comment/699\",[]],[\"name/700\",[358,58.136]],[\"comment/700\",[]],[\"name/701\",[359,63.305]],[\"comment/701\",[]],[\"name/702\",[360,63.305]],[\"comment/702\",[]],[\"name/703\",[361,63.305]],[\"comment/703\",[]],[\"name/704\",[3,39.042]],[\"comment/704\",[]],[\"name/705\",[362,63.305]],[\"comment/705\",[]],[\"name/706\",[54,34.248]],[\"comment/706\",[]],[\"name/707\",[358,58.136]],[\"comment/707\",[]],[\"name/708\",[71,58.136]],[\"comment/708\",[]],[\"name/709\",[363,63.305]],[\"comment/709\",[]],[\"name/710\",[364,63.305]],[\"comment/710\",[]],[\"name/711\",[365,63.305]],[\"comment/711\",[]],[\"name/712\",[366,63.305]],[\"comment/712\",[]],[\"name/713\",[367,63.305]],[\"comment/713\",[]],[\"name/714\",[368,63.305]],[\"comment/714\",[]],[\"name/715\",[369,63.305]],[\"comment/715\",[]],[\"name/716\",[370,63.305]],[\"comment/716\",[]],[\"name/717\",[371,63.305]],[\"comment/717\",[]],[\"name/718\",[372,63.305]],[\"comment/718\",[]],[\"name/719\",[373,63.305]],[\"comment/719\",[]],[\"name/720\",[374,63.305]],[\"comment/720\",[]],[\"name/721\",[375,63.305]],[\"comment/721\",[]],[\"name/722\",[33,47.02]],[\"comment/722\",[]],[\"name/723\",[376,63.305]],[\"comment/723\",[]],[\"name/724\",[54,34.248]],[\"comment/724\",[]],[\"name/725\",[83,41.464,377,45.15]],[\"comment/725\",[]],[\"name/726\",[378,58.136]],[\"comment/726\",[]],[\"name/727\",[33,47.02]],[\"comment/727\",[]],[\"name/728\",[379,63.305]],[\"comment/728\",[]],[\"name/729\",[54,34.248]],[\"comment/729\",[]],[\"name/730\",[378,58.136]],[\"comment/730\",[]],[\"name/731\",[380,58.136]],[\"comment/731\",[]],[\"name/732\",[381,63.305]],[\"comment/732\",[]],[\"name/733\",[382,63.305]],[\"comment/733\",[]],[\"name/734\",[383,63.305]],[\"comment/734\",[]],[\"name/735\",[54,34.248]],[\"comment/735\",[]],[\"name/736\",[380,58.136]],[\"comment/736\",[]],[\"name/737\",[384,63.305]],[\"comment/737\",[]],[\"name/738\",[54,34.248]],[\"comment/738\",[]],[\"name/739\",[385,63.305]],[\"comment/739\",[]],[\"name/740\",[386,63.305]],[\"comment/740\",[]],[\"name/741\",[387,63.305]],[\"comment/741\",[]],[\"name/742\",[388,63.305]],[\"comment/742\",[]],[\"name/743\",[389,63.305]],[\"comment/743\",[]],[\"name/744\",[390,63.305]],[\"comment/744\",[]],[\"name/745\",[391,63.305]],[\"comment/745\",[]],[\"name/746\",[392,63.305]],[\"comment/746\",[]],[\"name/747\",[393,63.305]],[\"comment/747\",[]],[\"name/748\",[394,63.305]],[\"comment/748\",[]],[\"name/749\",[395,63.305]],[\"comment/749\",[]],[\"name/750\",[396,52.189]],[\"comment/750\",[]],[\"name/751\",[397,58.136]],[\"comment/751\",[]],[\"name/752\",[396,52.189]],[\"comment/752\",[]],[\"name/753\",[54,34.248]],[\"comment/753\",[]],[\"name/754\",[396,52.189]],[\"comment/754\",[]],[\"name/755\",[397,58.136]],[\"comment/755\",[]],[\"name/756\",[54,34.248]],[\"comment/756\",[]],[\"name/757\",[34,37.222,396,37.222]],[\"comment/757\",[]],[\"name/758\",[398,63.305]],[\"comment/758\",[]],[\"name/759\",[54,34.248]],[\"comment/759\",[]],[\"name/760\",[399,63.305]],[\"comment/760\",[]],[\"name/761\",[400,63.305]],[\"comment/761\",[]],[\"name/762\",[401,63.305]],[\"comment/762\",[]],[\"name/763\",[402,63.305]],[\"comment/763\",[]],[\"name/764\",[403,63.305]],[\"comment/764\",[]],[\"name/765\",[404,63.305]],[\"comment/765\",[]],[\"name/766\",[18,28.778]],[\"comment/766\",[]],[\"name/767\",[405,63.305]],[\"comment/767\",[]],[\"name/768\",[406,63.305]],[\"comment/768\",[]],[\"name/769\",[407,63.305]],[\"comment/769\",[]],[\"name/770\",[408,63.305]],[\"comment/770\",[]],[\"name/771\",[409,63.305]],[\"comment/771\",[]],[\"name/772\",[410,63.305]],[\"comment/772\",[]],[\"name/773\",[411,58.136]],[\"comment/773\",[]],[\"name/774\",[18,28.778]],[\"comment/774\",[]],[\"name/775\",[96,32.825]],[\"comment/775\",[]],[\"name/776\",[412,63.305]],[\"comment/776\",[]],[\"name/777\",[413,63.305]],[\"comment/777\",[]],[\"name/778\",[414,63.305]],[\"comment/778\",[]],[\"name/779\",[415,63.305]],[\"comment/779\",[]],[\"name/780\",[411,58.136]],[\"comment/780\",[]]],\"invertedIndex\":[[\"__type\",{\"_index\":54,\"name\":{\"52\":{},\"59\":{},\"61\":{},\"64\":{},\"69\":{},\"73\":{},\"82\":{},\"139\":{},\"196\":{},\"261\":{},\"318\":{},\"320\":{},\"322\":{},\"324\":{},\"326\":{},\"530\":{},\"538\":{},\"697\":{},\"706\":{},\"724\":{},\"729\":{},\"735\":{},\"738\":{},\"753\":{},\"756\":{},\"759\":{}},\"comment\":{}}],[\"_actionmap\",{\"_index\":211,\"name\":{\"296\":{},\"600\":{},\"668\":{}},\"comment\":{}}],[\"_aftcfg\",{\"_index\":108,\"name\":{\"123\":{},\"148\":{},\"206\":{},\"286\":{},\"351\":{},\"591\":{},\"659\":{}},\"comment\":{}}],[\"_aftlogger\",{\"_index\":164,\"name\":{\"207\":{},\"217\":{},\"245\":{},\"280\":{}},\"comment\":{}}],[\"_api\",{\"_index\":313,\"name\":{\"509\":{},\"521\":{}},\"comment\":{}}],[\"_appendtofile\",{\"_index\":289,\"name\":{\"460\":{}},\"comment\":{}}],[\"_assertion\",{\"_index\":202,\"name\":{\"287\":{},\"581\":{},\"649\":{}},\"comment\":{}}],[\"_async2sync\",{\"_index\":245,\"name\":{\"342\":{}},\"comment\":{}}],[\"_asyncspecdone\",{\"_index\":250,\"name\":{\"347\":{}},\"comment\":{}}],[\"_backofftype\",{\"_index\":122,\"name\":{\"152\":{}},\"comment\":{}}],[\"_browser\",{\"_index\":349,\"name\":{\"651\":{}},\"comment\":{}}],[\"_buildinfo\",{\"_index\":271,\"name\":{\"420\":{}},\"comment\":{}}],[\"_buildinfomgr\",{\"_index\":210,\"name\":{\"295\":{},\"599\":{},\"667\":{}},\"comment\":{}}],[\"_buildmgr\",{\"_index\":257,\"name\":{\"360\":{},\"389\":{}},\"comment\":{}}],[\"_cacheduration\",{\"_index\":41,\"name\":{\"37\":{}},\"comment\":{}}],[\"_cfg\",{\"_index\":19,\"name\":{\"13\":{}},\"comment\":{}}],[\"_checkandsendlogs\",{\"_index\":278,\"name\":{\"436\":{}},\"comment\":{}}],[\"_client\",{\"_index\":273,\"name\":{\"422\":{}},\"comment\":{}}],[\"_condition\",{\"_index\":120,\"name\":{\"150\":{}},\"comment\":{}}],[\"_createkinesislogrecord\",{\"_index\":277,\"name\":{\"435\":{}},\"comment\":{}}],[\"_currentdelay\",{\"_index\":126,\"name\":{\"156\":{}},\"comment\":{}}],[\"_dateformat\",{\"_index\":288,\"name\":{\"454\":{}},\"comment\":{}}],[\"_delay\",{\"_index\":121,\"name\":{\"151\":{}},\"comment\":{}}],[\"_description\",{\"_index\":204,\"name\":{\"289\":{},\"593\":{},\"661\":{}},\"comment\":{}}],[\"_driver\",{\"_index\":328,\"name\":{\"548\":{},\"575\":{},\"582\":{},\"642\":{}},\"comment\":{}}],[\"_enabled\",{\"_index\":312,\"name\":{\"507\":{}},\"comment\":{}}],[\"_err\",{\"_index\":132,\"name\":{\"162\":{}},\"comment\":{}}],[\"_failaction\",{\"_index\":131,\"name\":{\"161\":{}},\"comment\":{}}],[\"_filename\",{\"_index\":296,\"name\":{\"477\":{}},\"comment\":{}}],[\"_findtestsbyfield\",{\"_index\":316,\"name\":{\"513\":{}},\"comment\":{}}],[\"_format\",{\"_index\":290,\"name\":{\"461\":{}},\"comment\":{}}],[\"_generatetestresult\",{\"_index\":225,\"name\":{\"315\":{},\"373\":{},\"400\":{},\"617\":{},\"685\":{}},\"comment\":{}}],[\"_generatetestresults\",{\"_index\":224,\"name\":{\"314\":{},\"372\":{},\"399\":{},\"616\":{},\"684\":{}},\"comment\":{}}],[\"_getenabledplugins\",{\"_index\":199,\"name\":{\"282\":{}},\"comment\":{}}],[\"_getinnerpromise\",{\"_index\":146,\"name\":{\"177\":{},\"302\":{},\"606\":{},\"674\":{}},\"comment\":{}}],[\"_gettestrailresultfortestresult\",{\"_index\":319,\"name\":{\"527\":{}},\"comment\":{}}],[\"_getverifier\",{\"_index\":260,\"name\":{\"368\":{},\"396\":{}},\"comment\":{}}],[\"_includeresults\",{\"_index\":287,\"name\":{\"453\":{}},\"comment\":{}}],[\"_innerpromise\",{\"_index\":206,\"name\":{\"291\":{},\"595\":{},\"663\":{}},\"comment\":{}}],[\"_internalmap\",{\"_index\":40,\"name\":{\"36\":{}},\"comment\":{}}],[\"_isconditionmet\",{\"_index\":144,\"name\":{\"175\":{}},\"comment\":{}}],[\"_iserror\",{\"_index\":86,\"name\":{\"96\":{}},\"comment\":{}}],[\"_isstillvalid\",{\"_index\":50,\"name\":{\"48\":{}},\"comment\":{}}],[\"_level\",{\"_index\":272,\"name\":{\"421\":{},\"455\":{},\"480\":{},\"518\":{}},\"comment\":{}}],[\"_locator\",{\"_index\":330,\"name\":{\"550\":{},\"577\":{},\"644\":{}},\"comment\":{}}],[\"_lockfiledescriptor\",{\"_index\":100,\"name\":{\"112\":{}},\"comment\":{}}],[\"_logmessage\",{\"_index\":223,\"name\":{\"313\":{},\"371\":{},\"398\":{},\"615\":{},\"683\":{}},\"comment\":{}}],[\"_logresult\",{\"_index\":222,\"name\":{\"312\":{},\"370\":{},\"397\":{},\"614\":{},\"682\":{}},\"comment\":{}}],[\"_logs\",{\"_index\":270,\"name\":{\"419\":{},\"476\":{},\"520\":{}},\"comment\":{}}],[\"_matcher\",{\"_index\":203,\"name\":{\"288\":{},\"592\":{},\"660\":{}},\"comment\":{}}],[\"_maxattempts\",{\"_index\":123,\"name\":{\"153\":{}},\"comment\":{}}],[\"_maxduration\",{\"_index\":124,\"name\":{\"154\":{}},\"comment\":{}}],[\"_maxlogchars\",{\"_index\":318,\"name\":{\"522\":{}},\"comment\":{}}],[\"_maxloglines\",{\"_index\":298,\"name\":{\"479\":{}},\"comment\":{}}],[\"_memorymap\",{\"_index\":107,\"name\":{\"122\":{}},\"comment\":{}}],[\"_outputdir\",{\"_index\":297,\"name\":{\"478\":{}},\"comment\":{}}],[\"_outputpath\",{\"_index\":286,\"name\":{\"452\":{}},\"comment\":{}}],[\"_parent\",{\"_index\":329,\"name\":{\"549\":{},\"576\":{},\"643\":{}},\"comment\":{}}],[\"_policyengmgr\",{\"_index\":209,\"name\":{\"294\":{},\"598\":{},\"666\":{}},\"comment\":{}}],[\"_processmessage\",{\"_index\":87,\"name\":{\"97\":{}},\"comment\":{}}],[\"_processstack\",{\"_index\":88,\"name\":{\"98\":{}},\"comment\":{}}],[\"_regeneratehtmlfile\",{\"_index\":301,\"name\":{\"488\":{}},\"comment\":{}}],[\"_reject\",{\"_index\":125,\"name\":{\"155\":{}},\"comment\":{}}],[\"_removeinternalstacklines\",{\"_index\":89,\"name\":{\"99\":{}},\"comment\":{}}],[\"_removenewlinesandextrawhitespace\",{\"_index\":90,\"name\":{\"100\":{}},\"comment\":{}}],[\"_rep\",{\"_index\":252,\"name\":{\"350\":{},\"380\":{}},\"comment\":{}}],[\"_reporter\",{\"_index\":208,\"name\":{\"293\":{},\"597\":{},\"628\":{},\"665\":{}},\"comment\":{}}],[\"_request\",{\"_index\":414,\"name\":{\"778\":{}},\"comment\":{}}],[\"_resolveassertion\",{\"_index\":214,\"name\":{\"303\":{},\"590\":{},\"658\":{}},\"comment\":{}}],[\"_response\",{\"_index\":415,\"name\":{\"779\":{}},\"comment\":{}}],[\"_result\",{\"_index\":127,\"name\":{\"157\":{}},\"comment\":{}}],[\"_results\",{\"_index\":295,\"name\":{\"475\":{}},\"comment\":{}}],[\"_retryable\",{\"_index\":119,\"name\":{\"149\":{}},\"comment\":{}}],[\"_safestropt\",{\"_index\":168,\"name\":{\"216\":{}},\"comment\":{}}],[\"_sectioncache\",{\"_index\":21,\"name\":{\"15\":{}},\"comment\":{}}],[\"_send\",{\"_index\":280,\"name\":{\"438\":{}},\"comment\":{}}],[\"_sendbatch\",{\"_index\":279,\"name\":{\"437\":{}},\"comment\":{}}],[\"_sessionmgr\",{\"_index\":338,\"name\":{\"583\":{},\"650\":{}},\"comment\":{}}],[\"_sessionoptions\",{\"_index\":339,\"name\":{\"584\":{},\"652\":{}},\"comment\":{}}],[\"_starttime\",{\"_index\":205,\"name\":{\"290\":{},\"594\":{},\"662\":{}},\"comment\":{}}],[\"_stepcount\",{\"_index\":177,\"name\":{\"246\":{}},\"comment\":{}}],[\"_success\",{\"_index\":128,\"name\":{\"158\":{}},\"comment\":{}}],[\"_testcases\",{\"_index\":256,\"name\":{\"359\":{},\"388\":{}},\"comment\":{}}],[\"_testids\",{\"_index\":207,\"name\":{\"292\":{},\"596\":{},\"664\":{}},\"comment\":{}}],[\"_testnames\",{\"_index\":246,\"name\":{\"343\":{},\"352\":{}},\"comment\":{}}],[\"_timeout\",{\"_index\":101,\"name\":{\"113\":{}},\"comment\":{}}],[\"_totalattempts\",{\"_index\":129,\"name\":{\"159\":{}},\"comment\":{}}],[\"_totalduration\",{\"_index\":130,\"name\":{\"160\":{}},\"comment\":{}}],[\"_updatememorymap\",{\"_index\":110,\"name\":{\"135\":{}},\"comment\":{}}],[\"_valuecache\",{\"_index\":20,\"name\":{\"14\":{}},\"comment\":{}}],[\"_verbosity\",{\"_index\":81,\"name\":{\"89\":{}},\"comment\":{}}],[\"_waitforlock\",{\"_index\":103,\"name\":{\"115\":{}},\"comment\":{}}],[\"_writetofile\",{\"_index\":109,\"name\":{\"134\":{}},\"comment\":{}}],[\"acc\",{\"_index\":379,\"name\":{\"728\":{}},\"comment\":{}}],[\"accept\",{\"_index\":378,\"name\":{\"726\":{},\"730\":{}},\"comment\":{}}],[\"accesskey\",{\"_index\":304,\"name\":{\"496\":{}},\"comment\":{}}],[\"action\",{\"_index\":59,\"name\":{\"58\":{}},\"comment\":{}}],[\"addlisteners\",{\"_index\":263,\"name\":{\"408\":{}},\"comment\":{}}],[\"aft\",{\"_index\":0,\"name\":{\"0\":{},\"1\":{},\"2\":{},\"3\":{},\"4\":{},\"5\":{},\"6\":{},\"7\":{},\"8\":{},\"9\":{},\"10\":{}},\"comment\":{}}],[\"aftcfg\",{\"_index\":96,\"name\":{\"108\":{},\"185\":{},\"208\":{},\"214\":{},\"225\":{},\"240\":{},\"273\":{},\"278\":{},\"297\":{},\"355\":{},\"376\":{},\"382\":{},\"402\":{},\"440\":{},\"463\":{},\"490\":{},\"514\":{},\"531\":{},\"540\":{},\"546\":{},\"560\":{},\"564\":{},\"573\":{},\"601\":{},\"624\":{},\"632\":{},\"640\":{},\"669\":{},\"691\":{},\"775\":{}},\"comment\":{}}],[\"aftconfig\",{\"_index\":17,\"name\":{\"11\":{},\"33\":{}},\"comment\":{}}],[\"aftjasminereporter\",{\"_index\":244,\"name\":{\"340\":{}},\"comment\":{}}],[\"aftlog\",{\"_index\":251,\"name\":{\"348\":{},\"378\":{}},\"comment\":{}}],[\"aftlogger\",{\"_index\":151,\"name\":{\"183\":{},\"190\":{},\"209\":{},\"226\":{},\"241\":{},\"274\":{},\"441\":{},\"464\":{},\"491\":{},\"515\":{},\"532\":{},\"561\":{},\"625\":{},\"633\":{},\"692\":{}},\"comment\":{}}],[\"aftmochareporter\",{\"_index\":262,\"name\":{\"406\":{}},\"comment\":{}}],[\"afttest\",{\"_index\":255,\"name\":{\"357\":{},\"386\":{}},\"comment\":{}}],[\"algorithm\",{\"_index\":388,\"name\":{\"742\":{}},\"comment\":{}}],[\"allowautoredirect\",{\"_index\":357,\"name\":{\"699\":{}},\"comment\":{}}],[\"and\",{\"_index\":215,\"name\":{\"304\":{},\"607\":{},\"675\":{}},\"comment\":{}}],[\"applicationjson\",{\"_index\":374,\"name\":{\"720\":{}},\"comment\":{}}],[\"applicationoctetstream\",{\"_index\":367,\"name\":{\"713\":{}},\"comment\":{}}],[\"args\",{\"_index\":160,\"name\":{\"200\":{}},\"comment\":{}}],[\"auth\",{\"_index\":383,\"name\":{\"734\":{}},\"comment\":{}}],[\"authorization\",{\"_index\":380,\"name\":{\"731\":{},\"736\":{}},\"comment\":{}}],[\"aws\",{\"_index\":6,\"name\":{\"3\":{}},\"comment\":{}}],[\"basic\",{\"_index\":381,\"name\":{\"732\":{}},\"comment\":{}}],[\"batch\",{\"_index\":267,\"name\":{\"413\":{},\"427\":{}},\"comment\":{}}],[\"batchsize\",{\"_index\":268,\"name\":{\"414\":{},\"428\":{}},\"comment\":{}}],[\"between\",{\"_index\":238,\"name\":{\"334\":{}},\"comment\":{}}],[\"browser\",{\"_index\":350,\"name\":{\"654\":{}},\"comment\":{}}],[\"buildinfomanager\",{\"_index\":166,\"name\":{\"212\":{}},\"comment\":{}}],[\"buildinfomgr\",{\"_index\":213,\"name\":{\"300\":{},\"361\":{},\"604\":{},\"672\":{}},\"comment\":{}}],[\"buildinfoplugin\",{\"_index\":171,\"name\":{\"221\":{}},\"comment\":{}}],[\"buildname\",{\"_index\":169,\"name\":{\"219\":{},\"223\":{}},\"comment\":{}}],[\"buildnumber\",{\"_index\":170,\"name\":{\"220\":{},\"224\":{}},\"comment\":{}}],[\"cacheduration\",{\"_index\":308,\"name\":{\"500\":{}},\"comment\":{}}],[\"cachemap\",{\"_index\":39,\"name\":{\"34\":{}},\"comment\":{}}],[\"cacheobject\",{\"_index\":69,\"name\":{\"72\":{}},\"comment\":{}}],[\"calculatebackoffdelay\",{\"_index\":118,\"name\":{\"146\":{}},\"comment\":{}}],[\"class\",{\"_index\":60,\"name\":{\"60\":{}},\"comment\":{}}],[\"clear\",{\"_index\":42,\"name\":{\"38\":{},\"124\":{}},\"comment\":{}}],[\"client\",{\"_index\":274,\"name\":{\"424\":{}},\"comment\":{}}],[\"cnonce\",{\"_index\":391,\"name\":{\"745\":{}},\"comment\":{}}],[\"compare\",{\"_index\":234,\"name\":{\"330\":{}},\"comment\":{}}],[\"constructor\",{\"_index\":18,\"name\":{\"12\":{},\"35\":{},\"87\":{},\"107\":{},\"120\":{},\"147\":{},\"184\":{},\"202\":{},\"205\":{},\"213\":{},\"222\":{},\"229\":{},\"233\":{},\"243\":{},\"271\":{},\"277\":{},\"285\":{},\"341\":{},\"349\":{},\"358\":{},\"379\":{},\"387\":{},\"407\":{},\"410\":{},\"418\":{},\"443\":{},\"450\":{},\"466\":{},\"473\":{},\"493\":{},\"506\":{},\"517\":{},\"534\":{},\"545\":{},\"557\":{},\"563\":{},\"568\":{},\"580\":{},\"621\":{},\"627\":{},\"635\":{},\"648\":{},\"688\":{},\"766\":{},\"774\":{}},\"comment\":{}}],[\"containing\",{\"_index\":239,\"name\":{\"335\":{}},\"comment\":{}}],[\"content\",{\"_index\":377,\"name\":{\"725\":{}},\"comment\":{}}],[\"contenttype\",{\"_index\":375,\"name\":{\"721\":{}},\"comment\":{}}],[\"convert\",{\"_index\":58,\"name\":{\"57\":{}},\"comment\":{}}],[\"cookie\",{\"_index\":396,\"name\":{\"750\":{},\"752\":{},\"754\":{},\"757\":{}},\"comment\":{}}],[\"cookies\",{\"_index\":395,\"name\":{\"749\":{}},\"comment\":{}}],[\"core\",{\"_index\":1,\"name\":{\"0\":{}},\"comment\":{}}],[\"created\",{\"_index\":193,\"name\":{\"267\":{}},\"comment\":{}}],[\"credentials\",{\"_index\":275,\"name\":{\"429\":{}},\"comment\":{}}],[\"ct\",{\"_index\":376,\"name\":{\"723\":{}},\"comment\":{}}],[\"data\",{\"_index\":71,\"name\":{\"75\":{},\"708\":{}},\"comment\":{}}],[\"dateformat\",{\"_index\":284,\"name\":{\"447\":{}},\"comment\":{}}],[\"debug\",{\"_index\":180,\"name\":{\"250\":{}},\"comment\":{}}],[\"defaultallowredirect\",{\"_index\":408,\"name\":{\"770\":{}},\"comment\":{}}],[\"defaultheaders\",{\"_index\":406,\"name\":{\"768\":{}},\"comment\":{}}],[\"defaultmethod\",{\"_index\":407,\"name\":{\"769\":{}},\"comment\":{}}],[\"defaultmultipart\",{\"_index\":410,\"name\":{\"772\":{}},\"comment\":{}}],[\"defaultpostdata\",{\"_index\":409,\"name\":{\"771\":{}},\"comment\":{}}],[\"defaults\",{\"_index\":57,\"name\":{\"56\":{}},\"comment\":{}}],[\"defaulturl\",{\"_index\":405,\"name\":{\"767\":{}},\"comment\":{}}],[\"delete\",{\"_index\":43,\"name\":{\"39\":{},\"125\":{}},\"comment\":{}}],[\"deliverystream\",{\"_index\":266,\"name\":{\"412\":{},\"426\":{}},\"comment\":{}}],[\"digest\",{\"_index\":382,\"name\":{\"733\":{}},\"comment\":{}}],[\"digestoptions\",{\"_index\":384,\"name\":{\"737\":{}},\"comment\":{}}],[\"disposable\",{\"_index\":148,\"name\":{\"180\":{}},\"comment\":{}}],[\"dispose\",{\"_index\":149,\"name\":{\"181\":{},\"259\":{},\"369\":{},\"385\":{},\"405\":{}},\"comment\":{}}],[\"driver\",{\"_index\":324,\"name\":{\"539\":{},\"551\":{},\"569\":{},\"586\":{},\"636\":{}},\"comment\":{}}],[\"ellide\",{\"_index\":74,\"name\":{\"79\":{}},\"comment\":{}}],[\"ellipsislocation\",{\"_index\":73,\"name\":{\"78\":{}},\"comment\":{}}],[\"enabled\",{\"_index\":162,\"name\":{\"203\":{},\"210\":{},\"227\":{},\"231\":{},\"234\":{},\"275\":{},\"416\":{},\"439\":{},\"448\":{},\"462\":{},\"471\":{},\"489\":{},\"504\":{},\"508\":{},\"528\":{},\"558\":{},\"623\":{},\"631\":{},\"690\":{}},\"comment\":{}}],[\"entries\",{\"_index\":47,\"name\":{\"45\":{},\"131\":{}},\"comment\":{}}],[\"equaling\",{\"_index\":236,\"name\":{\"332\":{}},\"comment\":{}}],[\"err\",{\"_index\":80,\"name\":{\"86\":{},\"88\":{},\"101\":{}},\"comment\":{}}],[\"errlevel\",{\"_index\":78,\"name\":{\"84\":{}},\"comment\":{}}],[\"erroptions\",{\"_index\":76,\"name\":{\"81\":{}},\"comment\":{}}],[\"error\",{\"_index\":186,\"name\":{\"256\":{}},\"comment\":{}}],[\"errverbosity\",{\"_index\":75,\"name\":{\"80\":{}},\"comment\":{}}],[\"exactly\",{\"_index\":237,\"name\":{\"333\":{}},\"comment\":{}}],[\"exclude\",{\"_index\":55,\"name\":{\"53\":{}},\"comment\":{}}],[\"expected\",{\"_index\":232,\"name\":{\"328\":{}},\"comment\":{}}],[\"expires\",{\"_index\":401,\"name\":{\"762\":{}},\"comment\":{}}],[\"expiringfilelock\",{\"_index\":95,\"name\":{\"106\":{},\"116\":{}},\"comment\":{}}],[\"fail\",{\"_index\":185,\"name\":{\"255\":{},\"364\":{},\"392\":{}},\"comment\":{}}],[\"failurestring\",{\"_index\":235,\"name\":{\"331\":{}},\"comment\":{}}],[\"fileio\",{\"_index\":104,\"name\":{\"118\":{}},\"comment\":{}}],[\"filelockmaxhold\",{\"_index\":26,\"name\":{\"20\":{}},\"comment\":{}}],[\"filelockmaxwait\",{\"_index\":25,\"name\":{\"19\":{}},\"comment\":{}}],[\"filename\",{\"_index\":106,\"name\":{\"121\":{},\"467\":{}},\"comment\":{}}],[\"filesystem\",{\"_index\":9,\"name\":{\"4\":{}},\"comment\":{}}],[\"filesystemmap\",{\"_index\":105,\"name\":{\"119\":{}},\"comment\":{}}],[\"filesystemreportingplugin\",{\"_index\":285,\"name\":{\"449\":{}},\"comment\":{}}],[\"filesystemreportingpluginconfig\",{\"_index\":281,\"name\":{\"442\":{}},\"comment\":{}}],[\"finalise\",{\"_index\":176,\"name\":{\"239\":{},\"434\":{},\"459\":{},\"487\":{},\"526\":{}},\"comment\":{}}],[\"findtestcases\",{\"_index\":315,\"name\":{\"511\":{}},\"comment\":{}}],[\"firehose\",{\"_index\":8,\"name\":{\"3\":{}},\"comment\":{}}],[\"foreach\",{\"_index\":44,\"name\":{\"40\":{},\"126\":{}},\"comment\":{}}],[\"format\",{\"_index\":153,\"name\":{\"188\":{}},\"comment\":{}}],[\"fsmapdirectory\",{\"_index\":27,\"name\":{\"21\":{}},\"comment\":{}}],[\"full\",{\"_index\":92,\"name\":{\"103\":{}},\"comment\":{}}],[\"fullname\",{\"_index\":254,\"name\":{\"354\":{},\"375\":{}},\"comment\":{}}],[\"fullpathandfile\",{\"_index\":299,\"name\":{\"481\":{}},\"comment\":{}}],[\"fulltitle\",{\"_index\":261,\"name\":{\"383\":{},\"403\":{}},\"comment\":{}}],[\"func\",{\"_index\":62,\"name\":{\"63\":{}},\"comment\":{}}],[\"generatorname\",{\"_index\":321,\"name\":{\"535\":{}},\"comment\":{}}],[\"get\",{\"_index\":33,\"name\":{\"27\":{},\"41\":{},\"117\":{},\"127\":{},\"218\":{},\"722\":{},\"727\":{}},\"comment\":{}}],[\"getcomponent\",{\"_index\":332,\"name\":{\"555\":{},\"578\":{},\"589\":{},\"645\":{},\"657\":{}},\"comment\":{}}],[\"getroot\",{\"_index\":331,\"name\":{\"554\":{},\"572\":{},\"639\":{}},\"comment\":{}}],[\"getsection\",{\"_index\":35,\"name\":{\"29\":{}},\"comment\":{}}],[\"getsession\",{\"_index\":334,\"name\":{\"559\":{},\"566\":{},\"622\":{},\"630\":{},\"689\":{}},\"comment\":{}}],[\"gettestcase\",{\"_index\":314,\"name\":{\"510\":{}},\"comment\":{}}],[\"greaterthan\",{\"_index\":241,\"name\":{\"337\":{}},\"comment\":{}}],[\"gridsessiongeneratorplugin\",{\"_index\":345,\"name\":{\"626\":{}},\"comment\":{}}],[\"handle\",{\"_index\":93,\"name\":{\"104\":{}},\"comment\":{}}],[\"handleasync\",{\"_index\":94,\"name\":{\"105\":{}},\"comment\":{}}],[\"has\",{\"_index\":45,\"name\":{\"42\":{},\"128\":{}},\"comment\":{}}],[\"havingvalue\",{\"_index\":240,\"name\":{\"336\":{}},\"comment\":{}}],[\"headers\",{\"_index\":358,\"name\":{\"700\":{},\"707\":{}},\"comment\":{}}],[\"hostname\",{\"_index\":113,\"name\":{\"141\":{}},\"comment\":{}}],[\"html\",{\"_index\":10,\"name\":{\"5\":{}},\"comment\":{}}],[\"htmlreportingplugin\",{\"_index\":294,\"name\":{\"472\":{}},\"comment\":{}}],[\"htmlreportingpluginconfig\",{\"_index\":291,\"name\":{\"465\":{}},\"comment\":{}}],[\"httpdata\",{\"_index\":364,\"name\":{\"710\":{}},\"comment\":{}}],[\"httpheaders\",{\"_index\":365,\"name\":{\"711\":{}},\"comment\":{}}],[\"httpmethod\",{\"_index\":355,\"name\":{\"695\":{}},\"comment\":{}}],[\"httponly\",{\"_index\":403,\"name\":{\"764\":{}},\"comment\":{}}],[\"httprequest\",{\"_index\":356,\"name\":{\"696\":{}},\"comment\":{}}],[\"httpresponse\",{\"_index\":362,\"name\":{\"705\":{}},\"comment\":{}}],[\"httpservice\",{\"_index\":411,\"name\":{\"773\":{},\"780\":{}},\"comment\":{}}],[\"httpserviceconfig\",{\"_index\":404,\"name\":{\"765\":{}},\"comment\":{}}],[\"includeresults\",{\"_index\":283,\"name\":{\"446\":{}},\"comment\":{}}],[\"info\",{\"_index\":181,\"name\":{\"251\":{}},\"comment\":{}}],[\"initialise\",{\"_index\":174,\"name\":{\"236\":{},\"431\":{},\"456\":{},\"484\":{},\"529\":{}},\"comment\":{}}],[\"internals\",{\"_index\":221,\"name\":{\"310\":{},\"587\":{},\"655\":{}},\"comment\":{}}],[\"ip\",{\"_index\":112,\"name\":{\"140\":{}},\"comment\":{}}],[\"issuccessful\",{\"_index\":136,\"name\":{\"167\":{}},\"comment\":{}}],[\"istype\",{\"_index\":155,\"name\":{\"193\":{}},\"comment\":{}}],[\"iterator\",{\"_index\":51,\"name\":{\"49\":{},\"136\":{}},\"comment\":{}}],[\"jasmine\",{\"_index\":2,\"name\":{\"1\":{}},\"comment\":{}}],[\"jasminestarted\",{\"_index\":247,\"name\":{\"344\":{}},\"comment\":{}}],[\"jsonkey\",{\"_index\":63,\"name\":{\"65\":{}},\"comment\":{}}],[\"jsonobject\",{\"_index\":65,\"name\":{\"67\":{}},\"comment\":{}}],[\"jsonvalue\",{\"_index\":64,\"name\":{\"66\":{}},\"comment\":{}}],[\"key\",{\"_index\":399,\"name\":{\"760\":{}},\"comment\":{}}],[\"keys\",{\"_index\":48,\"name\":{\"46\":{},\"132\":{}},\"comment\":{}}],[\"kinesis\",{\"_index\":7,\"name\":{\"3\":{}},\"comment\":{}}],[\"kinesisreportingplugin\",{\"_index\":269,\"name\":{\"417\":{}},\"comment\":{}}],[\"kinesisreportingpluginconfig\",{\"_index\":264,\"name\":{\"409\":{}},\"comment\":{}}],[\"lasterror\",{\"_index\":134,\"name\":{\"165\":{}},\"comment\":{}}],[\"lessthan\",{\"_index\":242,\"name\":{\"338\":{}},\"comment\":{}}],[\"level\",{\"_index\":159,\"name\":{\"198\":{}},\"comment\":{}}],[\"localsessiongeneratorplugin\",{\"_index\":344,\"name\":{\"620\":{}},\"comment\":{}}],[\"locator\",{\"_index\":325,\"name\":{\"541\":{},\"553\":{},\"571\":{},\"637\":{}},\"comment\":{}}],[\"lockduration\",{\"_index\":98,\"name\":{\"110\":{}},\"comment\":{}}],[\"lockname\",{\"_index\":97,\"name\":{\"109\":{}},\"comment\":{}}],[\"log\",{\"_index\":152,\"name\":{\"187\":{},\"237\":{},\"257\":{},\"432\":{},\"457\":{},\"485\":{},\"524\":{}},\"comment\":{}}],[\"logger\",{\"_index\":77,\"name\":{\"83\":{}},\"comment\":{}}],[\"loglevel\",{\"_index\":24,\"name\":{\"18\":{},\"186\":{},\"191\":{},\"192\":{},\"230\":{},\"235\":{},\"248\":{},\"415\":{},\"423\":{},\"444\":{},\"451\":{},\"470\":{},\"474\":{},\"501\":{},\"519\":{}},\"comment\":{}}],[\"logmessagedata\",{\"_index\":157,\"name\":{\"195\":{}},\"comment\":{}}],[\"logs\",{\"_index\":276,\"name\":{\"430\":{},\"482\":{},\"523\":{}},\"comment\":{}}],[\"machineinfo\",{\"_index\":115,\"name\":{\"143\":{}},\"comment\":{}}],[\"machineinfodata\",{\"_index\":111,\"name\":{\"138\":{}},\"comment\":{}}],[\"maxlogcharacters\",{\"_index\":309,\"name\":{\"502\":{}},\"comment\":{}}],[\"maxloglines\",{\"_index\":293,\"name\":{\"469\":{}},\"comment\":{}}],[\"merge\",{\"_index\":72,\"name\":{\"76\":{}},\"comment\":{}}],[\"message\",{\"_index\":68,\"name\":{\"71\":{},\"93\":{},\"199\":{}},\"comment\":{}}],[\"metadata\",{\"_index\":194,\"name\":{\"268\":{}},\"comment\":{}}],[\"method\",{\"_index\":359,\"name\":{\"701\":{}},\"comment\":{}}],[\"mimetype\",{\"_index\":366,\"name\":{\"712\":{}},\"comment\":{}}],[\"mocha\",{\"_index\":4,\"name\":{\"2\":{}},\"comment\":{}}],[\"multipart\",{\"_index\":361,\"name\":{\"703\":{}},\"comment\":{}}],[\"multipartformdata\",{\"_index\":373,\"name\":{\"719\":{}},\"comment\":{}}],[\"name\",{\"_index\":158,\"name\":{\"197\":{}},\"comment\":{}}],[\"nc\",{\"_index\":390,\"name\":{\"744\":{}},\"comment\":{}}],[\"nonce\",{\"_index\":389,\"name\":{\"743\":{}},\"comment\":{}}],[\"not\",{\"_index\":243,\"name\":{\"339\":{}},\"comment\":{}}],[\"on\",{\"_index\":216,\"name\":{\"305\":{},\"608\":{},\"676\":{}},\"comment\":{}}],[\"opaque\",{\"_index\":394,\"name\":{\"748\":{}},\"comment\":{}}],[\"options\",{\"_index\":322,\"name\":{\"536\":{}},\"comment\":{}}],[\"outputdir\",{\"_index\":292,\"name\":{\"468\":{}},\"comment\":{}}],[\"outputpath\",{\"_index\":282,\"name\":{\"445\":{}},\"comment\":{}}],[\"parent\",{\"_index\":326,\"name\":{\"542\":{},\"552\":{},\"570\":{},\"638\":{}},\"comment\":{}}],[\"pass\",{\"_index\":184,\"name\":{\"254\":{},\"363\":{},\"391\":{}},\"comment\":{}}],[\"pending\",{\"_index\":259,\"name\":{\"365\":{},\"393\":{}},\"comment\":{}}],[\"performrequest\",{\"_index\":412,\"name\":{\"776\":{}},\"comment\":{}}],[\"planid\",{\"_index\":307,\"name\":{\"499\":{}},\"comment\":{}}],[\"plugin\",{\"_index\":163,\"name\":{\"204\":{}},\"comment\":{}}],[\"pluginconfig\",{\"_index\":161,\"name\":{\"201\":{}},\"comment\":{}}],[\"pluginloader\",{\"_index\":165,\"name\":{\"211\":{}},\"comment\":{}}],[\"pluginnames\",{\"_index\":23,\"name\":{\"17\":{}},\"comment\":{}}],[\"plugins\",{\"_index\":167,\"name\":{\"215\":{},\"244\":{},\"279\":{},\"565\":{}},\"comment\":{}}],[\"pluginssearchdir\",{\"_index\":22,\"name\":{\"16\":{}},\"comment\":{}}],[\"policyengineenabled\",{\"_index\":310,\"name\":{\"503\":{}},\"comment\":{}}],[\"policyengmgr\",{\"_index\":212,\"name\":{\"299\":{},\"603\":{},\"671\":{}},\"comment\":{}}],[\"postdata\",{\"_index\":360,\"name\":{\"702\":{}},\"comment\":{}}],[\"processenvvars\",{\"_index\":38,\"name\":{\"32\":{}},\"comment\":{}}],[\"processingresult\",{\"_index\":66,\"name\":{\"68\":{}},\"comment\":{}}],[\"processproperties\",{\"_index\":37,\"name\":{\"31\":{}},\"comment\":{}}],[\"projectid\",{\"_index\":305,\"name\":{\"497\":{}},\"comment\":{}}],[\"prototype\",{\"_index\":61,\"name\":{\"62\":{}},\"comment\":{}}],[\"qop\",{\"_index\":392,\"name\":{\"746\":{}},\"comment\":{}}],[\"rand\",{\"_index\":116,\"name\":{\"144\":{}},\"comment\":{}}],[\"realm\",{\"_index\":386,\"name\":{\"740\":{}},\"comment\":{}}],[\"region\",{\"_index\":265,\"name\":{\"411\":{},\"425\":{}},\"comment\":{}}],[\"replacewith\",{\"_index\":56,\"name\":{\"54\":{}},\"comment\":{}}],[\"reporter\",{\"_index\":3,\"name\":{\"1\":{},\"2\":{},\"242\":{},\"298\":{},\"356\":{},\"377\":{},\"384\":{},\"404\":{},\"543\":{},\"547\":{},\"574\":{},\"602\":{},\"629\":{},\"641\":{},\"670\":{},\"704\":{}},\"comment\":{}}],[\"reportername\",{\"_index\":178,\"name\":{\"247\":{}},\"comment\":{}}],[\"reporting\",{\"_index\":5,\"name\":{\"3\":{},\"4\":{},\"5\":{}},\"comment\":{}}],[\"reportingplugin\",{\"_index\":173,\"name\":{\"232\":{}},\"comment\":{}}],[\"reportingpluginconfig\",{\"_index\":172,\"name\":{\"228\":{}},\"comment\":{}}],[\"response\",{\"_index\":393,\"name\":{\"747\":{}},\"comment\":{}}],[\"result\",{\"_index\":67,\"name\":{\"70\":{},\"163\":{}},\"comment\":{}}],[\"resultid\",{\"_index\":192,\"name\":{\"266\":{}},\"comment\":{}}],[\"resultmessage\",{\"_index\":190,\"name\":{\"264\":{}},\"comment\":{}}],[\"retry\",{\"_index\":117,\"name\":{\"145\":{},\"178\":{}},\"comment\":{}}],[\"retrybackofftype\",{\"_index\":29,\"name\":{\"23\":{},\"77\":{}},\"comment\":{}}],[\"retrydelayms\",{\"_index\":30,\"name\":{\"24\":{}},\"comment\":{}}],[\"retrymaxattempts\",{\"_index\":28,\"name\":{\"22\":{}},\"comment\":{}}],[\"retrymaxdurationms\",{\"_index\":31,\"name\":{\"25\":{}},\"comment\":{}}],[\"retryrejectonfail\",{\"_index\":32,\"name\":{\"26\":{}},\"comment\":{}}],[\"returns\",{\"_index\":220,\"name\":{\"309\":{},\"612\":{},\"680\":{}},\"comment\":{}}],[\"safestringoption\",{\"_index\":53,\"name\":{\"51\":{},\"55\":{}},\"comment\":{}}],[\"secure\",{\"_index\":402,\"name\":{\"763\":{}},\"comment\":{}}],[\"selenium\",{\"_index\":13,\"name\":{\"8\":{}},\"comment\":{}}],[\"seleniumcomponent\",{\"_index\":336,\"name\":{\"567\":{}},\"comment\":{}}],[\"seleniumverifier\",{\"_index\":337,\"name\":{\"579\":{}},\"comment\":{}}],[\"seleniumverifierinternals\",{\"_index\":343,\"name\":{\"619\":{}},\"comment\":{}}],[\"services\",{\"_index\":16,\"name\":{\"10\":{}},\"comment\":{}}],[\"sessiongeneratormanager\",{\"_index\":340,\"name\":{\"585\":{},\"653\":{}},\"comment\":{}}],[\"set\",{\"_index\":34,\"name\":{\"28\":{},\"43\":{},\"129\":{},\"757\":{}},\"comment\":{}}],[\"setactual\",{\"_index\":233,\"name\":{\"329\":{}},\"comment\":{}}],[\"setcookie\",{\"_index\":397,\"name\":{\"751\":{},\"755\":{}},\"comment\":{}}],[\"setcookieoptions\",{\"_index\":398,\"name\":{\"758\":{}},\"comment\":{}}],[\"setrequestdefaults\",{\"_index\":413,\"name\":{\"777\":{}},\"comment\":{}}],[\"setsection\",{\"_index\":36,\"name\":{\"30\":{}},\"comment\":{}}],[\"setverbosity\",{\"_index\":82,\"name\":{\"91\":{}},\"comment\":{}}],[\"short\",{\"_index\":91,\"name\":{\"102\":{}},\"comment\":{}}],[\"shouldrun\",{\"_index\":197,\"name\":{\"272\":{},\"281\":{},\"311\":{},\"366\":{},\"394\":{},\"512\":{},\"613\":{},\"681\":{}},\"comment\":{}}],[\"size\",{\"_index\":46,\"name\":{\"44\":{},\"130\":{}},\"comment\":{}}],[\"specdone\",{\"_index\":249,\"name\":{\"346\":{}},\"comment\":{}}],[\"specstarted\",{\"_index\":248,\"name\":{\"345\":{}},\"comment\":{}}],[\"stack\",{\"_index\":84,\"name\":{\"94\":{}},\"comment\":{}}],[\"status\",{\"_index\":191,\"name\":{\"265\":{}},\"comment\":{}}],[\"statuscode\",{\"_index\":363,\"name\":{\"709\":{}},\"comment\":{}}],[\"step\",{\"_index\":182,\"name\":{\"252\":{}},\"comment\":{}}],[\"submitresult\",{\"_index\":175,\"name\":{\"238\":{},\"258\":{},\"433\":{},\"458\":{},\"486\":{},\"525\":{}},\"comment\":{}}],[\"suiteids\",{\"_index\":306,\"name\":{\"498\":{}},\"comment\":{}}],[\"test\",{\"_index\":253,\"name\":{\"353\":{},\"374\":{},\"381\":{},\"401\":{}},\"comment\":{}}],[\"testcases\",{\"_index\":258,\"name\":{\"362\":{},\"390\":{}},\"comment\":{}}],[\"testexecutionpolicymanager\",{\"_index\":198,\"name\":{\"276\":{}},\"comment\":{}}],[\"testexecutionpolicyplugin\",{\"_index\":196,\"name\":{\"270\":{}},\"comment\":{}}],[\"testid\",{\"_index\":188,\"name\":{\"262\":{}},\"comment\":{}}],[\"testname\",{\"_index\":189,\"name\":{\"263\":{}},\"comment\":{}}],[\"testrail\",{\"_index\":11,\"name\":{\"6\":{}},\"comment\":{}}],[\"testrailconfig\",{\"_index\":302,\"name\":{\"492\":{}},\"comment\":{}}],[\"testrailreportingplugin\",{\"_index\":317,\"name\":{\"516\":{}},\"comment\":{}}],[\"testrailtestexecutionpolicyplugin\",{\"_index\":311,\"name\":{\"505\":{}},\"comment\":{}}],[\"testresult\",{\"_index\":187,\"name\":{\"260\":{}},\"comment\":{}}],[\"testresults\",{\"_index\":300,\"name\":{\"483\":{}},\"comment\":{}}],[\"teststatus\",{\"_index\":195,\"name\":{\"269\":{}},\"comment\":{}}],[\"textcss\",{\"_index\":369,\"name\":{\"715\":{}},\"comment\":{}}],[\"texthtml\",{\"_index\":370,\"name\":{\"716\":{}},\"comment\":{}}],[\"textjavascript\",{\"_index\":372,\"name\":{\"718\":{}},\"comment\":{}}],[\"textplain\",{\"_index\":368,\"name\":{\"714\":{}},\"comment\":{}}],[\"textxml\",{\"_index\":371,\"name\":{\"717\":{}},\"comment\":{}}],[\"then\",{\"_index\":145,\"name\":{\"176\":{},\"301\":{},\"605\":{},\"673\":{}},\"comment\":{}}],[\"toconsole\",{\"_index\":154,\"name\":{\"189\":{}},\"comment\":{}}],[\"toobject\",{\"_index\":354,\"name\":{\"694\":{}},\"comment\":{}}],[\"tostring\",{\"_index\":85,\"name\":{\"95\":{}},\"comment\":{}}],[\"tostringtag\",{\"_index\":52,\"name\":{\"50\":{},\"137\":{}},\"comment\":{}}],[\"totalattempts\",{\"_index\":133,\"name\":{\"164\":{}},\"comment\":{}}],[\"totalduration\",{\"_index\":135,\"name\":{\"166\":{}},\"comment\":{}}],[\"tovalue\",{\"_index\":156,\"name\":{\"194\":{}},\"comment\":{}}],[\"trace\",{\"_index\":179,\"name\":{\"249\":{}},\"comment\":{}}],[\"type\",{\"_index\":83,\"name\":{\"92\":{},\"725\":{}},\"comment\":{}}],[\"ui\",{\"_index\":12,\"name\":{\"7\":{},\"8\":{},\"9\":{}},\"comment\":{}}],[\"uicomponent\",{\"_index\":327,\"name\":{\"544\":{}},\"comment\":{}}],[\"uicomponentoptions\",{\"_index\":323,\"name\":{\"537\":{}},\"comment\":{}}],[\"uisessionconfig\",{\"_index\":320,\"name\":{\"533\":{}},\"comment\":{}}],[\"uisessiongeneratormanager\",{\"_index\":335,\"name\":{\"562\":{}},\"comment\":{}}],[\"uisessiongeneratorplugin\",{\"_index\":333,\"name\":{\"556\":{}},\"comment\":{}}],[\"unlock\",{\"_index\":102,\"name\":{\"114\":{}},\"comment\":{}}],[\"until\",{\"_index\":137,\"name\":{\"168\":{}},\"comment\":{}}],[\"uri\",{\"_index\":387,\"name\":{\"741\":{}},\"comment\":{}}],[\"url\",{\"_index\":303,\"name\":{\"494\":{},\"698\":{}},\"comment\":{}}],[\"user\",{\"_index\":114,\"name\":{\"142\":{},\"495\":{}},\"comment\":{}}],[\"username\",{\"_index\":385,\"name\":{\"739\":{}},\"comment\":{}}],[\"using\",{\"_index\":147,\"name\":{\"179\":{}},\"comment\":{}}],[\"usingaftconfig\",{\"_index\":227,\"name\":{\"319\":{}},\"comment\":{}}],[\"usingbuildinfomanager\",{\"_index\":228,\"name\":{\"321\":{}},\"comment\":{}}],[\"usingreporter\",{\"_index\":229,\"name\":{\"323\":{}},\"comment\":{}}],[\"usingtestexecutionpolicymanager\",{\"_index\":230,\"name\":{\"325\":{}},\"comment\":{}}],[\"val\",{\"_index\":400,\"name\":{\"761\":{}},\"comment\":{}}],[\"validuntil\",{\"_index\":70,\"name\":{\"74\":{}},\"comment\":{}}],[\"values\",{\"_index\":49,\"name\":{\"47\":{},\"133\":{}},\"comment\":{}}],[\"verbosity\",{\"_index\":79,\"name\":{\"85\":{},\"90\":{}},\"comment\":{}}],[\"verifier\",{\"_index\":201,\"name\":{\"284\":{}},\"comment\":{}}],[\"verifierevent\",{\"_index\":200,\"name\":{\"283\":{}},\"comment\":{}}],[\"verifierinternals\",{\"_index\":226,\"name\":{\"317\":{}},\"comment\":{}}],[\"verifiermatcher\",{\"_index\":231,\"name\":{\"327\":{}},\"comment\":{}}],[\"verify\",{\"_index\":217,\"name\":{\"306\":{},\"316\":{},\"367\":{},\"395\":{},\"609\":{},\"677\":{}},\"comment\":{}}],[\"verifywithselenium\",{\"_index\":342,\"name\":{\"618\":{}},\"comment\":{}}],[\"verifywithwebdriverio\",{\"_index\":351,\"name\":{\"686\":{}},\"comment\":{}}],[\"wait\",{\"_index\":150,\"name\":{\"182\":{}},\"comment\":{}}],[\"waitduration\",{\"_index\":99,\"name\":{\"111\":{}},\"comment\":{}}],[\"warn\",{\"_index\":183,\"name\":{\"253\":{}},\"comment\":{}}],[\"web\",{\"_index\":15,\"name\":{\"10\":{}},\"comment\":{}}],[\"webdriverio\",{\"_index\":14,\"name\":{\"9\":{}},\"comment\":{}}],[\"webdriveriocomponent\",{\"_index\":346,\"name\":{\"634\":{}},\"comment\":{}}],[\"webdriverioremotesessiongeneratorplugin\",{\"_index\":352,\"name\":{\"687\":{}},\"comment\":{}}],[\"webdriverioverifier\",{\"_index\":348,\"name\":{\"647\":{}},\"comment\":{}}],[\"webdriverioverifierinternals\",{\"_index\":347,\"name\":{\"646\":{}},\"comment\":{}}],[\"withadditionalsessionoptions\",{\"_index\":341,\"name\":{\"588\":{},\"656\":{}},\"comment\":{}}],[\"withbackoff\",{\"_index\":139,\"name\":{\"170\":{}},\"comment\":{}}],[\"withdelay\",{\"_index\":138,\"name\":{\"169\":{}},\"comment\":{}}],[\"withdescription\",{\"_index\":218,\"name\":{\"307\":{},\"610\":{},\"678\":{}},\"comment\":{}}],[\"withfailaction\",{\"_index\":143,\"name\":{\"174\":{}},\"comment\":{}}],[\"withmaxattempts\",{\"_index\":141,\"name\":{\"172\":{}},\"comment\":{}}],[\"withmaxduration\",{\"_index\":140,\"name\":{\"171\":{}},\"comment\":{}}],[\"withrejectonfail\",{\"_index\":142,\"name\":{\"173\":{}},\"comment\":{}}],[\"withtestids\",{\"_index\":219,\"name\":{\"308\":{},\"611\":{},\"679\":{}},\"comment\":{}}],[\"xml\",{\"_index\":353,\"name\":{\"693\":{}},\"comment\":{}}]],\"pipeline\":[]}}"); \ No newline at end of file diff --git a/docs/classes/aft_core.AftConfig.html b/docs/classes/aft_core.AftConfig.html new file mode 100644 index 00000000..b35eec59 --- /dev/null +++ b/docs/classes/aft_core.AftConfig.html @@ -0,0 +1,461 @@ +AftConfig | automated-functional-testing
+
+ +
+
+
+ +
+

Hierarchy

+
    +
  • AftConfig
+
+
+
+ +
+
+

Constructors

+
+ +
+
+

Properties

+
+ +
+
+ +
_sectionCache: Map<string, {}>
+
+ +
_valueCache: Map<string, JsonValue>
+
+

Accessors

+
+ +
+
+ +
    +
  • get fileLockMaxWait(): number
  • +
  • +

    used by ExpiringFileLock to set the number of milliseconds to wait for a lock to become available

    + +

    Default

    10000

    +
    +

    Returns number

+
+ +
    +
  • get fsMapDirectory(): string
  • +
  • +

    used by FileSystemMap to set the directory where the data is written to the file system

    + +

    Default

    'FileSystemMap'

    +
    +

    Returns string

+
+ +
    +
  • get logLevel(): "trace" | "debug" | "info" | "step" | "warn" | "pass" | "fail" | "error" | "none"
  • +
  • +

    used by Reporter

    + +

    Default

    'warn'

    +
    +

    Returns "trace" | "debug" | "info" | "step" | "warn" | "pass" | "fail" | "error" | "none"

+
+ +
    +
  • get pluginNames(): string[]
  • +
  • +

    an array of plugin filenames (these must also match the lowercase plugin class name minus +any -, _ and . characters) to load via the pluginLoader

    +

    ex:

    +
    // aftconfig.json
    {
    "pluginNames": ["my-plugin"]
    } +
    +

    would match with the following plugin class

    +
    // my-plugin.js
    export class MyPlugin extends Plugin {
    doStuff = () => 'stuff';
    } +
    + +

    Default

    []

    +
    +

    Returns string[]

+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
    +
  • get retryRejectOnFail(): boolean
  • +
  • +

    used by retry to indicate if a failure to get success should result in a Promise.reject +on completion or simply returning null

    + +

    Default

    true

    +
    +

    Returns boolean

+
+

Methods

+
+ +
    + +
  • +

    looks for a value in the aftconfig.json file at the top level and if found attempts +to extract any environment variable set if the value matches a format of %some_var_name% +before returning the value or the specified defaultVal if nothing was found

    + +

    Returns

    the value set in the aftconfig.json file for the specified key or undefined

    +
    +
    +

    Type Parameters

    +
    +
    +

    Parameters

    +
      +
    • +
      key: string
      +

      the configuration key

      +
    • +
    • +
      Optional defaultVal: T
      +

      a default value to return if no value is set for the specified key

      +
    +

    Returns T

+
+ +
    + +
  • +

    looks for a top-level section in your aftconfig.json file with a name matching the passed in +className and returns it or a new instance of the className type

    + +

    Returns

    the section from aftconfig.json matching the name of the passed in className or a +new instance of the className type

    +
    +
    +

    Type Parameters

    +
      +
    • +

      T extends {}

    +
    +

    Parameters

    +
      +
    • +
      className: string | Class<T>
      +

      a class of type T where the name of the class and the section name must match

      +
    +

    Returns T

+
+ +
    + +
  • +

    attempts to get an environment variable value for a given key if the passed +in input is in the format of %some_env_var_key%

    + +

    Returns

    the value of the environment variable

    +
    +
    +

    Parameters

    +
      +
    • +
      input: string
      +

      a string that might reference an environment var between two % +characters like %some_env_var%

      +
    +

    Returns string

+
+ +
    + +
  • +

    iterates over all properties for the passed in input object and +if a property is a string it calls processEnvVars on the property

    + +

    Returns

    the input object with any string property values updated +based on the result of calling processEnvVars

    +
    +
    +

    Type Parameters

    +
      +
    • +

      T extends {}

    +
    +

    Parameters

    +
      +
    • +
      input: T
      +

      an object that contains properties

      +
    +

    Returns T

+
+ +
+
+ +
    + +
  • +

    adds the passed in section to the ConfigManager cache of aftconfig.json +sections so it will be used instead of the value from the actual JSON file

    +
    +
    +

    Type Parameters

    +
      +
    • +

      T extends {}

    +
    +

    Parameters

    +
      +
    • +
      key: string
      +

      adds the passed in section to the cache so it will be used +instead of reading from aftconfig.json

      +
    • +
    • +
      section: T
      +

      an object containing properties

      +
    +

    Returns void

+
+
+

Generated using TypeDoc

+
\ No newline at end of file diff --git a/docs/classes/aft_core.AftConfigProvider.html b/docs/classes/aft_core.AftConfigProvider.html deleted file mode 100644 index 9f26bbb4..00000000 --- a/docs/classes/aft_core.AftConfigProvider.html +++ /dev/null @@ -1,191 +0,0 @@ -AftConfigProvider | automated-functional-testing
-
- -
-
-
-
- -

Class AftConfigProvider<T>

-
-

Type Parameters

-
    -
  • -

    T extends object

-
-

Hierarchy

-
    -
  • AftConfigProvider
-
-

Implements

-
-
-
-
- -
-
-

Constructors

-
-
-

Properties

-
-
-

Accessors

-
-
-

Methods

-
get -
-
-

Constructors

-
- -
-
-

Properties

-
- -
_aftConfig: JsonObject
-
- -
_optsProvider: OptionsProvider<T>
-
- -
configKey: string
-
-

Accessors

-
- -
-
- -
-
-

Methods

-
- -
-
-
-

Generated using TypeDoc

-
\ No newline at end of file diff --git a/docs/classes/aft_core.AftLogger.html b/docs/classes/aft_core.AftLogger.html new file mode 100644 index 00000000..1f0f77cf --- /dev/null +++ b/docs/classes/aft_core.AftLogger.html @@ -0,0 +1,232 @@ +AftLogger | automated-functional-testing
+
+ +
+
+
+ +
+

a logging class that uses configuration to determine what +should be logged to the console and formats the logging output +to indicate the source of the logging data. +Configuration for this class can be passed in directly or +specified in aftconfig.json like:

+
// aftconfig.json
{
...
"logLevel": "info"
...
} +
+

NOTE: this should only be used in cases where using Reporter would +not be reasonable such as inside core components of AFT; otherwise you +should use a Reporter instance instead

+
+
+

Hierarchy

+
    +
  • AftLogger
+
+
+
+ +
+
+

Constructors

+
+
+

Properties

+
+
+

Accessors

+
+
+

Methods

+
+
+

Constructors

+
+ +
+
+

Properties

+
+ +
aftCfg: AftConfig
+
+

Accessors

+
+ +
    +
  • get logLevel(): "trace" | "debug" | "info" | "step" | "warn" | "pass" | "fail" | "error" | "none"
  • +
  • +

    allows for filtering out of erroneous information from logs by assigning +values to different types of logging. the purpose of each log level is +as follows:

    +
      +
    • trace - used when logging low-level debug events that occur within a loop
    • +
    • debug - used for debug logging that does not run within a loop or at a high frequency
    • +
    • info - used for informational events providing current state of a system
    • +
    • step - used within a test to denote where within the test steps we are
    • +
    • warn - used for unexpected errors that are recoverable
    • +
    • pass - used to indicate the success of a test expectation or assertion
    • +
    • fail - used to indicate the failure of a test expectation or assertion
    • +
    • error - used for unexpected errors that are not recoverable
    • +
    • none - used when no logging is desired (disables logging)
    • +
    +
    +

    Returns "trace" | "debug" | "info" | "step" | "warn" | "pass" | "fail" | "error" | "none"

+
+

Methods

+
+ +
    + +
  • +

    formats the passed in LogMessage.message based on the passed in options

    + +

    Returns

    the formatted log string

    +
    +
    +

    Parameters

    +
      +
    • +
      data: LogMessageData
      +

      a LogMessage object containing the level, name and message to +be formatted into a console-friendly log string

      +
    +

    Returns string

+
+ +
    + +
  • +

    function will check that the level is greater or equal to the current configured logLevel +and if it is, will send the name, level and message to the console. if any data +is included it will be converted to a string using JSON.stringify(...) and appended +to the message

    +
    +
    +

    Parameters

    +
      +
    • +
      data: LogMessageData
      +

      an array of additional data to be included in the logs

      +
    +

    Returns void

+
+ +
    + +
  • +

    applies a colour based on the supplied level and outputs the message +to the console using console.log in that colour

    +
    +

    NOTE: calling this function directly will bypass checking the level +to see if the message should actually be logged and simply outputs to +the console

    +
    +
    +
    +

    Parameters

    +
      +
    • +
      level: "trace" | "debug" | "info" | "step" | "warn" | "pass" | "fail" | "error" | "none"
      +

      a valid {LogLevel} like 'warn' or 'trace'

      +
    • +
    • +
      message: string
      +

      the message string to log to console

      +
    +

    Returns void

+
+
+

Generated using TypeDoc

+
\ No newline at end of file diff --git a/docs/classes/aft_core.BuildInfoManager.html b/docs/classes/aft_core.BuildInfoManager.html index e622f461..d2d74829 100644 --- a/docs/classes/aft_core.BuildInfoManager.html +++ b/docs/classes/aft_core.BuildInfoManager.html @@ -14,22 +14,12 @@
  • aft-core
  • BuildInfoManager
  • Class BuildInfoManager

    -
    -

    loads and provides an interface between any BuildInfoPlugin -that provides CICD build details such as TeamCity, Jenkins, -Bamboo or Octopus.

    -

    to specify a plugin use the following aftconfig.json key:

    -
    {
    ...
    "buildinfomanager": {
    "pluginNames": ["plugin-name"]
    }
    ...
    } -
    -

    Hierarchy

    @@ -37,50 +27,58 @@

    Constructors

    -
    +
    -
    +
  • Defined in aft-core/src/plugins/build-info/build-info-manager.ts:16
  • Properties

    -
    - -
    safeStrOpt: SafeStringOption[] = ...
    +
    + +
    _aftLogger: AftLogger
    +
    + +
    _safeStrOpt: SafeStringOption[] = ...
    +
    + +
    aftCfg: AftConfig
    +
    + +
    plugins: BuildInfoPlugin[]

    Methods

    @@ -88,71 +86,29 @@
    +
  • Defined in aft-core/src/plugins/build-info/build-info-manager.ts:41
    • -

      returns a build number as a string as provided by the first enabled -plugin

      +

      gets the first enabled IBuildInfoPlugin and returns the value from it's buildNumber +function or a name consisting of the current date like: YYYYMMDD if no enabled plugins found

      -

      Returns

      the build number returned by the first enabled plugin -or null if none exist

      +

      Returns

      the build name generated by the first enabled IBuildInfoPlugin.buildNumber or +a name consisting of the current date like: YYYYMMDD if no enabled plugins found

      Returns Promise<string>

    -
    - -
    -
    - -
    -
    - -
    +
  • Defined in aft-core/src/plugins/build-info/build-info-manager.ts:66
  • -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    +
  • Defined in aft-core/src/plugins/build-info/build-info-manager.ts:29
  • +
  • get
  • Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/classes/aft_core.BuildInfoPlugin.html b/docs/classes/aft_core.BuildInfoPlugin.html index fc43737c..4f9fc846 100644 --- a/docs/classes/aft_core.BuildInfoPlugin.html +++ b/docs/classes/aft_core.BuildInfoPlugin.html @@ -13,23 +13,18 @@
  • automated-functional-testing
  • aft-core
  • BuildInfoPlugin
  • -

    Class BuildInfoPlugin<T>Abstract

    +

    Class BuildInfoPlugin

    -

    interface to be implemented by any Plugin implementation

    -
    -
    -

    Type Parameters

    -
    +

    class to be extended by any Plugin implementation

    +

    Hierarchy

    +
  • Defined in aft-core/src/plugins/build-info/build-info-plugin.ts:3
  • @@ -41,37 +36,51 @@

    Constructors

    Accessors

    -

    Methods

    Constructors

    +

    Returns BuildInfoPlugin

    +
  • Defined in aft-core/src/plugins/plugin.ts:23
  • Accessors

    +
    + +
    +
    + +
    +
  • Defined in aft-core/src/plugins/plugin.ts:20
  • Methods

    - +
    +
  • Defined in aft-core/src/plugins/build-info/build-info-plugin.ts:4
  • - +
    -
    - -
      - -
    • -
      -

      Type Parameters

      -
        -
      • -

        K extends string | number | symbol

      • -
      • -

        V

      -
      -

      Parameters

      -
        -
      • -
        key: K
      • -
      • -
        Optional defaultVal: V
      -

      Returns V

    +
  • Defined in aft-core/src/plugins/build-info/build-info-plugin.ts:5
  • +
  • buildNumber
  • Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/classes/aft_core.CacheMap.html b/docs/classes/aft_core.CacheMap.html index 74b499fd..c4cd5a43 100644 --- a/docs/classes/aft_core.CacheMap.html +++ b/docs/classes/aft_core.CacheMap.html @@ -45,7 +45,7 @@

    Implements

    • Map<K, V>
    +
  • Defined in aft-core/src/helpers/cache-map.ts:16
  • @@ -104,19 +104,19 @@
    useFileCache: boolean
    Optional filename: string

    Returns CacheMap<K, V>

    +
  • Defined in aft-core/src/helpers/cache-map.ts:20
  • Properties

    _cacheDuration: number
    +
  • Defined in aft-core/src/helpers/cache-map.ts:18
  • _internalMap: Map<K, CacheObject> | FileSystemMap<K, CacheObject>
    +
  • Defined in aft-core/src/helpers/cache-map.ts:17
  • Accessors

    @@ -125,9 +125,9 @@
    +
  • Defined in aft-core/src/helpers/cache-map.ts:106
  • +
  • Defined in aft-core/src/helpers/cache-map.ts:70
  • Methods

    @@ -145,9 +145,9 @@
    +
  • Defined in aft-core/src/helpers/cache-map.ts:96
    • @@ -160,7 +160,7 @@

      Parameters

      cacheObject: CacheObject

    Returns boolean

    +
  • Defined in aft-core/src/helpers/cache-map.ts:117
  • +
  • Defined in aft-core/src/helpers/cache-map.ts:28
  • +
  • Defined in aft-core/src/helpers/cache-map.ts:31
  • +
  • Defined in aft-core/src/helpers/cache-map.ts:73
  • +
  • Defined in aft-core/src/helpers/cache-map.ts:34
  • +
  • Defined in aft-core/src/helpers/cache-map.ts:44
  • +
  • Defined in aft-core/src/helpers/cache-map.ts:53
  • +
  • Defined in aft-core/src/helpers/cache-map.ts:83
  • +
  • Defined in aft-core/src/helpers/cache-map.ts:62
  • +
  • Defined in aft-core/src/helpers/cache-map.ts:86
  • provides a standardised way of generating log-friendly exception details in either short or full formatting. Usage would look like:

    -
    const logMgr = new LogManager({logName: 'foo'});
    const result = await Err.handle(functionThatThrowsTypeError, {
    logMgr: logMgr,
    errLevel: 'debug',
    verbosity: 'short'
    }); +
    const result1 = Err.handle(() => functionThatThrowsTypeError());
    const result2 = await Err.handleAsync(async () => asyncFunctionThatThrowsArgumentError());

    which would output:

    -
    YYYYMMDD - [foo] - DEBUG - TypeError: [max 100 characters of message...] --- [max 300 characters of the ... first line of stack trace]
    +
    YYYYMMDD - [AFT] - WARN  - TypeError: [max 100 characters of message...] --- [max 300 characters...of the stack trace]
    +YYYYMMDD - [AFT] - WARN  - ArgumentError: [max 100 characters of message...] --- [max 300 characters...of the stack trace]
     
    +
    +

    NOTE: an optional Partial<ErrorOptions> object can be passed to the handle and handleAsync functions allowing +you to control the LogLevel used (defaults to 'warn'), the verbosity (defaults to 'short'), and the +Reporter instance used (defaults to aftLog global instance)

    +

    and:

    -
    const logMgr = new LogManager({logName: 'AFT'});
    try {
    functionThatThrowsTypeError();
    } catch (e) {
    await logMgr.warn(Err.short(e));
    await logMgr.debug(Err.full(e));
    } +
    const logger = new Reporter('AFT');
    try {
    functionThatThrowsTypeError();
    } catch (e) {
    await logger.warn(Err.short(e));
    await logger.debug(Err.full(e));
    }

    which outputs:

    -
    YYYYMMDD - [AFT] - WARN - TypeError: [max 100 characters of message...] --- [max 300 characters of the ... first line of stack trace]
    -YYYYMMDD - [AFT] - DEBUG - TypeError: [full type error description message]
    +
    YYYYMMDD - [AFT] - WARN - TypeError: [max 100 characters of message...] --- [max 300 characters...of the stack trace]
    +YYYYMMDD - [AFT] - DEBUG - TypeError: [full type error message and stack trace]
     [full stack trace of as much as the Error contained]
     
    @@ -36,8 +42,8 @@

    Hierarchy

    • Err
    +
  • Defined in aft-core/src/helpers/err.ts:62
  • +
  • Defined in aft-core/src/helpers/err.ts:156
  • @@ -83,19 +89,19 @@

    Parameters

    error: any

    Returns Err

    +
  • Defined in aft-core/src/helpers/err.ts:66
  • Properties

    _verbosity: ErrVerbosity
    +
  • Defined in aft-core/src/helpers/err.ts:64
  • err: Error
    +
  • Defined in aft-core/src/helpers/err.ts:63
  • Accessors

    @@ -105,7 +111,7 @@
    +
  • Defined in aft-core/src/helpers/err.ts:90
  • +
  • Defined in aft-core/src/helpers/err.ts:94
  • +
  • Defined in aft-core/src/helpers/err.ts:86
  • +
  • Defined in aft-core/src/helpers/err.ts:74
  • Methods

    @@ -144,7 +150,7 @@

    Parameters

    obj: any

    Returns boolean

    +
  • Defined in aft-core/src/helpers/err.ts:110
    • @@ -157,7 +163,7 @@

      Parameters

      message: string

    Returns string

    +
  • Defined in aft-core/src/helpers/err.ts:114
    • @@ -170,7 +176,7 @@

      Parameters

      stack: string

    Returns string

    +
  • Defined in aft-core/src/helpers/err.ts:123
    • @@ -183,7 +189,7 @@

      Parameters

      stack: string

    Returns string

    +
  • Defined in aft-core/src/helpers/err.ts:135
    • @@ -196,7 +202,7 @@

      Parameters

      input: string

    Returns string

    +
  • Defined in aft-core/src/helpers/err.ts:147
  • Returns Err

    +
  • Defined in aft-core/src/helpers/err.ts:81
  • +
  • Defined in aft-core/src/helpers/err.ts:98
  • class will create a new (or use existing) lockfile locking @@ -22,7 +22,9 @@

    Class ExpiringFileLock

    the class will wait up to the maxWaitDurationMs before throwing an exception

    Ex:

    -
    const maxWait = 10000; // 10 seconds
    const maxHold = 5000; // 5 seconds
    // wait a maximum of 10 seconds to aquire lock and then hold
    // lock for maximum of 5 seconds or until `unlock` is called
    const lock = new ExpiringFileLock('unique_name', maxWait, maxHold);
    try {
    // perform action on shared resource...
    } finally {
    lock?.unlock();
    } +
    // aftconfig.json
    {
    fileLockMaxWait: 10000,
    fileLockMaxHold: 5000
    } +
    +
    // wait a maximum of 10 seconds to aquire lock and then hold
    // lock for maximum of 5 seconds or until `unlock` is called
    const lock = new ExpiringFileLock('unique_name');
    try {
    // perform action on shared resource...
    } finally {
    lock?.unlock();
    }
    @@ -30,7 +32,8 @@

    Hierarchy

    • ExpiringFileLock
    +
  • Defined in aft-core/src/helpers/expiring-file-lock.ts:36
  • +
  • Defined in aft-core/src/helpers/expiring-file-lock.ts:94
  • @@ -38,27 +41,28 @@

    Constructors

      - +
    • Parameters

      @@ -66,39 +70,42 @@

      Parameters

    • lockFileName: string
    • -
      maxWaitDurationMs: number
    • -
    • -
      maxHoldDurationMs: number
    -

    Returns ExpiringFileLock

    +
  • Defined in aft-core/src/helpers/expiring-file-lock.ts:45
  • Properties

    _lockFileDescriptor: number
    +
  • Defined in aft-core/src/helpers/expiring-file-lock.ts:42
  • _timeout: Timeout
    +
  • Defined in aft-core/src/helpers/expiring-file-lock.ts:43
  • +
    + +
    aftCfg: AftConfig
    lockDuration: number
    +
  • Defined in aft-core/src/helpers/expiring-file-lock.ts:39
  • lockName: string
    +
  • Defined in aft-core/src/helpers/expiring-file-lock.ts:38
  • waitDuration: number
    +
  • Defined in aft-core/src/helpers/expiring-file-lock.ts:40
  • Methods

    @@ -108,7 +115,7 @@
    +
  • Defined in aft-core/src/helpers/expiring-file-lock.ts:66
  • +
  • Defined in aft-core/src/helpers/expiring-file-lock.ts:61
  • +
  • constructor
  • +
  • _lockFileDescriptor
  • +
  • _timeout
  • +
  • aftCfg
  • +
  • lockDuration
  • +
  • lockName
  • +
  • waitDuration
  • +
  • _waitForLock
  • +
  • unlock
  • Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/classes/aft_core.FileSystemMap.html b/docs/classes/aft_core.FileSystemMap.html index 890a7422..3c528b81 100644 --- a/docs/classes/aft_core.FileSystemMap.html +++ b/docs/classes/aft_core.FileSystemMap.html @@ -25,6 +25,9 @@

    Param

    the filesystem name to store data within. this will be combined

    Param

    an optional array of arrays containing two elements used to seed the instantiated map object

    + +

    Param

    an optional AftConfig instance that allows you to override any +FileSystemMapConfig loaded from appsettings.json

    Type Parameters

    @@ -42,7 +45,7 @@

    Implements

    • Map<Tkey, Tval>
    +
  • Defined in aft-core/src/helpers/file-system-map.ts:20
  • @@ -54,7 +57,8 @@

    Constructors

    Properties

    -
    @@ -82,7 +86,7 @@

    Constructors

      - +
    • Type Parameters

      @@ -97,22 +101,29 @@

      Parameters

    • filename: string
    • -
      Optional entries: readonly (readonly [Tkey, Tval])[]
    +
    Optional entries: readonly (readonly [Tkey, Tval])[]
    +
  • +
    Optional aftCfg: AftConfig
  • Returns FileSystemMap<Tkey, Tval>

    +
  • Defined in aft-core/src/helpers/file-system-map.ts:27
  • Properties

    +
    + +
    _aftCfg: AftConfig
    _memoryMap: Map<Tkey, Tval>
    +
  • Defined in aft-core/src/helpers/file-system-map.ts:24
  • filename: string
    +
  • Defined in aft-core/src/helpers/file-system-map.ts:22
  • Accessors

    @@ -121,9 +132,9 @@
    +
  • Defined in aft-core/src/helpers/file-system-map.ts:94
  • +
  • Defined in aft-core/src/helpers/file-system-map.ts:74
  • Methods

    @@ -141,9 +152,9 @@
    +
  • Defined in aft-core/src/helpers/file-system-map.ts:90
  • +
  • Defined in aft-core/src/helpers/file-system-map.ts:108
  • +
  • Defined in aft-core/src/helpers/file-system-map.ts:99
  • +
  • Defined in aft-core/src/helpers/file-system-map.ts:45
  • +
  • Defined in aft-core/src/helpers/file-system-map.ts:49
  • +
  • Defined in aft-core/src/helpers/file-system-map.ts:78
  • +
  • Defined in aft-core/src/helpers/file-system-map.ts:55
  • +
  • Defined in aft-core/src/helpers/file-system-map.ts:60
  • +
  • Defined in aft-core/src/helpers/file-system-map.ts:64
  • +
  • Defined in aft-core/src/helpers/file-system-map.ts:82
  • +
  • Defined in aft-core/src/helpers/file-system-map.ts:68
  • +
  • Defined in aft-core/src/helpers/file-system-map.ts:86
  • +

    Class Plugin

    -

    interface to be implemented by any Plugin implementation

    -
    -
    -

    Type Parameters

    -
    +

    class to be extended by any Plugin implementation

    +

    Hierarchy

    -
    -

    Implements

    -
    @@ -48,51 +38,60 @@

    Constructors

    Properties

    -

    Accessors

    -
    -
    -

    Methods

    -

    Constructors

    +

    Returns Plugin

    +
  • Defined in aft-core/src/plugins/plugin.ts:23
  • Properties

    -
    - -
    _enabled: boolean
    +
  • Defined in aft-core/src/plugins/plugin.ts:13
  • Accessors

    +
    + +
    +
    + +
    -
    -

    Methods

    -
    - -
      - -
    • -
      -

      Type Parameters

      -
        -
      • -

        K extends string | number | symbol

      • -
      • -

        V

      -
      -

      Parameters

      -
        -
      • -
        key: K
      • -
      • -
        Optional defaultVal: V
      -

      Returns V

    +
  • Defined in aft-core/src/plugins/plugin.ts:20
  • +
  • _aftCfg
  • +
  • _aftLogger
  • +
  • aftCfg
  • +
  • aftLogger
  • +
  • enabled
  • Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/classes/aft_core.PluginConfig.html b/docs/classes/aft_core.PluginConfig.html new file mode 100644 index 00000000..9073ac7f --- /dev/null +++ b/docs/classes/aft_core.PluginConfig.html @@ -0,0 +1,107 @@ +PluginConfig | automated-functional-testing
    +
    + +
    +
    +
    + +
    +

    Hierarchy

    +
    +
    +
    +
    + +
    +
    +

    Constructors

    +
    +
    +

    Properties

    +
    +
    +

    Constructors

    +
    + +
    +
    +

    Properties

    +
    + +
    enabled: boolean = false
    +
    +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/classes/aft_core.PluginManager.html b/docs/classes/aft_core.PluginManager.html deleted file mode 100644 index e82f9922..00000000 --- a/docs/classes/aft_core.PluginManager.html +++ /dev/null @@ -1,299 +0,0 @@ -PluginManager | automated-functional-testing
    -
    - -
    -
    -
    -
    - -

    Class PluginManager<T, Tc>Abstract

    -
    -

    base class for use by classes that load in and manage plugins. -PluginManager instances should specify their plugin names and -location in the passed in options object or in the -aftconfig.json file under a section whose name -exactly matches the PluginManager instance's class name in all -lowercase.

    -

    ex: PluginInstance

    -
    export type PluginInstanceOptions = Union<PluginOptions, { foo?: string; bar?: boolean; }>;
    export class PluginInstance extends Plugin<PluginInstanceOptions> {
    constructor(options?: PluginInstanceOptions) {
    super(options);
    }
    } -
    -

    ex: PluginManagerInstance

    -
    export type PluginManagerInstanceOptions = Union<PluginManagerOptions, PluginInstanceOptions>;
    export class PluginManagerInstance extends PluginManager<PluginInstance, PluginInstanceOptions> {
    constructor(options?: PluginManagerInstanceOptions) {
    super(options);
    }
    } -
    -

    ex: aftconfig.json

    -
    {
    "PluginManagerInstance": {
    ...
    "plugins": [
    {"name": "some-custom-plugin", "enabled": false, "searchDirectory": "/full/path/to/search"},
    {"name": "a-second-plugin", "searchDirectory": "../../relative-path-to-search", "options": {"foo": "option used by plugin instance"}}
    ],
    "bar": "configurataion used by PluginManagerInstance"
    ...
    }
    } -
    -

    NOTE: the PluginManagerInstance will load plugins listed in the pluginNames array -and pass them any additional options specified (in this case the values for foo and bar)

    -
    -
    -

    Type Parameters

    -
    -
    -

    Hierarchy

    -
    -
    -

    Implements

    -
    -
    -
    -
    - -
    -
    -

    Constructors

    -
    -
    -

    Properties

    -
    -
    -

    Methods

    -
    -
    -

    Constructors

    -
    - -
      - -
    • -

      allows for specifying optional configuration for the PluginManager that will take -precedence over other forms of configuration as long as the cfgmgr is not overridden

      -
      -
      -

      Type Parameters

      -
      -
      -

      Parameters

      -
        -
      • -
        Optional options: Tc
        -

        an object defining configuration to be used by this PluginManager instance

        -
      -

      Returns PluginManager<T, Tc>

    -
    -

    Properties

    -
    - -
    _config: IConfigProvider<Tc>
    -
    - -
    _options: Tc
    -
    - -
    _plugins: T[]
    -
    -

    Methods

    -
    - -
    -
    - -
    -
    - -
    -
    - -
      - -
    • -

      instantiates new plugins and caches them for use at plugins

      -

      NOTE: this does not destroy previous instances, but removes them -from the internal array and replaces them with the new instances

      -
      -

      Returns Promise<T[]>

    -
    - -
      - -
    • -

      attempts to find the first plugin who's class name matches a specified string

      - -

      Returns

      the first plugin who's class name matched the passed in ctorName (both lowercase)

      -
      -
      -

      Parameters

      -
        -
      • -
        ctorName: string
        -

        the class name of the plugin

        -
      -

      Returns Promise<T>

    -
    - -
    -
    - -
    -
    - -
    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/classes/aft_core.PluginManagerWithLogging.html b/docs/classes/aft_core.PluginManagerWithLogging.html deleted file mode 100644 index 0c889050..00000000 --- a/docs/classes/aft_core.PluginManagerWithLogging.html +++ /dev/null @@ -1,295 +0,0 @@ -PluginManagerWithLogging | automated-functional-testing
    -
    - -
    -
    -
    -
    - -

    Class PluginManagerWithLogging<T, Tc>Abstract

    -
    -

    base class for use by classes that load in and manage plugins. -PluginManager instances should specify their plugin names and -location in the passed in options object or in the -aftconfig.json file under a section whose name -exactly matches the PluginManager instance's class name in all -lowercase.

    -

    ex: PluginInstance

    -
    export type PluginInstanceOptions = Union<PluginOptions, { foo?: string; bar?: boolean; }>;
    export class PluginInstance extends Plugin<PluginInstanceOptions> {
    constructor(options?: PluginInstanceOptions) {
    super(options);
    }
    } -
    -

    ex: PluginManagerInstance

    -
    export type PluginManagerInstanceOptions = Union<PluginManagerOptions, PluginInstanceOptions>;
    export class PluginManagerInstance extends PluginManager<PluginInstance, PluginInstanceOptions> {
    constructor(options?: PluginManagerInstanceOptions) {
    super(options);
    }
    } -
    -

    ex: aftconfig.json

    -
    {
    "PluginManagerInstance": {
    ...
    "plugins": [
    {"name": "some-custom-plugin", "enabled": false, "searchDirectory": "/full/path/to/search"},
    {"name": "a-second-plugin", "searchDirectory": "../../relative-path-to-search", "options": {"foo": "option used by plugin instance"}}
    ],
    "bar": "configurataion used by PluginManagerInstance"
    ...
    }
    } -
    -

    NOTE: the PluginManagerInstance will load plugins listed in the pluginNames array -and pass them any additional options specified (in this case the values for foo and bar)

    -
    -
    -

    Type Parameters

    -
    -
    -

    Hierarchy

    -
    -
    -
    -
    - -
    -
    -

    Constructors

    -
    -
    -

    Properties

    -
    -
    -

    Methods

    -
    -
    -

    Constructors

    -
    - -
    -
    -

    Properties

    -
    - -
    _logMgr: LogManager
    -
    -

    Methods

    -
    - -
    -
    - -
    -
    - -
    -
    - -
      - -
    • -

      instantiates new plugins and caches them for use at plugins

      -

      NOTE: this does not destroy previous instances, but removes them -from the internal array and replaces them with the new instances

      -
      -

      Returns Promise<T[]>

    -
    - -
    -
    - -
      - -
    • -

      attempts to find the first plugin who's class name matches a specified string

      - -

      Returns

      the first plugin who's class name matched the passed in ctorName (both lowercase)

      -
      -
      -

      Parameters

      -
        -
      • -
        ctorName: string
        -

        the class name of the plugin

        -
      -

      Returns Promise<T>

    -
    - -
    -
    - -
    -
    - -
    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/classes/aft_core.Reporter.html b/docs/classes/aft_core.Reporter.html new file mode 100644 index 00000000..79b56671 --- /dev/null +++ b/docs/classes/aft_core.Reporter.html @@ -0,0 +1,411 @@ +Reporter | automated-functional-testing
    +
    + +
    +
    +
    + +
    +

    a class that manages reporting plugins. +Configuration for this class can be passed in directly or +specified in aftconfig.json like:

    +
    // aftconfig.json
    {
    ...
    "logLevel": "info"
    ...
    } +
    +

    NOTE: multiple instances of this class are expected to be created as each instance should have a unique +reporterName associated with it. Ex:

    +
    const r1 = new Reporter('reporter for test 1');
    const r2 = new Reporter('reporter for test 2'); +
    +
    +
    +

    Hierarchy

    +
      +
    • Reporter
    +
    +
    +
    + +
    +
    +

    Constructors

    +
    +
    +

    Properties

    +
    +
    +

    Methods

    +
    +
    +

    Constructors

    +
    + +
    +
    +

    Properties

    +
    + +
    _aftLogger: AftLogger
    +
    + +
    _stepCount: number = 0
    +
    + +
    logLevel: "trace" | "debug" | "info" | "step" | "warn" | "pass" | "fail" | "error" | "none"
    +

    allows for filtering out of erroneous information from logs by assigning +values to different types of logging. the purpose of each log level is +as follows:

    +
      +
    • trace - used when logging low-level debug events that occur within a loop
    • +
    • debug - used for debug logging that does not run within a loop or at a high frequency
    • +
    • info - used for informational events providing current state of a system
    • +
    • step - used within a test to denote where within the test steps we are
    • +
    • warn - used for unexpected errors that are recoverable
    • +
    • pass - used to indicate the success of a test expectation or assertion
    • +
    • fail - used to indicate the failure of a test expectation or assertion
    • +
    • error - used for unexpected errors that are not recoverable
    • +
    • none - used when no logging is desired (disables logging)
    • +
    +
    +
    + +
    plugins: ReportingPlugin[]
    +
    + +
    reporterName: string
    +

    a name unique to a given reporter instance intended to uniquely identify output by +either the associated test or class doing the reporting

    +
    +
    +

    Methods

    +
    + +
      + +
    • +

      calls the log function with a LogLevel of debug

      +
      +
      +

      Parameters

      +
        +
      • +
        message: string
        +

        the message to be logged

        +
      • +
      • +
        Rest ...data: any[]
      +

      Returns Promise<void>

    +
    + +
      + +
    • +

      loops through any loaded ReportingPlugin objects and calls +their dispose function. This should be called upon completion +of any logging actions before destroying the AftLogger instance

      +
      +
      +

      Parameters

      +
        +
      • +
        Optional error: Error
      +

      Returns Promise<void>

    +
    + +
      + +
    • +

      calls the log function with a LogLevel of error

      +
      +
      +

      Parameters

      +
        +
      • +
        message: string
        +

        the message to be logged

        +
      • +
      • +
        Rest ...data: any[]
      +

      Returns Promise<void>

    +
    + +
      + +
    • +

      calls the log function with a LogLevel of fail

      +
      +
      +

      Parameters

      +
        +
      • +
        message: string
        +

        the message to be logged

        +
      • +
      • +
        Rest ...data: any[]
      +

      Returns Promise<void>

    +
    + +
      + +
    • +

      calls the log function with a LogLevel of info

      +
      +
      +

      Parameters

      +
        +
      • +
        message: string
        +

        the message to be logged

        +
      • +
      • +
        Rest ...data: any[]
      +

      Returns Promise<void>

    +
    + +
      + +
    • +

      function will send the LogLevel and message on to any +loaded ReportingPlugin objects

      +
      +
      +

      Parameters

      +
        +
      • +
        level: "trace" | "debug" | "info" | "step" | "warn" | "pass" | "fail" | "error" | "none"
        +

        the LogLevel of this message

        +
      • +
      • +
        message: string
        +

        the string to be logged

        +
      • +
      • +
        Rest ...data: any[]
        +

        an array of additional data to be included in the logs

        +
      +

      Returns Promise<void>

    +
    + +
      + +
    • +

      calls the log function with a LogLevel of pass

      +
      +
      +

      Parameters

      +
        +
      • +
        message: string
        +

        the message to be logged

        +
      • +
      • +
        Rest ...data: any[]
      +

      Returns Promise<void>

    +
    + +
      + +
    • +

      calls the log function with a LogLevel of step

      +
      +
      +

      Parameters

      +
        +
      • +
        message: string
        +

        the message to be logged

        +
      • +
      • +
        Rest ...data: any[]
      +

      Returns Promise<void>

    +
    + +
      + +
    • +

      function will send the passed in TestResult to any loaded IResultsPlugin implementations +allowing them to process the result

      +
      +
      +

      Parameters

      +
        +
      • +
        result: TestResult
        +

        a TestResult object to be sent

        +
      +

      Returns Promise<void>

    +
    + +
      + +
    • +

      calls the log function with a LogLevel of trace

      +
      +
      +

      Parameters

      +
        +
      • +
        message: string
        +

        the message to be logged

        +
      • +
      • +
        Rest ...data: any[]
      +

      Returns Promise<void>

    +
    + +
      + +
    • +

      calls the log function with a LogLevel of warn

      +
      +
      +

      Parameters

      +
        +
      • +
        message: string
        +

        the message to be logged

        +
      • +
      • +
        Rest ...data: any[]
      +

      Returns Promise<void>

    +
    +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/classes/aft_core.ReportingPlugin.html b/docs/classes/aft_core.ReportingPlugin.html new file mode 100644 index 00000000..7e0154ac --- /dev/null +++ b/docs/classes/aft_core.ReportingPlugin.html @@ -0,0 +1,260 @@ +ReportingPlugin | automated-functional-testing
    +
    + +
    +
    +
    + +
    +

    class to be extended by any Plugin implementation

    +
    +
    +

    Hierarchy

    +
    +
    +
    +
    + +
    +
    +

    Constructors

    +
    +
    +

    Accessors

    +
    +
    +

    Methods

    +
    +
    +

    Constructors

    +
    + +
    +
    +

    Accessors

    +
    + +
    +
    + +
    +
    + +
    +
    + +
      +
    • get logLevel(): "trace" | "debug" | "info" | "step" | "warn" | "pass" | "fail" | "error" | "none"
    • +
    • +

      allows for filtering out of erroneous information from logs by assigning +values to different types of logging. the purpose of each log level is +as follows:

      +
        +
      • trace - used when logging low-level debug events that occur within a loop
      • +
      • debug - used for debug logging that does not run within a loop or at a high frequency
      • +
      • info - used for informational events providing current state of a system
      • +
      • step - used within a test to denote where within the test steps we are
      • +
      • warn - used for unexpected errors that are recoverable
      • +
      • pass - used to indicate the success of a test expectation or assertion
      • +
      • fail - used to indicate the failure of a test expectation or assertion
      • +
      • error - used for unexpected errors that are not recoverable
      • +
      • none - used when no logging is desired (disables logging)
      • +
      +
      +

      Returns "trace" | "debug" | "info" | "step" | "warn" | "pass" | "fail" | "error" | "none"

    +
    +

    Methods

    +
    + +
      + +
    • +

      called by the parent Reporter before terminating to allow each plugin to +finalise any deferred logging actions

      +
      +
      +

      Parameters

      +
        +
      • +
        name: string
        +

        the name of the Reporter instance calling finalise

        +
      +

      Returns Promise<void>

    +
    + +
      + +
    • +

      called by the parent Reporter on load to allow any plugins to configure +themselves for a new logger

      +
      +
      +

      Parameters

      +
        +
      • +
        logName: string
        +

        the name of the Reporter instance calling dispose

        +
      +

      Returns Promise<void>

    +
    + +
      + +
    • +

      used for reporting message strings. this function would be called often

      +
      +
      +

      Parameters

      +
        +
      • +
        name: string
      • +
      • +
        level: "trace" | "debug" | "info" | "step" | "warn" | "pass" | "fail" | "error" | "none"
      • +
      • +
        message: string
        +

        the LogMessageData to be logged by this plugin

        +
      • +
      • +
        Rest ...data: any[]
      +

      Returns Promise<void>

    +
    + +
    +
    +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/classes/aft_core.ReportingPluginConfig.html b/docs/classes/aft_core.ReportingPluginConfig.html new file mode 100644 index 00000000..1315c200 --- /dev/null +++ b/docs/classes/aft_core.ReportingPluginConfig.html @@ -0,0 +1,116 @@ +ReportingPluginConfig | automated-functional-testing
    +
    + +
    +
    +
    + +
    +

    Hierarchy

    +
    +
    +
    +
    + +
    +
    +

    Constructors

    +
    +
    +

    Properties

    +
    +
    +

    Constructors

    +
    + +
    +
    +

    Properties

    +
    + +
    enabled: boolean = false
    +
    + +
    logLevel: "trace" | "debug" | "info" | "step" | "warn" | "pass" | "fail" | "error" | "none"
    +
    +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/classes/aft_core.Retry.html b/docs/classes/aft_core.Retry.html index 5388682e..b6bd6fe7 100644 --- a/docs/classes/aft_core.Retry.html +++ b/docs/classes/aft_core.Retry.html @@ -32,7 +32,7 @@

    Implements

    • PromiseLike<T>
    +
  • Defined in aft-core/src/helpers/retry.ts:10
  • @@ -44,50 +44,42 @@

    Constructors

    Properties

    -

    Accessors

    -

    Methods

    @@ -95,7 +87,7 @@

    Constructors

      - +
    • Type Parameters

      @@ -106,128 +98,91 @@

      T

    Parameters

    • -
      retryable: Func<void, T | PromiseLike<T>>
    +
    retryable: Func<void, T | PromiseLike<T>>
    +
  • +
    Optional aftCfg: AftConfig
  • Returns Retry<T>

    +
  • Defined in aft-core/src/helpers/retry.ts:28
  • Properties

    +
    + +
    _aftCfg: AftConfig
    - -
    #backOffType: RetryBackOffType
    +
  • Defined in aft-core/src/helpers/retry.ts:16
  • - -
    #condition: Func<T, boolean | PromiseLike<boolean>>
    +
  • Defined in aft-core/src/helpers/retry.ts:14
  • - -
    #currentDelay: number
    +
  • Defined in aft-core/src/helpers/retry.ts:20
  • - -
    #delay: number
    +
  • Defined in aft-core/src/helpers/retry.ts:15
  • - -
    #err: any
    +
  • Defined in aft-core/src/helpers/retry.ts:26
  • - -
    #failAction: Func<void, any>
    +
  • Defined in aft-core/src/helpers/retry.ts:25
  • - -
    #maxAttempts: number
    +
  • Defined in aft-core/src/helpers/retry.ts:17
  • - -
    #maxDuration: number
    +
  • Defined in aft-core/src/helpers/retry.ts:18
  • - -
    #reject: boolean
    +
  • Defined in aft-core/src/helpers/retry.ts:19
  • - -
    #result: T
    +
  • Defined in aft-core/src/helpers/retry.ts:21
  • - -
    #retryable: Func<void, T | PromiseLike<T>>
    +
  • Defined in aft-core/src/helpers/retry.ts:12
  • - -
    #success: boolean
    +
  • Defined in aft-core/src/helpers/retry.ts:22
  • - -
    #totalAttempts: number
    +
  • Defined in aft-core/src/helpers/retry.ts:23
  • - -
    #totalDuration: number
    +
  • Defined in aft-core/src/helpers/retry.ts:24
  • Accessors

    -
    - -
    -
    - -
      -
    • get condition(): Func<T, boolean | PromiseLike<boolean>>
    • -
    • -

      a Func<T, boolean | PromiseLike<boolean> (function accepting an argument of type T -and returning a boolean result) that is used to determine if the retryable is successful

      -
      -

      Returns Func<T, boolean | PromiseLike<boolean>>

    -
    - -
      -
    • get currentDelay(): number
    • -
    • -

      the millisecond delay amount most recently used (or to be used) between -retry attempts

      -
      -

      Returns number

    -
    - -
      -
    • get failAction(): Func<void, any>
    • -
    • -

      a Func<void, any> to call each time the retryable does not succeed -(defaults to undefined). call withFailAction(func) to specify a value

      -
      -

      Returns Func<void, any>

    +
  • Defined in aft-core/src/helpers/retry.ts:80
    • get lastError(): any
    • -

      the last error returned by the retryable (if any)

      +

      the last error returned by the retryable (if any). this can be used if +RetryConfig.rejectOnFail is set to false

      Returns any

    -
    - -
      -
    • get maxAttempts(): number
    • -
    • -

      the maximum number of retries to attempt before giving up (defaults to Infinity). -call withMaxAttempts(number) to specify a value

      -
      -

      Returns number

    -
    - -
      -
    • get maxDuration(): number
    • -
    • -

      a maximum amount of time to call the retryable if it is not successful -(defaults to Infinity). call withMaxDuration(number) to specify a value

      -
      -

      Returns number

    -
    - -
      -
    • get reject(): boolean
    • -
    • -

      a boolean indicating if a rejected promise should be returned if the retryable -does not successfully pass the condition within either the maximum number of -attempts or duration specified (default is true). call rejectIfUnsuccessful(false) -to change the default behaviour to resolve the promise with undefined instead

      -
      -

      Returns boolean

    +
  • Defined in aft-core/src/helpers/retry.ts:61
    • get result(): T
    • -

      the last result returned by the retryable or undefined

      +

      the last result returned by the retryable or undefined. this can be used +if RetryConfig.rejectOnFail is set to false

      Returns T

    -
    - -
      -
    • get retryable(): Func<void, T | PromiseLike<T>>
    • -
    • -

      the Func<void, T | PromiseLike<T>> to call until it's return -value passes the condition

      -
      -

      Returns Func<void, T | PromiseLike<T>>

    -
    - -
      -
    • get startDelay(): number
    • -
    • -

      the starting amount to delay between retries (defaults to 1ms). -call withStartDelayBetweenAttempts(number) to specify a value

      -
      -

      Returns number

    +
  • Defined in aft-core/src/helpers/retry.ts:45
    • get totalAttempts(): number
    • -

      the total number of attempts actually executed at the time this is called

      +

      the total number of attempts actually executed at the time this is called. this +can be used if RetryConfig.rejectOnFail is set to false

      Returns number

    +
  • Defined in aft-core/src/helpers/retry.ts:53
    • get totalDuration(): number
    • the total amount of time spent calling the retryable until it succeeded -or reached the maximum duration or number of attempts

      +or reached the maximum duration or number of attempts. this can be used if +RetryConfig.rejectOnFail is set to false

      Returns number

    +
  • Defined in aft-core/src/helpers/retry.ts:70
  • Methods

    @@ -347,11 +250,11 @@
    -
    - -
    +
    + +
      +
    • tests the passed in result against the specified condition to determine if it succeeds

      @@ -368,30 +271,7 @@
      result: T

    Returns Promise<boolean>

    -
    - -
      - -
    • -

      allows for specifying false if the last result should be returned if the retryable -cannot successfully pass the condition instead of returning a rejected promise

      - -

      Returns

      true if a rejected promise is returned on failure or false if a -resolved promise of the last result should be returned instead

      -
      -
      -

      Parameters

      -
        -
      • -
        enable: boolean
        -

        a boolean indicating if a rejected promise should be returned -if the retryable is unable to successfully pass the condition within either -the maximum number of attempts or duration specified (default is true)

        -
      -

      Returns Retry<T>

    +
  • Defined in aft-core/src/helpers/retry.ts:139
  • +
  • Defined in aft-core/src/helpers/retry.ts:145
    • @@ -457,27 +337,33 @@
      condition:

    Returns Retry<T>

    +
  • Defined in aft-core/src/helpers/retry.ts:91
    • -

      allows for specifying a RetryBackOffType used to calculate the delay between attempts -(default is constant which will continually use the value specified for startDelay)

      - -

      Returns

      the current Retry<T> instance

      -

      Parameters

      • -
        backOffType: RetryBackOffType
        -

        a RetryBackOffType used to calculate the delay between attempts

        -
      +
      backOffType: RetryBackOffType
    +

    Returns Retry<T>

    +
    + +
    +
  • Defined in aft-core/src/helpers/retry.ts:96
    • @@ -497,68 +383,46 @@
      func:

    Returns Retry<T>

    +
  • Defined in aft-core/src/helpers/retry.ts:127
    • - +
    • -

      allows for specifying a limit to the number of retry attempts

      - -

      Returns

      the current Retry<T> instance

      -

      Parameters

      • -
        maxAttempts: number
        -

        the maximum number of times to call the retryable

        -
      +
      attempts: number

    Returns Retry<T>

    +
  • Defined in aft-core/src/helpers/retry.ts:111
    • - +
    • -

      allows for specifying the maximum number of milliseconds to wait for -the retryable to return a value that passes the condition (defaults -to Infinity)

      - -

      Returns

      the current Retry<T> instance

      -

      Parameters

      • -
        durationMs: number
        -

        the maximum number of milliseconds to wait for the -retryable to succeed

        -
      +
      milliseconds: number

    Returns Retry<T>

    -
    - +
  • Defined in aft-core/src/helpers/retry.ts:106
  • +
    +
      - +
    • -

      allows for specifying a starting number of milliseconds to delay between retry -attempts (defaults to 1ms)

      - -

      Returns

      the current Retry<T> instance

      -

      Parameters

      • -
        delayMs: number
        -

        the starting number of milliseconds to delay between attempts

        -
      +
      reject: boolean

    Returns Retry<T>

    +
  • Defined in aft-core/src/helpers/retry.ts:116
    • @@ -567,7 +431,7 @@
    +
  • Defined in aft-core/src/helpers/retry.ts:205
  • Generated using TypeDoc

    diff --git a/docs/classes/aft_core.TestCaseManager.html b/docs/classes/aft_core.TestCaseManager.html deleted file mode 100644 index 1ecadd00..00000000 --- a/docs/classes/aft_core.TestCaseManager.html +++ /dev/null @@ -1,298 +0,0 @@ -TestCaseManager | automated-functional-testing
    -
    - -
    -
    -
    - -
    -

    loads and provides access to a TestCasePlugin for use in conditional test execution and filtering. -to specify a plugin use the following aftconfig.json key:

    -
    {
    ...
    "TestCaseManager": {
    "plugins": [
    {"name": "test-case-plugin", "options": {"username": "foo@bar.com", "accesskey": "SuperSecretKey"}}
    ]
    }
    ...
    } -
    -
    -
    -

    Hierarchy

    -
    -
    -
    -
    - -
    -
    -

    Constructors

    -
    - -
    -
    -

    Methods

    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/classes/aft_core.TestCasePlugin.html b/docs/classes/aft_core.TestCasePlugin.html deleted file mode 100644 index 7200f5cb..00000000 --- a/docs/classes/aft_core.TestCasePlugin.html +++ /dev/null @@ -1,200 +0,0 @@ -TestCasePlugin | automated-functional-testing
    -
    - -
    -
    -
    -
    - -

    Class TestCasePlugin<T>Abstract

    -
    -

    interface to be implemented by any Plugin implementation

    -
    -
    -

    Type Parameters

    -
    -
    -

    Hierarchy

    -
    -
    -
    -
    - -
    -
    -

    Constructors

    -
    -
    -

    Accessors

    -
    -
    -

    Methods

    -
    -
    -

    Constructors

    -
    - -
    -
    -

    Accessors

    -
    - -
    -
    -

    Methods

    -
    - -
    -
    - -
    -
    - -
      - -
    • -
      -

      Type Parameters

      -
        -
      • -

        K extends string | number | symbol

      • -
      • -

        V

      -
      -

      Parameters

      -
        -
      • -
        key: K
      • -
      • -
        Optional defaultVal: V
      -

      Returns V

    -
    - -
    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/classes/aft_core.TestExecutionPolicyManager.html b/docs/classes/aft_core.TestExecutionPolicyManager.html new file mode 100644 index 00000000..ddafe10e --- /dev/null +++ b/docs/classes/aft_core.TestExecutionPolicyManager.html @@ -0,0 +1,165 @@ +TestExecutionPolicyManager | automated-functional-testing
    +
    + +
    +
    +
    +
    + +

    Class TestExecutionPolicyManager

    +
    +

    Hierarchy

    +
      +
    • TestExecutionPolicyManager
    +
    +
    +
    + +
    +
    +

    Constructors

    +
    +
    +

    Properties

    +
    +
    +

    Methods

    +
    +
    +

    Constructors

    +
    + +
    +
    +

    Properties

    +
    + +
    _aftLogger: AftLogger
    +
    + +
    aftCfg: AftConfig
    +
    + +
    +
    +

    Methods

    +
    + +
    +
    + +
      + +
    • +

      iterates over all enabled ITestExecutionPolicyPlugin implementations calling shouldRun +and if any of the results return false then a ShouldRunResult containing false +and a reason comprised of all plugin reasons will be returned, otherwise true

      + +

      Returns

      a ShouldRunResult containing shouldRun=true if test should be run +otherwise false and a reason stating why

      +
      +
      +

      Parameters

      +
        +
      • +
        testId: string
        +

        the test case id to check

        +
      +

      Returns Promise<ProcessingResult<boolean>>

    +
    +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/classes/aft_core.TestExecutionPolicyPlugin.html b/docs/classes/aft_core.TestExecutionPolicyPlugin.html new file mode 100644 index 00000000..da2dfda3 --- /dev/null +++ b/docs/classes/aft_core.TestExecutionPolicyPlugin.html @@ -0,0 +1,164 @@ +TestExecutionPolicyPlugin | automated-functional-testing
    +
    + +
    +
    +
    +
    + +

    Class TestExecutionPolicyPlugin

    +
    +

    class to be extended by any Plugin implementation

    +
    +
    +

    Hierarchy

    +
      +
    • Plugin +
        +
      • TestExecutionPolicyPlugin
    +
    +
    +
    + +
    +
    +

    Constructors

    +
    +
    +

    Accessors

    +
    +
    +

    Methods

    +
    +
    +

    Constructors

    +
    + +
    +
    +

    Accessors

    +
    + +
    +
    + +
    +
    + +
    +
    +

    Methods

    +
    + +
    +
    +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/classes/aft_core.Verifier.html b/docs/classes/aft_core.Verifier.html index 6fc1211b..944e84b6 100644 --- a/docs/classes/aft_core.Verifier.html +++ b/docs/classes/aft_core.Verifier.html @@ -16,10 +16,10 @@

    Class Verifier

    class to be used for executing some Functional Test Assertion after checking with any -TestCasePlugin and DefectPlugin instances that have been loaded to confirm that the -assertion should be executed based on referenced Test ID(s) or Defect ID(s)

    +TestExecutionPolicyPlugin instances that have been loaded to confirm that the +assertion should be executed based on referenced Test ID(s)

    Ex:

    -
    await verify(async (v: Verifier) => {
    await v.logMgr.info('doing some testing...');
    let feature = new FeatureObj();
    return await feature.returnExpectedValue();
    }).withDescription('example usage for Verifier')
    .and.withTestIds('C1234') // if TestCasePlugin.shouldRun('C1234') returns `false` the assertion is not run
    .and.withKnownDefectIds('AUTO-123') // if DefectPlugin.getDefect('AUTO-123').status === 'open' the assertion is not run
    .returns('expected value'); +
    await verify(async (v: Verifier) => {
    await v.reporter.info('doing some testing...');
    let feature = new FeatureObj();
    return await feature.returnExpectedValue();
    }).withDescription('example usage for Verifier')
    .and.withTestIds('C1234') // if TestExecutionPolicyPlugin.shouldRun('C1234') returns `false` the assertion is not run
    .returns('expected value');

    Param

    the Func<Verifier, any> function to be executed by this Verifier

    @@ -35,7 +35,7 @@

    Implements

    • PromiseLike<void>
    +
  • Defined in aft-core/src/verification/verifier.ts:34
  • @@ -47,25 +47,26 @@

    Constructors

    Properties

    -

    Accessors

    -

    Methods

    @@ -75,17 +76,12 @@

    Methods

    _logMessage _logResult _resolveAssertion -_shouldRun_defects -_shouldRun_tests +on returns +shouldRun then verify -withBuildInfoManager -withDefectManager withDescription -withKnownDefectIds -withLogManager -withTestCaseManager withTestIds
    @@ -97,66 +93,74 @@
    +
  • Defined in aft-core/src/verification/verifier.ts:47
  • Properties

    +
    + +
    _actionMap: Map<VerifierEvent, Action<void>>
    +
    + +
    _aftCfg?: AftConfig
    _assertion: Func<Verifier, any>
    -
    - -
    _buildMgr: BuildInfoManager
    -
    - -
    _defectMgr: DefectManager
    -
    - -
    _defects: Set<string>
    +
    + +
    _buildInfoMgr: BuildInfoManager
    +
  • Defined in aft-core/src/verification/verifier.ts:44
  • _description: string
    +
  • Defined in aft-core/src/verification/verifier.ts:38
  • _innerPromise: Promise<void>
    -
    - -
    _logMgr: LogManager
    +
  • Defined in aft-core/src/verification/verifier.ts:40
  • _matcher: VerifierMatcher
    +
  • Defined in aft-core/src/verification/verifier.ts:37
  • +
    + +
    +
    + +
    _reporter: Reporter
    _startTime: number
    -
    - -
    _testMgr: TestCaseManager
    +
    + +
    _testIds: Set<string>
    -
    - -
    _tests: Set<string>
    +
  • Defined in aft-core/src/verification/verifier.ts:41
  • Accessors

    +
    + +
    -
    - +
  • Defined in aft-core/src/verification/verifier.ts:154
  • +
    +
    -
    - +
  • Defined in aft-core/src/verification/verifier.ts:88
  • +
    +
    -
    - +
  • Defined in aft-core/src/verification/verifier.ts:244
  • +
    +
    +
    + +
      +
    • get reporter(): Reporter
    • +
    • +

      a Reporter that uses either the Description or a list of Test Ids or a uuid as the logName depending on which is available (NOTE: description is preferred most and will be used if other values are also present)

      -

      Returns LogManager

    -
    - -
    +
  • Defined in aft-core/src/verification/verifier.ts:66
  • Methods

    @@ -222,7 +233,7 @@
    logMessage: string
    Optional testId: string

    Returns Promise<TestResult>

    +
  • Defined in aft-core/src/verification/verifier.ts:389
    • @@ -239,7 +250,7 @@
      logMessage: string
      Rest ...testIds: string[]

    Returns Promise<TestResult[]>

    +
  • Defined in aft-core/src/verification/verifier.ts:374
  • +
  • Defined in aft-core/src/verification/verifier.ts:100
  • Returns Promise<void>

    +
  • Defined in aft-core/src/verification/verifier.ts:355
    • creates TestResult objects for each testId and sends these -to the LogManager.logResult function

      +to the Reporter.logResult function

      Parameters

      @@ -280,7 +291,7 @@
      status: Optional message: string

    Returns Promise<void>

    +
  • Defined in aft-core/src/verification/verifier.ts:326
  • -
    - -
    +
    + +
    -
    - - +

    Returns Verifier

    +
  • Defined in aft-core/src/verification/verifier.ts:164
    • @@ -336,7 +344,20 @@
      result: any

    Returns Verifier

    +
  • Defined in aft-core/src/verification/verifier.ts:228
  • +
    + +
    +
  • Defined in aft-core/src/verification/verifier.ts:95
  • Returns Verifier

    -
    - -
    -
    - -
    +
  • Defined in aft-core/src/verification/verifier.ts:185
    • @@ -464,67 +445,7 @@
      description: string

    Returns Verifier

    -
    - -
      - -
    • -

      allows for setting a defectId to be checked before executing the assertion. -if the referenced defectId is open then the assertion will not be run.

      - -

      Returns

      this Verifier instance

      -
      -
      -

      Parameters

      -
        -
      • -
        Rest ...defectIds: string[]
        -

        a defect identifier for your connected DefectPlugin

        -
      -

      Returns Verifier

    -
    - -
    -
    - -
    +
  • Defined in aft-core/src/verification/verifier.ts:196
  • +
  • Defined in aft-core/src/verification/verifier.ts:211
  • Generated using TypeDoc

    diff --git a/docs/classes/aft_jasmine_reporter.AftJasmineReporter.html b/docs/classes/aft_jasmine_reporter.AftJasmineReporter.html index 58f31482..e9bbf7be 100644 --- a/docs/classes/aft_jasmine_reporter.AftJasmineReporter.html +++ b/docs/classes/aft_jasmine_reporter.AftJasmineReporter.html @@ -23,7 +23,7 @@

    Implements

    • CustomReporter
    +
  • Defined in aft-jasmine-reporter/src/aft-jasmine-reporter.ts:4
  • @@ -54,19 +54,19 @@
    +
  • Defined in aft-jasmine-reporter/src/aft-jasmine-reporter.ts:8
  • Properties

    _async2Sync: Promise<any>[]
    +
  • Defined in aft-jasmine-reporter/src/aft-jasmine-reporter.ts:5
  • _testNames: FileSystemMap<string, any>
    +
  • Defined in aft-jasmine-reporter/src/aft-jasmine-reporter.ts:6
  • Methods

    @@ -81,7 +81,7 @@

    Parameters

    result: SpecResult

    Returns Promise<void>

    +
  • Defined in aft-jasmine-reporter/src/aft-jasmine-reporter.ts:32
  • +
  • Defined in aft-jasmine-reporter/src/aft-jasmine-reporter.ts:13
    • @@ -104,7 +104,7 @@
      result: SpecResult
    Returns void
    +
  • Defined in aft-jasmine-reporter/src/aft-jasmine-reporter.ts:28
    • @@ -118,7 +118,7 @@
      result: SpecResult
    Returns void
    +
  • Defined in aft-jasmine-reporter/src/aft-jasmine-reporter.ts:24
  • Properties

    -

    Accessors

    -

    Constructors

      - +
    • Parameters

      • -
        Optional scope: any
      +
      Optional scope: any
    • +
    • +
      Optional aftCfg: AftConfig

    Returns AftLog

    +
  • Defined in aft-jasmine-reporter/src/aft-log.ts:9
  • Properties

    -
    - -
    _logMgr: LogManager
    _testNames: FileSystemMap<string, any>
    +
  • Defined in aft-jasmine-reporter/src/aft-log.ts:6
  • test: SpecResult
    +
  • Defined in aft-jasmine-reporter/src/aft-log.ts:7
  • Accessors

    +
    + +
    -
    - +
  • Defined in aft-jasmine-reporter/src/aft-log.ts:22
  • +
    +
    +
  • Defined in aft-jasmine-reporter/src/aft-log.ts:34
  • +
  • reporter
  • Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/classes/aft_jasmine_reporter.AftTest.html b/docs/classes/aft_jasmine_reporter.AftTest.html index 3412475d..2770b7be 100644 --- a/docs/classes/aft_jasmine_reporter.AftTest.html +++ b/docs/classes/aft_jasmine_reporter.AftTest.html @@ -25,7 +25,7 @@

    Hierarchy

    • AftTest
    +
  • Defined in aft-jasmine-reporter/src/aft-test.ts:9
  • @@ -37,21 +37,23 @@

    Constructors

    Properties

    -

    Accessors

    -

    Methods

    Constructors

      - +
    • expects to be passed the scope from an executing Mocha test (i.e. the this argument)

      @@ -76,39 +79,50 @@

      Parameters

    • Optional scope: any

      the this scope from within a Mocha it

      -
    + +
  • +
    Optional aftCfg: AftConfig
  • Returns AftTest

    +
  • Defined in aft-jasmine-reporter/src/aft-test.ts:18
  • Properties

    -
    - -
    _defects: string[]
    _testcases: string[]
    +
  • Defined in aft-jasmine-reporter/src/aft-test.ts:10
  • test: SpecResult
    +
  • Defined in aft-jasmine-reporter/src/aft-log.ts:7
  • Accessors

    -
    - +
    + +
    +
    +
    +
  • Defined in aft-jasmine-reporter/src/aft-test.ts:23
  • -
    - +
  • Defined in aft-jasmine-reporter/src/aft-log.ts:22
  • +
    +
      -
    • get logMgr(): LogManager
    • +
    • get reporter(): Reporter
    • -

      Returns LogManager

    +
  • Defined in aft-jasmine-reporter/src/aft-log.ts:34
  • +
  • Defined in aft-jasmine-reporter/src/aft-test.ts:27
  • Methods

    @@ -153,7 +167,7 @@
    logMessage: string
    Optional testId: string

    Returns Promise<TestResult>

    +
  • Defined in aft-jasmine-reporter/src/aft-test.ts:156
    • @@ -170,7 +184,25 @@
      logMessage: string
      Rest ...testIds: string[]

    Returns Promise<TestResult[]>

    +
  • Defined in aft-jasmine-reporter/src/aft-test.ts:141
  • +
    + +
      + +
    • +
      +

      Type Parameters

      +
        +
      • +

        T extends Verifier<T>

      +
      +

      Parameters

      +
        +
      • +
        Optional verifierType: Class<T>
      +

      Returns T

      @@ -185,14 +217,14 @@
      status: TestStatus
      Optional message: string

    Returns Promise<void>

    +
  • Defined in aft-jasmine-reporter/src/aft-test.ts:122
    • creates ITestResult objects for each testId and sends these -to the LogManager.logResult function

      +to the Reporter.logResult function

      Parameters

      @@ -203,7 +235,7 @@
      status: TestStatus
    • Optional message: string

    Returns Promise<void>

    +
  • Defined in aft-jasmine-reporter/src/aft-test.ts:93
  • +
  • Defined in aft-jasmine-reporter/src/aft-test.ts:83
  • +
  • Defined in aft-jasmine-reporter/src/aft-test.ts:38
  • +
  • Defined in aft-jasmine-reporter/src/aft-test.ts:34
  • +
  • Defined in aft-jasmine-reporter/src/aft-test.ts:46
    • +

      determines if any of the referenced Test Case ID's should be run according to the +loaded TestExecutionPolicyPlugin implementations' shouldRun methods

      + +

      Returns

      true if test should be run, otherwise false

      +

      Returns Promise<boolean>

    +
  • Defined in aft-jasmine-reporter/src/aft-test.ts:55
  • +
    + +
      + +
    • +

      creates a new {Verifier} that will run the passed in assertion if the shouldRun function +returns true otherwise it will bypass execution

      + +

      Returns

      a {Verifier} instance already configured with test cases, description, logger and config

      +
      +
      +

      Type Parameters

      +
        +
      • +

        T extends Verifier<T>

      +
      +

      Parameters

      +
        +
      • +
        assertion: Func<T, any>
        +

        a function that performs test actions and will accept a {Verifier} instance +for use during the test actions' execution

        +
      • +
      • +
        Optional verifierType: Class<T>
        +

        an optional {Verifier} class to use instead of the base {Verifier} type

        +
      +

      Returns T

    +
  • shouldRun
  • +
  • verify
  • Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/classes/aft_logging_filesystem.FilesystemLoggingPlugin.html b/docs/classes/aft_logging_filesystem.FilesystemLoggingPlugin.html deleted file mode 100644 index f37c229f..00000000 --- a/docs/classes/aft_logging_filesystem.FilesystemLoggingPlugin.html +++ /dev/null @@ -1,306 +0,0 @@ -FilesystemLoggingPlugin | automated-functional-testing
    -
    - -
    -
    -
    - -
    -

    Hierarchy

    -
    -
    -
    -
    - -
    -
    -

    Constructors

    -
    - -
    -
    -

    Properties

    -
    - -
    _dateFormat: string
    -
    - -
    _includeResults: boolean
    -
    - -
    _outputPath: string
    -
    -

    Accessors

    -
    - -
    -
    - -
      -
    • get enabled(): boolean
    • -
    • -

      Returns boolean

    -
    - -
    -
    - -
      -
    • get level(): "trace" | "debug" | "info" | "step" | "warn" | "pass" | "fail" | "error" | "none"
    • -
    • -

      allows for filtering out of erroneous information from logs by assigning -values to different types of logging. the purpose of each log level is -as follows:

      -
        -
      • trace - used when logging low-level debug events that occur within a loop
      • -
      • debug - used for debug logging that does not run within a loop or at a high frequency
      • -
      • info - used for informational events providing current state of a system
      • -
      • step - used within a test to denote where within the test steps we are
      • -
      • warn - used for unexpected errors that are recoverable
      • -
      • pass - used to indicate the success of a test expectation or assertion
      • -
      • fail - used to indicate the failure of a test expectation or assertion
      • -
      • error - used for unexpected errors that are not recoverable
      • -
      • none - used when no logging is desired (disables logging)
      • -
      -
      -

      Returns "trace" | "debug" | "info" | "step" | "warn" | "pass" | "fail" | "error" | "none"

    -
    - -
    -
    -

    Methods

    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
      - -
    • -
      -

      Type Parameters

      -
        -
      • -

        K extends "enabled" | "outputPath" | "level" | "includeResults" | "dateFormat"

      • -
      • -

        V extends string | boolean

      -
      -

      Parameters

      -
        -
      • -
        key: K
      • -
      • -
        Optional defaultVal: V
      -

      Returns V

    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/classes/aft_logging_html.HtmlLoggingPlugin.html b/docs/classes/aft_logging_html.HtmlLoggingPlugin.html deleted file mode 100644 index 1edb3161..00000000 --- a/docs/classes/aft_logging_html.HtmlLoggingPlugin.html +++ /dev/null @@ -1,328 +0,0 @@ -HtmlLoggingPlugin | automated-functional-testing
    -
    - -
    -
    -
    - -
    -

    Hierarchy

    -
    -
    -
    -
    - -
    -
    -

    Constructors

    -
    -
    -

    Properties

    -
    -
    -

    Accessors

    -
    -
    -

    Methods

    -
    -
    -

    Constructors

    -
    - -
    -
    -

    Properties

    -
    - -
    _logs: FileSystemMap<string, string[]>
    -
    - -
    _results: FileSystemMap<string, HtmlTestResult[]>
    -
    -

    Accessors

    -
    - -
      -
    • get enabled(): boolean
    • -
    • -

      Returns boolean

    -
    - -
    -
    - -
    -
    - -
      -
    • get level(): "trace" | "debug" | "info" | "step" | "warn" | "pass" | "fail" | "error" | "none"
    • -
    • -

      allows for filtering out of erroneous information from logs by assigning -values to different types of logging. the purpose of each log level is -as follows:

      -
        -
      • trace - used when logging low-level debug events that occur within a loop
      • -
      • debug - used for debug logging that does not run within a loop or at a high frequency
      • -
      • info - used for informational events providing current state of a system
      • -
      • step - used within a test to denote where within the test steps we are
      • -
      • warn - used for unexpected errors that are recoverable
      • -
      • pass - used to indicate the success of a test expectation or assertion
      • -
      • fail - used to indicate the failure of a test expectation or assertion
      • -
      • error - used for unexpected errors that are not recoverable
      • -
      • none - used when no logging is desired (disables logging)
      • -
      -
      -

      Returns "trace" | "debug" | "info" | "step" | "warn" | "pass" | "fail" | "error" | "none"

    -
    - -
    -
    - -
    -
    -

    Methods

    -
    - -
    -
    - -
      - -
    • -
      -

      Parameters

      -
        -
      • -
        logName: string
      • -
      • -
        Optional error: Error
      -

      Returns Promise<void>

    -
    - -
    -
    - -
      - -
    • -
      -

      Parameters

      -
        -
      • -
        logName: string
      • -
      • -
        result: TestResult
      -

      Returns Promise<void>

    -
    - -
    -
    - -
      - -
    • -
      -

      Type Parameters

      -
        -
      • -

        K extends "enabled" | "fileName" | "level" | "outputDir" | "maxLogLines"

      • -
      • -

        V extends string | number | boolean

      -
      -

      Parameters

      -
        -
      • -
        key: K
      • -
      • -
        Optional defaultVal: V
      -

      Returns V

    -
    - -
    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/classes/aft_mocha_reporter.AftLog.html b/docs/classes/aft_mocha_reporter.AftLog.html index 20aa6b62..c9dc31d8 100644 --- a/docs/classes/aft_mocha_reporter.AftLog.html +++ b/docs/classes/aft_mocha_reporter.AftLog.html @@ -21,7 +21,7 @@

    Hierarchy

    +
  • Defined in aft-mocha-reporter/src/aft-log.ts:3
  • @@ -33,13 +33,14 @@

    Constructors

    Properties

    -

    Accessors

    Methods

    @@ -50,28 +51,35 @@

    Constructors

      - +
    • Parameters

      • -
        Optional scope: any
      +
      Optional scope: any
    • +
    • +
      Optional aftCfg: AftConfig

    Returns AftLog

    +
  • Defined in aft-mocha-reporter/src/aft-log.ts:9
  • Properties

    -
    - -
    _logMgr: LogManager
    test: Test
    +
  • Defined in aft-mocha-reporter/src/aft-log.ts:6
  • Accessors

    @@ -81,15 +89,15 @@
    -
    - +
  • Defined in aft-mocha-reporter/src/aft-log.ts:14
  • +
    +
    +
  • Defined in aft-mocha-reporter/src/aft-log.ts:22
  • Methods

    @@ -99,7 +107,7 @@
    +
  • Defined in aft-mocha-reporter/src/aft-log.ts:29
  • Generated using TypeDoc

    diff --git a/docs/classes/aft_mocha_reporter.AftMochaReporter.html b/docs/classes/aft_mocha_reporter.AftMochaReporter.html index 2b88e249..7819826b 100644 --- a/docs/classes/aft_mocha_reporter.AftMochaReporter.html +++ b/docs/classes/aft_mocha_reporter.AftMochaReporter.html @@ -25,7 +25,7 @@

    Hierarchy

    • AftMochaReporter
    +
  • Defined in aft-mocha-reporter/src/aft-mocha-reporter.ts:14
  • @@ -62,7 +62,7 @@
    runner: Runner

    Returns AftMochaReporter

    +
  • Defined in aft-mocha-reporter/src/aft-mocha-reporter.ts:15
  • Properties

    @@ -103,7 +103,7 @@

    Parameters

    runner: Runner

    Returns void

    +
  • Defined in aft-mocha-reporter/src/aft-mocha-reporter.ts:20
  • +
  • Defined in aft-mocha-reporter/src/aft-test.ts:9
  • @@ -37,21 +37,22 @@

    Constructors

    Properties

    -

    Accessors

    -

    Methods

    Constructors

      - +
    • expects to be passed the scope from an executing Mocha test (i.e. the this argument)

      @@ -76,39 +78,39 @@

      Parameters

    • Optional scope: any

      the this scope from within a Mocha it

      -
    + +
  • +
    Optional aftCfg: AftConfig
  • Returns AftTest

    +
  • Defined in aft-mocha-reporter/src/aft-test.ts:18
  • Properties

    -
    - -
    _defects: string[]
    - +
    _testcases: string[]
    +
  • Defined in aft-mocha-reporter/src/aft-test.ts:10
  • +
    + +
    aftCfg: AftConfig
    test: Test
    +
  • Defined in aft-mocha-reporter/src/aft-log.ts:6
  • Accessors

    -
    - -
    -
    - +
  • Defined in aft-mocha-reporter/src/aft-log.ts:14
  • +
    +
      -
    • get logMgr(): LogManager
    • +
    • get reporter(): Reporter
    • -

      Returns LogManager

    +
  • Defined in aft-mocha-reporter/src/aft-log.ts:22
    • get testcases(): string[]
    • +

      an array of test ID's parsed from the test title where test ID's +are expected to be in the surrounded by [ and ] like: "[TESTID]"

      +

      Returns string[]

    +
  • Defined in aft-mocha-reporter/src/aft-test.ts:28
  • Methods

    @@ -153,7 +158,7 @@
    logMessage: string
    Optional testId: string

    Returns Promise<TestResult>

    +
  • Defined in aft-mocha-reporter/src/aft-test.ts:148
    • @@ -170,7 +175,25 @@
      logMessage: string
      Rest ...testIds: string[]

    Returns Promise<TestResult[]>

    +
  • Defined in aft-mocha-reporter/src/aft-test.ts:133
  • +
    + +
      + +
    • +
      +

      Type Parameters

      +
        +
      • +

        T extends Verifier<T>

      +
      +

      Parameters

      +
        +
      • +
        Optional verifierType: Class<T>
      +

      Returns T

      @@ -185,14 +208,14 @@
      status: TestStatus
      Optional message: string

    Returns Promise<void>

    +
  • Defined in aft-mocha-reporter/src/aft-test.ts:114
    • creates ITestResult objects for each testId and sends these -to the LogManager.logResult function

      +to the Reporter.logResult function

      Parameters

      @@ -203,7 +226,7 @@
      status: TestStatus
    • Optional message: string

    Returns Promise<void>

    +
  • Defined in aft-mocha-reporter/src/aft-test.ts:85
  • +
  • Defined in aft-mocha-reporter/src/aft-log.ts:29
    • @@ -225,7 +248,7 @@

      Parameters

      err: any

    Returns Promise<void>

    +
  • Defined in aft-mocha-reporter/src/aft-test.ts:36
  • +
  • Defined in aft-mocha-reporter/src/aft-test.ts:32
  • +
  • Defined in aft-mocha-reporter/src/aft-test.ts:42
    • +

      determines if any of the referenced Test Case ID's should be run according to the +loaded TestExecutionPolicyPlugin implementations' shouldRun methods

      + +

      Returns

      true if test should be run, otherwise false

      +

      Returns Promise<boolean>

    +
  • Defined in aft-mocha-reporter/src/aft-test.ts:51
  • +
    + +
      + +
    • +

      creates a new {Verifier} that will run the passed in assertion if the shouldRun function +returns true otherwise it will bypass execution

      + +

      Returns

      a {Verifier} instance already configured with test cases, description, logger and config

      +
      +
      +

      Type Parameters

      +
        +
      • +

        T extends Verifier<T>

      +
      +

      Parameters

      +
        +
      • +
        assertion: Func<T, any>
        +

        a function that performs test actions and will accept a {Verifier} instance +for use during the test actions' execution

        +
      • +
      • +
        Optional verifierType: Class<T>
        +

        an optional {Verifier} class to use instead of the base {Verifier} type

        +
      +

      Returns T

    +
  • shouldRun
  • +
  • verify
  • Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/classes/aft_logging_awskinesis.KinesisLoggingPlugin.html b/docs/classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPlugin.html similarity index 51% rename from docs/classes/aft_logging_awskinesis.KinesisLoggingPlugin.html rename to docs/classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPlugin.html index 03ab26b6..3099454d 100644 --- a/docs/classes/aft_logging_awskinesis.KinesisLoggingPlugin.html +++ b/docs/classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPlugin.html @@ -1,4 +1,4 @@ -KinesisLoggingPlugin | automated-functional-testing
    +KinesisReportingPlugin | automated-functional-testing

    NOTE: this plugin accepts the following options:

    -
    {
    "level": "info",
    "accessKeyId": "your-aws-access-key-id",
    "secretAccessKey": "your-aws-secret-access-key",
    "sessionToken": "your-aws-session-token",
    "region": "us-west-1",
    "deliveryStream": "your-frehose-delivery-stream",
    "batch": true,
    "batchSize": 10
    } +
    // aftconfig.json
    {
    "KinesisReportingPluginConfig": {
    "logLevel": "info",
    "region": "us-west-1",
    "deliveryStream": "your-frehose-delivery-stream",
    "batch": true,
    "batchSize": 10
    }
    }

    NOTE: the order we obtain AWS Credentials follows the below:

    @@ -26,17 +26,17 @@

    Class KinesisLoggingPlugin

  • Shared Ini File: read from the host system
  • ECS Credentials: similar to the EC2 Metadata, but on ECS
  • Process Credentials: any credentials set on the current process
  • -
  • Options: read from passed in KinesisLoggingPluginOptions
  • +
  • Options: read from passed in KinesisReportingPluginOptions
  • Hierarchy

    @@ -44,83 +44,100 @@

    Constructors

    +

    Returns KinesisReportingPlugin

    +
  • Defined in aft-reporting-aws-kinesis-firehose/src/kinesis-reporting-plugin.ts:52
  • Properties

    -
    - -
    _buildInfoMgr: BuildInfoManager
    _client: Firehose
    +
  • Defined in aft-reporting-aws-kinesis-firehose/src/kinesis-reporting-plugin.ts:46
  • +
    + +
    _level: "trace" | "debug" | "info" | "step" | "warn" | "pass" | "fail" | "error" | "none"
    _logs: Map<string, Record[]>
    +
  • Defined in aft-reporting-aws-kinesis-firehose/src/kinesis-reporting-plugin.ts:42
  • Accessors

    -
    - -
    +
    + +
      +
    • get aftLogger(): AftLogger
    • +
    • +

      Returns AftLogger

    +
  • Defined in aft-reporting-aws-kinesis-firehose/src/kinesis-reporting-plugin.ts:81
  • +
  • Defined in aft-reporting-aws-kinesis-firehose/src/kinesis-reporting-plugin.ts:85
  • +
  • Defined in aft-reporting-aws-kinesis-firehose/src/kinesis-reporting-plugin.ts:77
    • get enabled(): boolean
    • Returns boolean

    -
    - -
      -
    • get level(): "trace" | "debug" | "info" | "step" | "warn" | "pass" | "fail" | "error" | "none"
    • +
    • Defined in aft-core/dist/src/plugins/reporting/reporting-plugin.d.ts:8
    +
    + +
      +
    • get logLevel(): "trace" | "debug" | "info" | "step" | "warn" | "pass" | "fail" | "error" | "none"
    • -

      allows for filtering out of erroneous information from logs by assigning -values to different types of logging. the purpose of each log level is -as follows:

      -
        -
      • trace - used when logging low-level debug events that occur within a loop
      • -
      • debug - used for debug logging that does not run within a loop or at a high frequency
      • -
      • info - used for informational events providing current state of a system
      • -
      • step - used within a test to denote where within the test steps we are
      • -
      • warn - used for unexpected errors that are recoverable
      • -
      • pass - used to indicate the success of a test expectation or assertion
      • -
      • fail - used to indicate the failure of a test expectation or assertion
      • -
      • error - used for unexpected errors that are not recoverable
      • -
      • none - used when no logging is desired (disables logging)
      • -
      -

      Returns "trace" | "debug" | "info" | "step" | "warn" | "pass" | "fail" | "error" | "none"

    +
  • Defined in aft-reporting-aws-kinesis-firehose/src/kinesis-reporting-plugin.ts:48
  • -
    - -
    -
    - -
    +
  • Defined in aft-reporting-aws-kinesis-firehose/src/kinesis-reporting-plugin.ts:73
  • Methods

    @@ -216,7 +202,7 @@

    Parameters

    options: CheckAndSendOptions

    Returns Promise<PutRecordBatchOutput | PutRecordOutput>

    +
  • Defined in aft-reporting-aws-kinesis-firehose/src/kinesis-reporting-plugin.ts:189
    • @@ -229,7 +215,7 @@

      Parameters

      logRecord: KinesisLogRecord

    Returns Record

    +
  • Defined in aft-reporting-aws-kinesis-firehose/src/kinesis-reporting-plugin.ts:181
    • @@ -244,7 +230,7 @@
      deliveryStream: string
      record: Record

    Returns Promise<PutRecordOutput>

    +
  • Defined in aft-reporting-aws-kinesis-firehose/src/kinesis-reporting-plugin.ts:229
    • @@ -259,7 +245,7 @@
      deliveryStream: string
      records: Record[]

    Returns Promise<PutRecordBatchOutput>

    +
  • Defined in aft-reporting-aws-kinesis-firehose/src/kinesis-reporting-plugin.ts:208
  • +
  • Defined in aft-reporting-aws-kinesis-firehose/src/kinesis-reporting-plugin.ts:63
  • -
    - +
  • Defined in aft-reporting-aws-kinesis-firehose/src/kinesis-reporting-plugin.ts:100
  • +
    +
      - +
    • Parameters

      • -
        name: string
      • -
      • -
        Optional error: Error
      +
      name: string

    Returns Promise<void>

    -
    - +
  • Defined in aft-reporting-aws-kinesis-firehose/src/kinesis-reporting-plugin.ts:174
  • +
    +
      - +
    • Parameters

      • -
        data: LogMessageData
      +
      logName: string

    Returns Promise<void>

    -
    - +
  • Defined in aft-reporting-aws-kinesis-firehose/src/kinesis-reporting-plugin.ts:124
  • +
    +
      - +
    • Parameters

      @@ -330,11 +314,15 @@

      Parameters

    • name: string
    • -
      result: TestResult
    +
    level: "trace" | "debug" | "info" | "step" | "warn" | "pass" | "fail" | "error" | "none"
    +
  • +
    message: string
  • +
  • +
    Rest ...data: any[]
  • Returns Promise<void>

    +
  • Defined in aft-reporting-aws-kinesis-firehose/src/kinesis-reporting-plugin.ts:132
    • @@ -349,30 +337,27 @@
      key: string
      Optional val: Record[]

    Returns Record[]

    -
    - -
    +
    + +
      +
    • -
      -

      Type Parameters

      -
        -
      • -

        K extends "enabled" | "buildInfoMgr" | "level" | "accessKeyId" | "secretAccessKey" | "sessionToken" | "region" | "deliveryStream" | "batch" | "batchSize" | "client"

      • -
      • -

        V extends string | number | boolean | Firehose | BuildInfoManager

      +

      implementation of the {ResultsPlugin} class used to submit results

      +

      Parameters

      • -
        key: K
      • +
        name: string
      • -
        Optional defaultVal: V
      -

      Returns V

    +

    Returns Promise<void>

    +
  • Defined in aft-reporting-aws-kinesis-firehose/src/kinesis-reporting-plugin.ts:155
  • +
  • KinesisReportingPlugin +
  • Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPluginConfig.html b/docs/classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPluginConfig.html new file mode 100644 index 00000000..16811f41 --- /dev/null +++ b/docs/classes/aft_reporting_aws_kinesis_firehose.KinesisReportingPluginConfig.html @@ -0,0 +1,145 @@ +KinesisReportingPluginConfig | automated-functional-testing
    +
    + +
    +
    +
    + +
    +

    Hierarchy

    +
      +
    • ReportingPluginConfig +
        +
      • KinesisReportingPluginConfig
    +
    +
    +
    + +
    +
    +

    Constructors

    +
    +
    +

    Properties

    +
    +
    +

    Constructors

    +
    + +
    +
    +

    Properties

    +
    + +
    batch: boolean = true
    +
    + +
    batchSize: number = 10
    +
    + +
    deliveryStream: string
    +
    + +
    enabled: boolean
    +
    + +
    logLevel: "trace" | "debug" | "info" | "step" | "warn" | "pass" | "fail" | "error" | "none"
    +
    + +
    region: string
    +
    +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/classes/aft_reporting_filesystem.FilesystemReportingPlugin.html b/docs/classes/aft_reporting_filesystem.FilesystemReportingPlugin.html new file mode 100644 index 00000000..1b552843 --- /dev/null +++ b/docs/classes/aft_reporting_filesystem.FilesystemReportingPlugin.html @@ -0,0 +1,292 @@ +FilesystemReportingPlugin | automated-functional-testing
    +
    + +
    +
    +
    + +
    +

    Hierarchy

    +
      +
    • ReportingPlugin +
        +
      • FilesystemReportingPlugin
    +
    +
    +
    + +
    +
    +

    Constructors

    +
    +
    +

    Properties

    +
    +
    +

    Accessors

    +
    +
    +

    Methods

    +
    +
    +

    Constructors

    +
    + +
    +
    +

    Properties

    +
    + +
    _dateFormat: string
    +
    + +
    _includeResults: boolean
    +
    + +
    _level: "trace" | "debug" | "info" | "step" | "warn" | "pass" | "fail" | "error" | "none"
    +
    + +
    _outputPath: string
    +
    +

    Accessors

    +
    + +
      +
    • get aftCfg(): AftConfig
    • +
    • +

      Returns AftConfig

    +
    + +
      +
    • get aftLogger(): AftLogger
    • +
    • +

      Returns AftLogger

    +
    + +
      +
    • get enabled(): boolean
    • +
    • +

      Returns boolean

    +
    + +
    +
    +

    Methods

    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
      + +
    • +
      +

      Parameters

      +
        +
      • +
        name: string
      • +
      • +
        level: "trace" | "debug" | "info" | "step" | "warn" | "pass" | "fail" | "error" | "none"
      • +
      • +
        message: string
      • +
      • +
        Rest ...data: any[]
      +

      Returns Promise<void>

    +
    + +
    +
    +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/classes/aft_reporting_filesystem.FilesystemReportingPluginConfig.html b/docs/classes/aft_reporting_filesystem.FilesystemReportingPluginConfig.html new file mode 100644 index 00000000..01444a33 --- /dev/null +++ b/docs/classes/aft_reporting_filesystem.FilesystemReportingPluginConfig.html @@ -0,0 +1,138 @@ +FilesystemReportingPluginConfig | automated-functional-testing
    +
    + +
    +
    +
    + +
    +

    Hierarchy

    +
      +
    • ReportingPluginConfig +
        +
      • FilesystemReportingPluginConfig
    +
    +
    +
    + +
    +
    +

    Constructors

    +
    +
    +

    Properties

    +
    +
    +

    Constructors

    +
    + +
    +
    +

    Properties

    +
    + +
    dateFormat: string = 'YYYY-MM-DD HH:mm:ss.SSS'
    +
    + +
    enabled: boolean
    +
    + +
    includeResults: boolean = true
    +
    + +
    logLevel: "trace" | "debug" | "info" | "step" | "warn" | "pass" | "fail" | "error" | "none" = 'trace'
    +
    + +
    outputPath: string = ...
    +
    +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/classes/aft_reporting_html.HtmlReportingPlugin.html b/docs/classes/aft_reporting_html.HtmlReportingPlugin.html new file mode 100644 index 00000000..8b3fafae --- /dev/null +++ b/docs/classes/aft_reporting_html.HtmlReportingPlugin.html @@ -0,0 +1,335 @@ +HtmlReportingPlugin | automated-functional-testing
    +
    + +
    +
    +
    + +
    +

    Hierarchy

    +
      +
    • ReportingPlugin +
        +
      • HtmlReportingPlugin
    +
    +
    +
    + +
    +
    +

    Constructors

    +
    + +
    +
    +

    Properties

    +
    + +
    _fileName: string
    +
    + +
    _level: "trace" | "debug" | "info" | "step" | "warn" | "pass" | "fail" | "error" | "none"
    +
    + +
    _logs: FileSystemMap<string, string[]>
    +
    + +
    _maxLogLines: number
    +
    + +
    _outputDir: string
    +
    + +
    _results: FileSystemMap<string, HtmlTestResult[]>
    +
    +

    Accessors

    +
    + +
      +
    • get aftCfg(): AftConfig
    • +
    • +

      Returns AftConfig

    +
    + +
      +
    • get aftLogger(): AftLogger
    • +
    • +

      Returns AftLogger

    +
    + +
      +
    • get enabled(): boolean
    • +
    • +

      Returns boolean

    +
    + +
    +
    + +
      +
    • get logLevel(): "trace" | "debug" | "info" | "step" | "warn" | "pass" | "fail" | "error" | "none"
    • +
    • +

      Returns "trace" | "debug" | "info" | "step" | "warn" | "pass" | "fail" | "error" | "none"

    +
    +

    Methods

    +
    + +
    +
    + +
    +
    + +
    +
    + +
      + +
    • +
      +

      Parameters

      +
        +
      • +
        name: string
      • +
      • +
        level: "trace" | "debug" | "info" | "step" | "warn" | "pass" | "fail" | "error" | "none"
      • +
      • +
        message: string
      • +
      • +
        Rest ...data: any[]
      +

      Returns Promise<void>

    +
    + +
    +
    + +
    +
    + +
    +
    +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/classes/aft_reporting_html.HtmlReportingPluginConfig.html b/docs/classes/aft_reporting_html.HtmlReportingPluginConfig.html new file mode 100644 index 00000000..3c122f10 --- /dev/null +++ b/docs/classes/aft_reporting_html.HtmlReportingPluginConfig.html @@ -0,0 +1,138 @@ +HtmlReportingPluginConfig | automated-functional-testing
    +
    + +
    +
    +
    + +
    +

    Hierarchy

    +
      +
    • ReportingPluginConfig +
        +
      • HtmlReportingPluginConfig
    +
    +
    +
    + +
    +
    +

    Constructors

    +
    +
    +

    Properties

    +
    +
    +

    Constructors

    +
    + +
    +
    +

    Properties

    +
    + +
    enabled: boolean
    +
    + +
    fileName: string = 'testresults.html'
    +
    + +
    logLevel: "trace" | "debug" | "info" | "step" | "warn" | "pass" | "fail" | "error" | "none" = 'warn'
    +
    + +
    maxLogLines: number
    +
    + +
    outputDir: string = ...
    +
    +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/classes/aft_testrail.TestRailConfig.html b/docs/classes/aft_testrail.TestRailConfig.html index 99cf909b..4245fcf6 100644 --- a/docs/classes/aft_testrail.TestRailConfig.html +++ b/docs/classes/aft_testrail.TestRailConfig.html @@ -17,12 +17,12 @@

    Class TestRailConfig

    reads configuration from either the passed in TestRailConfigOptions or the aftconfig.json file under a heading of testrailconfig like:

    -
    {
    "TestRailConfig": {
    "url": "https://your-instance-of.testrail.io",
    "user": "your-username@your-company.com",
    "accesskey": "your-access-key-for-testrail",
    "projectid": 123,
    "suiteids": [234, 345, 456],
    "planid": 123456
    }
    } +
    {
    "TestRailConfig": {
    "url": "https://your-instance-of.testrail.io",
    "user": "your-username@your-company.com",
    "accesskey": "your-access-key-for-testrail",
    "projectid": 123,
    "suiteids": [234, 345, 456],
    "planid": 123456
    }
    }

    NOTE:

    • projectid and suiteids are only used if no planid is specified
    • -
    • if 'TestRailLoggingPluginis in use and noplanid` is specified a new +
    • if 'TestRailReportingPluginis in use and noplanid` is specified a new TestRail plan will be created and the value stored in a shared file for access by other processes and subsequent test executions
    @@ -30,13 +30,11 @@

    Class TestRailConfig

    Hierarchy

      -
    • TestRailConfig
    -
    -

    Implements

    +
  • ReportingPluginConfig
  • +
  • Defined in aft-testrail/src/configuration/testrail-config.ts:24
  • @@ -44,188 +42,90 @@

    Constructors

    -
    +
    -
    +

    Inherited from ReportingPluginConfig.constructor

    Properties

    -
    - -
    _accessKey: string
    -
    - -
    _cacheDuration: number
    -
    - -
    _config: IConfigProvider<TestRailConfigOptions>
    -
    - -
    _planId: number
    -
    - -
    _projectId: number
    -
    - -
    _shared: FileSystemMap<string, number>
    -
    - -
    _suiteIds: number[]
    -
    - -
    _url: string
    -
    - -
    _user: string
    -
    -

    Methods

    -
    +
    -
    -
    +
  • Defined in aft-testrail/src/configuration/testrail-config.ts:27
  • +
    -
    -
    - -
    -
    +
    cacheDuration: number = 300000
    +
    + +
    enabled: boolean
    +
    + +
    logLevel: "trace" | "debug" | "info" | "step" | "warn" | "pass" | "fail" | "error" | "none" = 'warn'
    +
    + +
    maxLogCharacters: number = 250
    +
    -
    -
    - -
    +
    + +
    policyEngineEnabled: boolean = true
    -
    - -
    +
    + +
    projectId: number
    -
    +
  • Defined in aft-testrail/src/configuration/testrail-config.ts:28
  • +
    -
    -
    +
  • Defined in aft-testrail/src/configuration/testrail-config.ts:29
  • +
    -
    -
    +
  • Defined in aft-testrail/src/configuration/testrail-config.ts:25
  • +
    -
    +
  • Defined in aft-testrail/src/configuration/testrail-config.ts:26
  • +
  • constructor
  • +
  • accessKey
  • +
  • cacheDuration
  • +
  • enabled
  • +
  • logLevel
  • +
  • maxLogCharacters
  • +
  • planId
  • +
  • policyEngineEnabled
  • +
  • projectId
  • +
  • suiteIds
  • +
  • url
  • +
  • user
  • Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/classes/aft_testrail.TestRailLoggingPlugin.html b/docs/classes/aft_testrail.TestRailLoggingPlugin.html deleted file mode 100644 index c6950cf7..00000000 --- a/docs/classes/aft_testrail.TestRailLoggingPlugin.html +++ /dev/null @@ -1,326 +0,0 @@ -TestRailLoggingPlugin | automated-functional-testing
    -
    - -
    -
    -
    - -
    -

    NOTE: this plugin can accept the following options from the LogManager via -aftconfig.json

    -
    {
    "level": "warn",
    "maxLogCharacters": 300,
    "enabled": true
    } -
    -
    -
    -

    Hierarchy

    -
    -
    -
    -
    - -
    -
    -

    Constructors

    -
    - -
    -
    -

    Properties

    -
    - -
    _api: TestRailApi
    -
    - -
    _logs: Map<string, string>
    -
    - -
    _trConfig: TestRailConfig
    -
    -

    Accessors

    -
    - -
    -
    - -
    -
    - -
      -
    • get enabled(): boolean
    • -
    • -

      Returns boolean

    -
    - -
      -
    • get level(): "error" | "trace" | "debug" | "info" | "step" | "warn" | "pass" | "fail" | "none"
    • -
    • -

      allows for filtering out of erroneous information from logs by assigning -values to different types of logging. the purpose of each log level is -as follows:

      -
        -
      • trace - used when logging low-level debug events that occur within a loop
      • -
      • debug - used for debug logging that does not run within a loop or at a high frequency
      • -
      • info - used for informational events providing current state of a system
      • -
      • step - used within a test to denote where within the test steps we are
      • -
      • warn - used for unexpected errors that are recoverable
      • -
      • pass - used to indicate the success of a test expectation or assertion
      • -
      • fail - used to indicate the failure of a test expectation or assertion
      • -
      • error - used for unexpected errors that are not recoverable
      • -
      • none - used when no logging is desired (disables logging)
      • -
      -
      -

      Returns "error" | "trace" | "debug" | "info" | "step" | "warn" | "pass" | "fail" | "none"

    -
    - -
    -
    -

    Methods

    -
    - -
    -
    - -
      - -
    • -
      -

      Parameters

      -
        -
      • -
        logName: string
      • -
      • -
        result: TestResult
      -

      Returns Promise<TestRailResultRequest>

    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
      - -
    • -
      -

      Type Parameters

      -
        -
      • -

        K extends "config" | "enabled" | "api" | "level" | "maxLogCharacters"

      • -
      • -

        V extends string | number | boolean | TestRailConfig | TestRailApi

      -
      -

      Parameters

      -
        -
      • -
        key: K
      • -
      • -
        Optional defaultVal: V
      -

      Returns V

    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/classes/aft_testrail.TestRailReportingPlugin.html b/docs/classes/aft_testrail.TestRailReportingPlugin.html new file mode 100644 index 00000000..a75aab85 --- /dev/null +++ b/docs/classes/aft_testrail.TestRailReportingPlugin.html @@ -0,0 +1,320 @@ +TestRailReportingPlugin | automated-functional-testing
    +
    + +
    +
    +
    + +
    +

    this plugin uses the following configuration to control its operation via +aftconfig.json and if the logLevel is unset it will be set from the value +in ReporterConfig before falling back to a value of warn

    +
    {
    "TestRailConfig": {
    "logLevel": "warn",
    "maxLogCharacters": 300,
    "planId": 1234,
    "projectId": 12,
    "suiteIds": [34, 567]
    }
    } +
    +
    +

    NOTE: if no value is set for planId and a logLevel value other than none is used +then a new TestRail Plan will be created from the specified projectId and suiteIds +configuration keys

    +
    +
    +
    +

    Hierarchy

    +
      +
    • ReportingPlugin +
        +
      • TestRailReportingPlugin
    +
    +
    +
    + +
    +
    +

    Constructors

    +
    +
    +

    Properties

    +
    +
    +

    Accessors

    +
    +
    +

    Methods

    +
    +
    +

    Constructors

    +
    + +
    +
    +

    Properties

    +
    + +
    _api: TestRailApi
    +
    + +
    _level: "trace" | "debug" | "info" | "step" | "warn" | "pass" | "fail" | "error" | "none"
    +
    + +
    _logs: Map<string, string>
    +
    + +
    _maxLogChars: number
    +
    + +
    initialise: ((logName: string) => Promise<void>)
    +
    +

    Type declaration

    +
      +
    • +
        +
      • (logName: string): Promise<void>
      • +
      • +

        called by the parent Reporter on load to allow any plugins to configure +themselves for a new logger

        +
        +
        +

        Parameters

        +
          +
        • +
          logName: string
          +

          the name of the Reporter instance calling dispose

          +
        +

        Returns Promise<void>

    +
    +

    Accessors

    +
    + +
      +
    • get aftCfg(): AftConfig
    • +
    • +

      Returns AftConfig

    +
    + +
      +
    • get aftLogger(): AftLogger
    • +
    • +

      Returns AftLogger

    +
    + +
      +
    • get enabled(): boolean
    • +
    • +

      Returns boolean

    +
    + +
      +
    • get logLevel(): "trace" | "debug" | "info" | "step" | "warn" | "pass" | "fail" | "error" | "none"
    • +
    • +

      Returns "trace" | "debug" | "info" | "step" | "warn" | "pass" | "fail" | "error" | "none"

    +
    +

    Methods

    +
    + +
    +
    + +
    +
    + +
      + +
    • +
      +

      Parameters

      +
        +
      • +
        name: string
      • +
      • +
        level: "trace" | "debug" | "info" | "step" | "warn" | "pass" | "fail" | "error" | "none"
      • +
      • +
        message: string
      • +
      • +
        Rest ...data: any[]
      +

      Returns Promise<void>

    +
    + +
    +
    + +
    +
    +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/classes/aft_testrail.TestRailTestCasePlugin.html b/docs/classes/aft_testrail.TestRailTestCasePlugin.html deleted file mode 100644 index 7f58a86b..00000000 --- a/docs/classes/aft_testrail.TestRailTestCasePlugin.html +++ /dev/null @@ -1,326 +0,0 @@ -TestRailTestCasePlugin | automated-functional-testing
    -
    - -
    -
    -
    - -
    -

    NOTE: this plugin has no configuration options as they are -all retrieved from TestRailConfig under the TestRailConfig -section of your aftconfig.json file

    -
    -
    -

    Hierarchy

    -
    -
    -
    -
    - -
    -
    -

    Constructors

    -
    - -
    -
    -

    Properties

    -
    - -
    _api: TestRailApi
    -
    - -
    _logMgr: LogManager
    -
    - -
    _trConfig: TestRailConfig
    -
    -

    Accessors

    -
    - -
    -
    - -
    -
    - -
      -
    • get enabled(): boolean
    • -
    • -

      Returns boolean

    -
    - -
    -
    -

    Methods

    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
      - -
    • -

      the searchTerm must take the format of key=value where the key is a valid -field on a TestRailTest or TestRailCase object and the value is the expected -value to be found for said key

      -
      -
      -

      Parameters

      -
        -
      • -
        searchTerm: string
        -

        a string containing a key and a value to be used to locate tests

        -
      -

      Returns Promise<TestCase[]>

    -
    - -
    -
    - -
      - -
    • -
      -

      Type Parameters

      -
        -
      • -

        K extends "config" | "enabled" | "api" | "logMgr"

      • -
      • -

        V extends boolean | TestRailConfig | TestRailApi | LogManager

      -
      -

      Parameters

      -
        -
      • -
        key: K
      • -
      • -
        Optional defaultVal: V
      -

      Returns V

    -
    - -
      - -
    • -

      function will find a TestRail test or case by case id and if found -will return true if the test is not already marked as passed. if -no test is found then false is returned

      -
      -
      -

      Parameters

      -
        -
      • -
        caseId: string
        -

        the TestRail case id used to lookup either a test in an -existing plan or a case in an existing suite

        -
      -

      Returns Promise<boolean>

    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/classes/aft_testrail.TestRailTestExecutionPolicyPlugin.html b/docs/classes/aft_testrail.TestRailTestExecutionPolicyPlugin.html new file mode 100644 index 00000000..290fd783 --- /dev/null +++ b/docs/classes/aft_testrail.TestRailTestExecutionPolicyPlugin.html @@ -0,0 +1,248 @@ +TestRailTestExecutionPolicyPlugin | automated-functional-testing
    +
    + +
    +
    +
    +
    + +

    Class TestRailTestExecutionPolicyPlugin

    +
    +

    NOTE: this plugin has no configuration options as they are +all retrieved from TestRailConfig under the TestRailConfig +section of your aftconfig.json file

    +
    +
    +

    Hierarchy

    +
      +
    • TestExecutionPolicyPlugin +
        +
      • TestRailTestExecutionPolicyPlugin
    +
    +
    +
    + +
    +
    +

    Constructors

    +
    +
    +

    Properties

    +
    +
    +

    Accessors

    +
    +
    +

    Methods

    +
    +
    +

    Constructors

    +
    + +
    +
    +

    Properties

    +
    + +
    _api: TestRailApi
    +
    + +
    _enabled: boolean
    +
    +

    Accessors

    +
    + +
      +
    • get aftCfg(): AftConfig
    • +
    • +

      Returns AftConfig

    +
    + +
      +
    • get aftLogger(): AftLogger
    • +
    • +

      Returns AftLogger

    +
    + +
    +
    +

    Methods

    +
    + +
    +
    + +
      + +
    • +

      the searchTerm must take the format of key=value where the key is a valid +field on a TestRailTest or TestRailCase object and the value is the expected +value to be found for said key

      +
      +
      +

      Parameters

      +
        +
      • +
        searchTerm: string
        +

        a string containing a key and a value to be used to locate tests

        +
      +

      Returns Promise<(TestRailCase | TestRailTest)[]>

    +
    + +
    +
    + +
      + +
    • +

      function will find a TestRail test or case by case id and if found +will return true if the test is not already marked as passed. if +no test is found then false is returned

      +
      +
      +

      Parameters

      +
        +
      • +
        caseId: string
        +

        the TestRail case id used to lookup either a test in an +existing plan or a case in an existing suite

        +
      +

      Returns Promise<ProcessingResult<boolean>>

    +
    +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/classes/aft_ui.UiComponent.html b/docs/classes/aft_ui.UiComponent.html new file mode 100644 index 00000000..e248bc84 --- /dev/null +++ b/docs/classes/aft_ui.UiComponent.html @@ -0,0 +1,220 @@ +UiComponent | automated-functional-testing
    +
    + +
    +
    +
    +
    + +

    Class UiComponentAbstract

    +
    +

    used to encapsulate logical blocks of a UI providing the ability to chain +element lookups back to a root ancestor meaning that individual locators +only need to be concerned with elements that exist as a child of the parent +of this UiFacet. this is especially useful when UI elements exist in +multiple places on a page and you only wish to get one instance in a specific +location

    +
    +
    +

    Hierarchy

    +
      +
    • UiComponent
    +
    +
    +
    + +
    +
    +

    Constructors

    +
    +
    +

    Properties

    +
    +
    +

    Accessors

    +
    +
    +

    Methods

    +
    +
    +

    Constructors

    +
    + +
    +
    +

    Properties

    +
    + +
    _driver: unknown
    +
    + +
    _locator: unknown
    +
    + +
    _parent: Func<void, Promise<unknown>>
    +
    + +
    aftCfg: AftConfig
    +
    + +
    reporter: Reporter
    +
    +

    Accessors

    +
    + +
    +
    + +
    +
    + +
    +
    +

    Methods

    +
    + +
    +
    + +
    +
    +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/classes/aft_ui.UiFacet.html b/docs/classes/aft_ui.UiFacet.html deleted file mode 100644 index b4e0df3b..00000000 --- a/docs/classes/aft_ui.UiFacet.html +++ /dev/null @@ -1,303 +0,0 @@ -UiFacet | automated-functional-testing
    -
    - -
    -
    -
    -
    - -

    Class UiFacet<T>Abstract

    -
    -

    Type Parameters

    -
    -
    -

    Hierarchy

    -
      -
    • UiFacet
    -
    -

    Implements

    -
      -
    • IHasOptions<T>
    -
    -
    -
    - -
    -
    -

    Constructors

    -
    -
    -

    Properties

    -
    -
    -

    Accessors

    -
    -
    -

    Methods

    -
    -
    -

    Constructors

    -
    - -
    -
    -

    Properties

    -
    - -
    _logMgr: LogManager
    -
    - -
    _opts: T
    -
    -

    Accessors

    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    -

    Methods

    -
    - -
    -
    - -
    -
    - -
      - -
    • -
      -

      Type Parameters

      -
      -
      -

      Parameters

      -
        -
      • -
        facetType: Class<F>
      • -
      • -
        Optional options: T
      -

      Returns Promise<F>

    -
    - -
    -
    - -
      - -
    • -
      -

      Type Parameters

      -
        -
      • -

        K extends string | number | symbol

      • -
      • -

        V

      -
      -

      Parameters

      -
        -
      • -
        key: K
      • -
      • -
        Optional defaultVal: V
      -

      Returns V

    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/classes/aft_ui.UiPlatform.html b/docs/classes/aft_ui.UiPlatform.html deleted file mode 100644 index 5ac9a1b6..00000000 --- a/docs/classes/aft_ui.UiPlatform.html +++ /dev/null @@ -1,170 +0,0 @@ -UiPlatform | automated-functional-testing
    -
    - -
    -
    -
    - -
    -

    Hierarchy

    -
      -
    • UiPlatform
    -
    -
    -
    - -
    -
    -

    Constructors

    -
    -
    -

    Properties

    -
    -
    -

    Methods

    -
    -
    -

    Constructors

    -
    - -
    -
    -

    Properties

    -
    - -
    browser: string
    -
    - -
    browserVersion: string
    -
    - -
    deviceName: string
    -
    - -
    os: string
    -
    - -
    osVersion: string
    -
    - -
    ANY: string = '+'
    -
    -

    Methods

    -
    - -
    -
    - -
    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/classes/aft_ui.UiSession.html b/docs/classes/aft_ui.UiSession.html deleted file mode 100644 index 739580d0..00000000 --- a/docs/classes/aft_ui.UiSession.html +++ /dev/null @@ -1,236 +0,0 @@ -UiSession | automated-functional-testing
    -
    - -
    -
    -
    -
    - -

    Class UiSession<T>Abstract

    -
    -

    Type Parameters

    -
    -
    -

    Hierarchy

    -
      -
    • UiSession
    -
    -

    Implements

    -
      -
    • IHasOptions<T>
    • -
    • Disposable
    -
    -
    -
    - -
    -
    -

    Constructors

    -
    -
    -

    Properties

    -
    -
    -

    Accessors

    -
    -
    -

    Methods

    -
    -
    -

    Constructors

    -
    - -
    -
    -

    Properties

    -
    - -
    _logMgr: LogManager
    -
    - -
    _options: T
    -
    - -
    _platform: UiPlatform
    -
    - -
    driver: unknown
    -
    -

    Accessors

    -
    - -
    -
    - -
    -
    -

    Methods

    -
    - -
      - -
    • -
      -

      Parameters

      -
        -
      • -
        Optional error: any
      -

      Returns Promise<void>

    -
    - -
    -
    - -
      - -
    • -
      -

      Type Parameters

      -
        -
      • -

        K extends string | number | symbol

      • -
      • -

        V

      -
      -

      Parameters

      -
        -
      • -
        key: K
      • -
      • -
        Optional defaultVal: V
      -

      Returns V

    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/classes/aft_ui.UiSessionConfig.html b/docs/classes/aft_ui.UiSessionConfig.html new file mode 100644 index 00000000..cef1d196 --- /dev/null +++ b/docs/classes/aft_ui.UiSessionConfig.html @@ -0,0 +1,112 @@ +UiSessionConfig | automated-functional-testing
    +
    + +
    +
    +
    + +
    +

    Hierarchy

    +
      +
    • UiSessionConfig
    +
    +
    +
    + +
    +
    +

    Constructors

    +
    +
    +

    Properties

    +
    +
    +

    Constructors

    +
    + +
    +
    +

    Properties

    +
    + +
    generatorName: string
    +
    + +
    options: Record<string, any> = {}
    +
    +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/classes/aft_ui.UiSessionGeneratorManager.html b/docs/classes/aft_ui.UiSessionGeneratorManager.html index 62f12547..ccb04946 100644 --- a/docs/classes/aft_ui.UiSessionGeneratorManager.html +++ b/docs/classes/aft_ui.UiSessionGeneratorManager.html @@ -13,34 +13,19 @@
  • automated-functional-testing
  • aft-ui
  • UiSessionGeneratorManager
  • -

    Class UiSessionGeneratorManager<T, Tc>Abstract

    +

    Class UiSessionGeneratorManager

    -

    abstract class that should be extended by PluginManager instances that manage UI Session Generator Plugins -configuration options supported by this class are:

    -
      -
    • platform - [optional] an string containing any, none or all of the following string values: os, osVersion, browser, browserVersion, deviceName
    • -
    • loadWaitDuration - [optional] a number representing the max milliseconds to wait for a UI element (defaults to 10000 ms)
    • -
    • pluginNames - an array containing any UiSessionGeneratorPlugin<T extends UiSessionGeneratorPluginOptions> implementations to load (NOTE: only the first enabled will be used)
    • -
    • searchDir - the root directory from which to start searching for plugins (defaults to process.cwd())
    • -
    -
    {
    ...
    "UiSessionGeneratorManagerInstance": {
    "uiplatform": "mac_11_safari",
    "plugins": [{
    "name": "some-custom-session-plugin",
    "searchDirectory": "../starting/path/to/find/plugin/",
    "options": {
    "uiplatform": "windows_10_chrome_87_Google Pixel XL"
    }
    }]
    }
    ...
    } +

    class will get a UI Session Generator Plugin by name listed in UiSessionConfig.sessionGeneratorName +and call it's getSession function

    +
    {
    "pluginNames": [
    "grid-session-generator-plugin",
    "local-browser-session-generator-plugin"
    ]
    ...
    "UiSessionConfig": {
    "generatorName": "grid-session-generator-plugin",
    "uiplatform": {
    "os": "android",
    "osValue": "13",
    "browser": "chrome",
    "browserVersion": "112",
    "deviceName": "Samsung Galaxy S23"
    },
    "options": {
    "url": "https://hub-cloud.browserstack.com/wd/hub"
    "capabilities": {
    "browserName": "chrome"
    "bstack:options": {
    "userName": "lkjsdlak",
    "accessKey": "laksdjf12312",
    "debug": true
    }
    }
    }
    }
    ...
    }
    -
    -
    -

    Type Parameters

    -
    +

    Hierarchy

      -
    • PluginManagerWithLogging<T, Tc> -
        -
      • UiSessionGeneratorManager
    @@ -48,210 +33,62 @@

    Constructors

    -
    +
    -
    +
  • Defined in aft-ui/src/sessions/ui-session-generator-manager.ts:45
  • Properties

    -
    - -
    _uiPlt: UiPlatform
    +
  • Defined in aft-ui/src/sessions/ui-session-generator-manager.ts:42
  • +
    + +

    Methods

    -
    - -
      - -
    • -
      -

      Type Parameters

      -
        -
      • -

        K extends string | number | symbol

      • -
      • -

        V

      -
      -

      Parameters

      -
        -
      • -
        key: K
      • -
      • -
        Optional defaultVal: V
      -

      Returns Promise<V>

    -
    - -
      - -
    • -

      Returns Promise<T[]>

    -
    - -
      - -
    • -

      returns the first loaded plugin instance

      -
      -

      Returns Promise<T>

    -
    - -
      - -
    • -

      instantiates new plugins and caches them for use at plugins

      -

      NOTE: this does not destroy previous instances, but removes them -from the internal array and replaces them with the new instances

      -
      -

      Returns Promise<T[]>

    -
    - -
      - -
    • -

      Returns Promise<LogManager>

    -
    - -
      - -
    • -

      attempts to find the first plugin who's class name matches a specified string

      - -

      Returns

      the first plugin who's class name matched the passed in ctorName (both lowercase)

      -
      -
      -

      Parameters

      -
        -
      • -
        ctorName: string
        -

        the class name of the plugin

        -
      -

      Returns Promise<T>

    -
    - +
    +
    -
    - -
      - -
    • -
      -

      Type Parameters

      -
        -
      • -

        K extends string | number | symbol

      • -
      • -

        V

      -
      -

      Parameters

      -
        -
      • -
        key: K
      • -
      • -
        Optional defaultVal: V
      -

      Returns V

    +

    Returns Promise<unknown>

    -
    - -
    -
    - -
      - -
    • -

      returns the array of loaded plugin instances

      -
      -

      Returns Promise<T[]>

    -
    - -
    +
  • Defined in aft-ui/src/sessions/ui-session-generator-manager.ts:54
  • +
  • constructor
  • +
  • aftCfg
  • +
  • plugins
  • +
  • getSession
  • Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/classes/aft_ui.UiSessionGeneratorPlugin.html b/docs/classes/aft_ui.UiSessionGeneratorPlugin.html index 6dc30013..7ae14ecb 100644 --- a/docs/classes/aft_ui.UiSessionGeneratorPlugin.html +++ b/docs/classes/aft_ui.UiSessionGeneratorPlugin.html @@ -13,20 +13,15 @@
  • automated-functional-testing
  • aft-ui
  • UiSessionGeneratorPlugin
  • -

    Class UiSessionGeneratorPlugin<T>Abstract

    -
    -

    Type Parameters

    -
    +

    Class UiSessionGeneratorPlugin

    Hierarchy

      -
    • Plugin<T> +
    • Plugin
      • UiSessionGeneratorPlugin
    +
  • Defined in aft-ui/src/sessions/ui-session-generator-plugin.ts:4
  • @@ -37,119 +32,75 @@

    Constructors

    -

    Properties

    -
    -

    Accessors

    -

    Methods

    -

    Constructors

    -
    -

    Properties

    -
    - -
    _logMgr: LogManager
    -
    - -
    _platform: UiPlatform
    +
  • Defined in aft-core/dist/src/plugins/plugin.d.ts:15
  • Accessors

    -
    - +
    +
      -
    • get enabled(): boolean
    • +
    • get aftCfg(): AftConfig
    • -

      Returns boolean

    -
    - -
      -
    • get logMgr(): LogManager
    • +
    • Defined in aft-core/dist/src/plugins/plugin.d.ts:12
    +
    + +
    -
    - +
  • Defined in aft-core/dist/src/plugins/plugin.d.ts:13
  • +
    +
    +
  • Defined in aft-ui/src/sessions/ui-session-generator-plugin.ts:5
  • Methods

    -
    - +
    +
      - +
    • Parameters

      -

      Returns Promise<UiSession<any>>

    +

    Returns Promise<unknown>

    -
    - -
      - -
    • -
      -

      Type Parameters

      -
        -
      • -

        K extends string | number | symbol

      • -
      • -

        V

      -
      -

      Parameters

      -
        -
      • -
        key: K
      • -
      • -
        Optional defaultVal: V
      -

      Returns V

    +
  • Defined in aft-ui/src/sessions/ui-session-generator-plugin.ts:11
  • +
  • aftCfg
  • +
  • aftLogger
  • +
  • enabled
  • +
  • getSession
  • Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/classes/aft_ui_browsers.BrowserFacet.html b/docs/classes/aft_ui_browsers.BrowserFacet.html deleted file mode 100644 index b6df1066..00000000 --- a/docs/classes/aft_ui_browsers.BrowserFacet.html +++ /dev/null @@ -1,285 +0,0 @@ -BrowserFacet | automated-functional-testing
    -
    - -
    -
    -
    - -
    -

    Hierarchy

    -
    -
    -
    -
    - -
    -
    -

    Constructors

    -
    - -
    -
    -

    Accessors

    -
    - -
      -
    • get index(): number
    • -
    • -

      Returns number

    -
    - -
    -
    - -
      -
    • get logMgr(): LogManager
    • -
    • -

      Returns LogManager

    -
    - -
      -
    • get maxWaitMs(): number
    • -
    • -

      Returns number

    -
    - -
    -
    - -
      -
    • get retryDelayBackOff(): RetryBackOffType
    • -
    • -

      Returns RetryBackOffType

    -
    - -
      -
    • get retryDelayMs(): number
    • -
    • -

      Returns number

    -
    - -
    -
    -

    Methods

    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
      - -
    • -
      -

      Type Parameters

      -
        -
      • -

        K extends keyof UiFacetOptions

      • -
      • -

        V extends number | LogManager | RetryBackOffType | Locator | UiFacet<any> & BrowserFacet | UiSession<any> & BrowserSession<any>

      -
      -

      Parameters

      -
        -
      • -
        key: K
      • -
      • -
        Optional defaultVal: V
      -

      Returns V

    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/classes/aft_ui_browsers.BrowserSession.html b/docs/classes/aft_ui_browsers.BrowserSession.html deleted file mode 100644 index 30a866b0..00000000 --- a/docs/classes/aft_ui_browsers.BrowserSession.html +++ /dev/null @@ -1,316 +0,0 @@ -BrowserSession | automated-functional-testing
    -
    - -
    -
    -
    - -
    -

    Type Parameters

    -
    -
    -

    Hierarchy

    -
    -
    -
    -
    - -
    -
    -

    Constructors

    -
    - -
      - -
    • -
      -

      Type Parameters

      -
      -
      -

      Parameters

      -
        -
      • -
        Optional options: T
      -

      Returns BrowserSession<T>

    -
    -

    Properties

    -
    - -
    _additionalCapabilities: object
    -
    - -
    _resolution: string
    -
    - -
    _uiplatform: UiPlatform
    -
    -

    Accessors

    -
    - -
    -
    - -
    -
    - -
      -
    • get logMgr(): LogManager
    • -
    • -

      Returns LogManager

    -
    - -
      -
    • get platform(): UiPlatform
    • -
    • -

      Returns UiPlatform

    -
    - -
    -
    - -
    -
    -

    Methods

    -
    - -
    -
    - -
      - -
    • -
      -

      Type Parameters

      -
        -
      • -

        T extends UiFacet<To, T>

      • -
      • -

        To extends UiFacetOptions

      -
      -

      Parameters

      -
        -
      • -
        facetType: Class<T>
      • -
      • -
        Optional options: To
      -

      Returns Promise<T>

    -
    - -
    -
    - -
      - -
    • -
      -

      Type Parameters

      -
        -
      • -

        K extends string | number | symbol

      • -
      • -

        V

      -
      -

      Parameters

      -
        -
      • -
        key: K
      • -
      • -
        Optional defaultVal: V
      -

      Returns V

    -
    - -
    -
    - -
    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/classes/aft_ui_browsers.BrowserSessionGeneratorPlugin.html b/docs/classes/aft_ui_browsers.BrowserSessionGeneratorPlugin.html deleted file mode 100644 index 5859fd3d..00000000 --- a/docs/classes/aft_ui_browsers.BrowserSessionGeneratorPlugin.html +++ /dev/null @@ -1,310 +0,0 @@ -BrowserSessionGeneratorPlugin | automated-functional-testing
    -
    - -
    -
    -
    -
    - -

    Class BrowserSessionGeneratorPlugin<T>Abstract

    -
    -

    abstract class to be extended by any Browser Session Generator Plugins to be -loaded by the BrowserSessionGeneratorManager. accepts options of the following:

    -
    {
    "url": "http://url.to/selenium/grid",
    "uiplatform": "android_11_firefox_75_Google Pixel XL",
    "additionalCapabilities": {
    "someKey": "someValue"
    },
    "implicitTimeout": 3000
    } -
    -
    -
    -

    Type Parameters

    -
    -
    -

    Hierarchy

    -
    -
    -
    -
    - -
    -
    -

    Constructors

    -
    - -
    -
    -

    Properties

    -
    - -
    _caps: object
    -
    - -
    _resolution: string
    -
    - -
    _timeout: number
    -
    - -
    _url: string
    -
    -

    Accessors

    -
    - -
    -
    - -
      -
    • get enabled(): boolean
    • -
    • -

      Returns boolean

    -
    - -
    -
    - -
      -
    • get logMgr(): LogManager
    • -
    • -

      Returns LogManager

    -
    - -
    -
    - -
      -
    • get uiplatform(): UiPlatform
    • -
    • -

      Returns UiPlatform

    -
    - -
    -
    -

    Methods

    -
    - -
      - -
    • -

      expected to be called from within BrowserSessionGeneratorPlugin implementations -after configuring their own Capabilties within their newUiSession function

      - -

      Returns

      a new WebDriver instance

      -
      -
      -

      Parameters

      -
        -
      • -
        capabilities: Capabilities
        -

        capabilities to pass to the Remote WebDriver Builder

        -
      -

      Returns Promise<WebDriver>

    -
    - -
    -
    - -
      - -
    • -
      -

      Parameters

      -
        -
      • -
        Optional options: UiSessionOptions
      -

      Returns Promise<UiSession<any>>

    -
    - -
      - -
    • -
      -

      Type Parameters

      -
        -
      • -

        K extends string | number | symbol

      • -
      • -

        V

      -
      -

      Parameters

      -
        -
      • -
        key: K
      • -
      • -
        Optional defaultVal: V
      -

      Returns V

    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/classes/aft_ui_browsers.BrowserStackBrowserSession.html b/docs/classes/aft_ui_browsers.BrowserStackBrowserSession.html deleted file mode 100644 index 3d9482bb..00000000 --- a/docs/classes/aft_ui_browsers.BrowserStackBrowserSession.html +++ /dev/null @@ -1,373 +0,0 @@ -BrowserStackBrowserSession | automated-functional-testing
    -
    - -
    -
    -
    - -
    -

    Hierarchy

    -
    -
    -
    -
    - -
    -
    -

    Constructors

    -
    - -
    -
    -

    Properties

    -
    - -
    _debug: boolean
    -
    - -
    _key: string
    -
    - -
    _local: boolean
    -
    - -
    _localIdentifier: string
    -
    - -
    _user: string
    -
    -

    Accessors

    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
      -
    • get logMgr(): LogManager
    • -
    • -

      Returns LogManager

    -
    - -
      -
    • get platform(): UiPlatform
    • -
    • -

      Returns UiPlatform

    -
    - -
    -
    - -
    -
    - -
    -
    -

    Methods

    -
    - -
    -
    - -
    -
    - -
    -
    - -
      - -
    • -
      -

      Type Parameters

      -
        -
      • -

        K extends keyof UiSessionOptions | "resolution" | "additionalCapabilities" | "debug" | "user" | "key" | "local" | "localIdentifier"

      • -
      • -

        V extends string | boolean | object | WebDriver | LogManager

      -
      -

      Parameters

      -
        -
      • -
        key: K
      • -
      • -
        Optional defaultVal: V
      -

      Returns V

    -
    - -
    -
    - -
    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/classes/aft_ui_browsers.BrowserStackBrowserSessionGeneratorPlugin.html b/docs/classes/aft_ui_browsers.BrowserStackBrowserSessionGeneratorPlugin.html deleted file mode 100644 index 738c1099..00000000 --- a/docs/classes/aft_ui_browsers.BrowserStackBrowserSessionGeneratorPlugin.html +++ /dev/null @@ -1,359 +0,0 @@ -BrowserStackBrowserSessionGeneratorPlugin | automated-functional-testing
    -
    - -
    -
    -
    -
    - -

    Class BrowserStackBrowserSessionGeneratorPlugin

    -
    -

    abstract class to be extended by any Browser Session Generator Plugins to be -loaded by the BrowserSessionGeneratorManager. accepts options of the following:

    -
    {
    "url": "http://url.to/selenium/grid",
    "uiplatform": "android_11_firefox_75_Google Pixel XL",
    "additionalCapabilities": {
    "someKey": "someValue"
    },
    "implicitTimeout": 3000
    } -
    -
    -
    -

    Hierarchy

    -
    -
    -
    -
    - -
    -
    -

    Constructors

    -
    - -
    -
    -

    Properties

    -
    - -
    _debug: boolean
    -
    - -
    _key: string
    -
    - -
    _local: boolean
    -
    - -
    _localIdentifier: string
    -
    - -
    _user: string
    -
    -

    Accessors

    -
    - -
    -
    - -
    -
    - -
      -
    • get enabled(): boolean
    • -
    • -

      Returns boolean

    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
      -
    • get logMgr(): LogManager
    • -
    • -

      Returns LogManager

    -
    - -
    -
    - -
      -
    • get uiplatform(): UiPlatform
    • -
    • -

      Returns UiPlatform

    -
    - -
    -
    - -
    -
    -

    Methods

    -
    - -
    -
    - -
    -
    - -
    -
    - -
      - -
    • -
      -

      Type Parameters

      -
        -
      • -

        K extends "uiplatform" | "logMgr" | "resolution" | "additionalCapabilities" | "enabled" | "url" | "implicitTimeout" | "debug" | "user" | "key" | "local" | "localIdentifier"

      • -
      • -

        V extends string | number | boolean | object | LogManager

      -
      -

      Parameters

      -
        -
      • -
        key: K
      • -
      • -
        Optional defaultVal: V
      -

      Returns V

    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/classes/aft_ui_browsers.BrowserVerifier.html b/docs/classes/aft_ui_browsers.BrowserVerifier.html deleted file mode 100644 index 1913cf5c..00000000 --- a/docs/classes/aft_ui_browsers.BrowserVerifier.html +++ /dev/null @@ -1,760 +0,0 @@ -BrowserVerifier | automated-functional-testing
    -
    - -
    -
    -
    - -
    -

    Hierarchy

    -
      -
    • Verifier -
        -
      • BrowserVerifier
    -
    -
    -
    - -
    -
    -

    Constructors

    -
    - -
      - -
    • -

      Returns BrowserVerifier

    -
    -

    Properties

    -
    - -
    _assertion: Func<BrowserVerifier, any>
    -
    - -
    _buildMgr: BuildInfoManager
    -
    - -
    _defectMgr: DefectManager
    -
    - -
    _defects: Set<string>
    -
    - -
    _description: string
    -
    - -
    _innerPromise: Promise<void>
    -
    - -
    _logMgr: LogManager
    -
    - -
    _matcher: VerifierMatcher
    -
    - -
    _session: BrowserSession<any>
    -
    - -
    _sessionMgr: BrowserSessionGeneratorManager
    -
    - -
    _sessionOptions: BrowserSessionOptions
    -
    - -
    _startTime: number
    -
    - -
    _testMgr: TestCaseManager
    -
    - -
    _tests: Set<string>
    -
    -

    Accessors

    -
    - -
      -
    • get and(): this
    • -
    • -

      a syntactic way of connecting fluent functions for the Verifier

      -
      -

      Returns this

    -
    - -
      -
    • get buildMgr(): BuildInfoManager
    • -
    • -

      Returns BuildInfoManager

    -
    - -
      -
    • get defectMgr(): DefectManager
    • -
    • -

      Returns DefectManager

    -
    - -
      -
    • get logMgr(): LogManager
    • -
    • -

      a LogManager that uses either the Description -or a list of Test Ids or a uuid as the logName depending -on which is available (NOTE: description is preferred most and -will be used if other values are also present)

      -
      -

      Returns LogManager

    -
    - -
    -
    - -
      -
    • get sessionGeneratorManager(): BrowserSessionGeneratorManager
    • -
    • -

      a BrowserSessionGeneratorManager instance used to generate new -Browser sessions

      -
      -

      Returns BrowserSessionGeneratorManager

    -
    - -
    -
    - -
      -
    • get testMgr(): TestCaseManager
    • -
    • -

      Returns TestCaseManager

    -
    -

    Methods

    -
    - -
      - -
    • -
      -

      Parameters

      -
        -
      • -
        status: TestStatus
      • -
      • -
        logMessage: string
      • -
      • -
        Optional testId: string
      -

      Returns Promise<TestResult>

    -
    - -
      - -
    • -
      -

      Parameters

      -
        -
      • -
        status: TestStatus
      • -
      • -
        logMessage: string
      • -
      • -
        Rest ...testIds: string[]
      -

      Returns Promise<TestResult[]>

    -
    - -
      - -
    • -

      Returns Promise<void>

    -
    - -
      - -
    • -
      -

      Parameters

      -
        -
      • -
        status: TestStatus
      • -
      • -
        Optional message: string
      -

      Returns Promise<void>

    -
    - -
      - -
    • -

      creates TestResult objects for each testId and sends these -to the LogManager.logResult function

      -
      -
      -

      Parameters

      -
        -
      • -
        status: TestStatus
      • -
      • -
        Optional message: string
      -

      Returns Promise<void>

    -
    - -
    -
    - -
      - -
    • -
      -

      Parameters

      -
        -
      • -
        Rest ...defects: string[]
      -

      Returns Promise<ProcessingResult>

    -
    - -
      - -
    • -
      -

      Parameters

      -
        -
      • -
        Rest ...tests: string[]
      -

      Returns Promise<ProcessingResult>

    -
    - -
      - -
    • -

      allows for specifying either the expected return value or a VerifierMatcher -to be used to compare the return value using the VerifierMatcher.compare() -function. if not set then only exceptions will cause a failed result on -the executed assertion

      - -

      Returns

      this Verifier instance

      -
      -
      -

      Parameters

      -
        -
      • -
        result: any
        -

        the expected result or a VerifierMatcher implementation

        -
      -

      Returns BrowserVerifier

    -
    - -
      - -
    • -
      -

      Type Parameters

      -
        -
      • -

        TResult1 = Verifier

      • -
      • -

        TResult2 = never

      -
      -

      Parameters

      -
        -
      • -
        Optional onfulfilled: ((value: void) => TResult1 | PromiseLike<TResult1>)
        -
          -
        • -
            -
          • (value: void): TResult1 | PromiseLike<TResult1>
          • -
          • -
            -

            Parameters

            -
              -
            • -
              value: void
            -

            Returns TResult1 | PromiseLike<TResult1>

      • -
      • -
        Optional onrejected: ((reason: any) => TResult2 | PromiseLike<TResult2>)
        -
          -
        • -
            -
          • (reason: any): TResult2 | PromiseLike<TResult2>
          • -
          • -
            -

            Parameters

            -
              -
            • -
              reason: any
            -

            Returns TResult2 | PromiseLike<TResult2>

      -

      Returns Promise<TResult1 | TResult2>

    -
    - -
      - -
    • -

      the starting point for setting up a Verifier execution. Generally it is preferred -to use the verify(...) const instead of creating individual Verifier instances. -ex:

      -
      await verify(async (v: Verifier) => {
      await v.logMgr.info('doing some testing...');
      let feature = new FeatureObj();
      return await feature.returnExpectedValue();
      }).withDescription('example usage for Verifier')
      .and.withTestId('C1234')
      .returns('expected value'); -
      - -

      Returns

      this Verifier instance

      -
      -
      -

      Parameters

      -
        -
      • -
        assertion: Func<Verifier, any>
        -

        the Func<Verifier, any> function to be executed by this Verifier

        -
      -

      Returns BrowserVerifier

    -
    - -
      - -
    • -

      allows for passing in an instance of BrowserSessionGeneratorManager to be -used in locating a BrowserSessionGeneratorPlugin instance to use in -generating a BrowserSession. -NOTE: if not set then the global const browserSessionGeneratorMgr will be used

      - -

      Returns

      this BrowserVerifier instance

      -
      -
      -

      Parameters

      -
        -
      • -
        sessionMgr: BrowserSessionGeneratorManager
        -

        a BrowserSessionGeneratorManager to be used instead of the Global instance

        -
      -

      Returns BrowserVerifier

    -
    - -
    -
    - -
      - -
    • -

      allows for using a specific BuildInfoManager instance. if not -set then the global BuildInfoManager.instance() will be used

      - -

      Returns

      this Verifier instance

      -
      -
      -

      Parameters

      -
        -
      • -
        buildMgr: BuildInfoManager
        -

        a BuildInfoManager instance

        -
      -

      Returns BrowserVerifier

    -
    - -
      - -
    • -

      allows for using a specific DefectManager instance. if not -set then the global DefectManager.instance() will be used

      - -

      Returns

      this Verifier instance

      -
      -
      -

      Parameters

      -
        -
      • -
        defectMgr: DefectManager
        -

        a DefectManager instance

        -
      -

      Returns BrowserVerifier

    -
    - -
      - -
    • -

      allows for setting the description to be used as the logName in any -logging output from this Verifier

      - -

      Returns

      this Verifier instance

      -
      -
      -

      Parameters

      -
        -
      • -
        description: string
        -

        the description of this Verifier

        -
      -

      Returns BrowserVerifier

    -
    - -
      - -
    • -

      allows for setting a defectId to be checked before executing the assertion. -if the referenced defectId is open then the assertion will not be run.

      - -

      Returns

      this Verifier instance

      -
      -
      -

      Parameters

      -
        -
      • -
        Rest ...defectIds: string[]
        -

        a defect identifier for your connected DefectPlugin

        -
      -

      Returns BrowserVerifier

    -
    - -
      - -
    • -

      allows for using a specific LogManager instance. if not -set then one will be created for use by this Verifier

      - -

      Returns

      this Verifier instance

      -
      -
      -

      Parameters

      -
        -
      • -
        logMgr: LogManager
        -

        a LogManager instance

        -
      -

      Returns BrowserVerifier

    -
    - -
      - -
    • -

      allows for using a specific TestCaseManager instance. if not -set then the global TestCaseManager.instance() will be used

      - -

      Returns

      this Verifier instance

      -
      -
      -

      Parameters

      -
        -
      • -
        testMgr: TestCaseManager
        -

        a TestCaseManager instance

        -
      -

      Returns BrowserVerifier

    -
    - -
      - -
    • -

      allows for setting a testId to be checked before executing the assertion -and to be reported to from any connected logging plugins that connect to -your test case management system. if all the referenced testId values should not be -run (as returned by your AbstractTestCasePlugin.shouldRun(testId)) then -the assertion will not be run. -NOTE: multiple testId values can be chained together

      - -

      Returns

      this Verifier instance

      -
      -
      -

      Parameters

      -
        -
      • -
        Rest ...testIds: string[]
        -

        a test identifier for your connected AbstractTestCasePlugin

        -
      -

      Returns BrowserVerifier

    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/classes/aft_ui_browsers.SauceLabsBrowserSession.html b/docs/classes/aft_ui_browsers.SauceLabsBrowserSession.html deleted file mode 100644 index 925a8f85..00000000 --- a/docs/classes/aft_ui_browsers.SauceLabsBrowserSession.html +++ /dev/null @@ -1,356 +0,0 @@ -SauceLabsBrowserSession | automated-functional-testing
    -
    - -
    -
    -
    - -
    -

    Hierarchy

    -
    -
    -
    -
    - -
    -
    -

    Constructors

    -
    - -
    -
    -

    Properties

    -
    - -
    _accessKey: string
    -
    - -
    _tunnel: boolean
    -
    - -
    _tunnelIdentifier: string
    -
    - -
    _username: string
    -
    -

    Accessors

    -
    - -
    -
    - -
    -
    - -
    -
    - -
      -
    • get logMgr(): LogManager
    • -
    • -

      Returns LogManager

    -
    - -
      -
    • get platform(): UiPlatform
    • -
    • -

      Returns UiPlatform

    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    -

    Methods

    -
    - -
    -
    - -
    -
    - -
    -
    - -
      - -
    • -
      -

      Type Parameters

      -
        -
      • -

        K extends keyof UiSessionOptions | "resolution" | "additionalCapabilities" | "username" | "accessKey" | "tunnel" | "tunnelIdentifier"

      • -
      • -

        V extends string | boolean | object | WebDriver | LogManager

      -
      -

      Parameters

      -
        -
      • -
        key: K
      • -
      • -
        Optional defaultVal: V
      -

      Returns V

    -
    - -
    -
    - -
    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/classes/aft_ui_browsers.SauceLabsBrowserSessionGeneratorPlugin.html b/docs/classes/aft_ui_browsers.SauceLabsBrowserSessionGeneratorPlugin.html deleted file mode 100644 index b2542b69..00000000 --- a/docs/classes/aft_ui_browsers.SauceLabsBrowserSessionGeneratorPlugin.html +++ /dev/null @@ -1,342 +0,0 @@ -SauceLabsBrowserSessionGeneratorPlugin | automated-functional-testing
    -
    - -
    -
    -
    -
    - -

    Class SauceLabsBrowserSessionGeneratorPlugin

    -
    -

    abstract class to be extended by any Browser Session Generator Plugins to be -loaded by the BrowserSessionGeneratorManager. accepts options of the following:

    -
    {
    "url": "http://url.to/selenium/grid",
    "uiplatform": "android_11_firefox_75_Google Pixel XL",
    "additionalCapabilities": {
    "someKey": "someValue"
    },
    "implicitTimeout": 3000
    } -
    -
    -
    -

    Hierarchy

    -
    -
    -
    -
    - -
    -
    -

    Constructors

    -
    - -
    -
    -

    Properties

    -
    - -
    _accessKey: string
    -
    - -
    _tunnel: boolean
    -
    - -
    _tunnelIdentifier: string
    -
    - -
    _username: string
    -
    -

    Accessors

    -
    - -
    -
    - -
    -
    - -
      -
    • get enabled(): boolean
    • -
    • -

      Returns boolean

    -
    - -
    -
    - -
      -
    • get logMgr(): LogManager
    • -
    • -

      Returns LogManager

    -
    - -
    -
    - -
    -
    - -
    -
    - -
      -
    • get uiplatform(): UiPlatform
    • -
    • -

      Returns UiPlatform

    -
    - -
    -
    - -
    -
    -

    Methods

    -
    - -
    -
    - -
    -
    - -
    -
    - -
      - -
    • -
      -

      Type Parameters

      -
        -
      • -

        K extends "uiplatform" | "logMgr" | "resolution" | "additionalCapabilities" | "enabled" | "url" | "implicitTimeout" | "username" | "accessKey" | "tunnel" | "tunnelIdentifier"

      • -
      • -

        V extends string | number | boolean | object | LogManager

      -
      -

      Parameters

      -
        -
      • -
        key: K
      • -
      • -
        Optional defaultVal: V
      -

      Returns V

    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/classes/aft_ui_browsers.SeleniumGridSessionGeneratorPlugin.html b/docs/classes/aft_ui_browsers.SeleniumGridSessionGeneratorPlugin.html deleted file mode 100644 index d7c62acd..00000000 --- a/docs/classes/aft_ui_browsers.SeleniumGridSessionGeneratorPlugin.html +++ /dev/null @@ -1,269 +0,0 @@ -SeleniumGridSessionGeneratorPlugin | automated-functional-testing
    -
    - -
    -
    -
    - -
    -

    abstract class to be extended by any Browser Session Generator Plugins to be -loaded by the BrowserSessionGeneratorManager. accepts options of the following:

    -
    {
    "url": "http://url.to/selenium/grid",
    "uiplatform": "android_11_firefox_75_Google Pixel XL",
    "additionalCapabilities": {
    "someKey": "someValue"
    },
    "implicitTimeout": 3000
    } -
    -
    -
    -

    Hierarchy

    -
    -
    -
    -
    - -
    -
    -

    Constructors

    -
    - -
    -
    -

    Accessors

    -
    - -
    -
    - -
      -
    • get enabled(): boolean
    • -
    • -

      Returns boolean

    -
    - -
    -
    - -
      -
    • get logMgr(): LogManager
    • -
    • -

      Returns LogManager

    -
    - -
    -
    - -
      -
    • get uiplatform(): UiPlatform
    • -
    • -

      Returns UiPlatform

    -
    - -
    -
    -

    Methods

    -
    - -
    -
    - -
    -
    - -
    -
    - -
      - -
    • -
      -

      Type Parameters

      -
        -
      • -

        K extends "uiplatform" | "logMgr" | "resolution" | "additionalCapabilities" | "enabled" | "url" | "implicitTimeout"

      • -
      • -

        V extends string | number | boolean | object | LogManager

      -
      -

      Parameters

      -
        -
      • -
        key: K
      • -
      • -
        Optional defaultVal: V
      -

      Returns V

    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/classes/aft_ui_mobile_apps.AppiumGridSessionGeneratorPlugin.html b/docs/classes/aft_ui_mobile_apps.AppiumGridSessionGeneratorPlugin.html deleted file mode 100644 index aaaeb513..00000000 --- a/docs/classes/aft_ui_mobile_apps.AppiumGridSessionGeneratorPlugin.html +++ /dev/null @@ -1,241 +0,0 @@ -AppiumGridSessionGeneratorPlugin | automated-functional-testing
    -
    - -
    -
    -
    - -
    -

    Hierarchy

    -
    -
    -
    -
    - -
    -
    -

    Constructors

    -
    -
    -

    Accessors

    -
    -
    -

    Methods

    -
    -
    -

    Constructors

    -
    - -
    -
    -

    Accessors

    -
    - -
    -
    - -
      -
    • get enabled(): boolean
    • -
    • -

      Returns boolean

    -
    - -
      -
    • get logMgr(): LogManager
    • -
    • -

      Returns LogManager

    -
    - -
      -
    • get uiplatform(): UiPlatform
    • -
    • -

      Returns UiPlatform

    -
    -

    Methods

    -
    - -
    -
    - -
    -
    - -
    -
    - -
      - -
    • -
      -

      Type Parameters

      -
        -
      • -

        K extends "logMgr" | "uiplatform" | "app" | "remoteOptions" | "enabled"

      • -
      • -

        V extends string | boolean | object | LogManager

      -
      -

      Parameters

      -
        -
      • -
        key: K
      • -
      • -
        Optional defaultVal: V
      -

      Returns V

    -
    - -
    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/classes/aft_ui_mobile_apps.BrowserStackAppAutomateApi.html b/docs/classes/aft_ui_mobile_apps.BrowserStackAppAutomateApi.html deleted file mode 100644 index 9a4463eb..00000000 --- a/docs/classes/aft_ui_mobile_apps.BrowserStackAppAutomateApi.html +++ /dev/null @@ -1,262 +0,0 @@ -BrowserStackAppAutomateApi | automated-functional-testing
    -
    - -
    -
    -
    - -
    -

    Hierarchy

    -
      -
    • BrowserStackAppAutomateApi
    -
    -

    Implements

    -
    -
    -
    -
    - -
    -
    -

    Constructors

    -
    -
    -

    Properties

    -
    -
    -

    Accessors

    -
    -
    -

    Methods

    -
    -
    -

    Constructors

    -
    - -
    -
    -

    Properties

    -
    - -
    _apiUrl: string
    -
    - -
    _key: string
    -
    - -
    _logMgr: LogManager
    -
    - -
    -
    - -
    _user: string
    -
    -

    Accessors

    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    -

    Methods

    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/classes/aft_ui_mobile_apps.BrowserStackMobileAppSession.html b/docs/classes/aft_ui_mobile_apps.BrowserStackMobileAppSession.html deleted file mode 100644 index 2b6f2621..00000000 --- a/docs/classes/aft_ui_mobile_apps.BrowserStackMobileAppSession.html +++ /dev/null @@ -1,295 +0,0 @@ -BrowserStackMobileAppSession | automated-functional-testing
    -
    - -
    -
    -
    - -
    -

    Hierarchy

    -
    -
    -
    -
    - -
    -
    -

    Constructors

    -
    -
    -

    Properties

    -
    -
    -

    Accessors

    -
    -
    -

    Methods

    -
    -
    -

    Constructors

    -
    - -
    -
    -

    Properties

    -
    - -
    _debug: boolean
    -
    - -
    _key: string
    -
    - -
    _local: boolean
    -
    - -
    _localIdentifier: string
    -
    - -
    _user: string
    -
    -

    Accessors

    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
      -
    • get logMgr(): LogManager
    • -
    • -

      Returns LogManager

    -
    - -
      -
    • get platform(): UiPlatform
    • -
    • -

      Returns UiPlatform

    -
    - -
    -
    -

    Methods

    -
    - -
    -
    - -
    -
    - -
      - -
    • -
      -

      Type Parameters

      -
        -
      • -

        K extends "user" | "key" | "debug" | keyof UiSessionOptions | "app" | "remoteOptions" | "local" | "localIdentifier"

      • -
      • -

        V extends string | boolean | BrowserAsync | RemoteOptions | LogManager

      -
      -

      Parameters

      -
        -
      • -
        key: K
      • -
      • -
        Optional defaultVal: V
      -

      Returns V

    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/classes/aft_ui_mobile_apps.BrowserStackMobileAppSessionGeneratorPlugin.html b/docs/classes/aft_ui_mobile_apps.BrowserStackMobileAppSessionGeneratorPlugin.html deleted file mode 100644 index 5cc0d34e..00000000 --- a/docs/classes/aft_ui_mobile_apps.BrowserStackMobileAppSessionGeneratorPlugin.html +++ /dev/null @@ -1,365 +0,0 @@ -BrowserStackMobileAppSessionGeneratorPlugin | automated-functional-testing
    -
    - -
    -
    -
    - -
    -

    Hierarchy

    -
    -
    -
    -
    - -
    -
    -

    Constructors

    -
    - -
    -
    -

    Properties

    -
    - -
    -
    - -
    _apiUrl: string
    -
    - -
    _debug: boolean
    -
    - -
    _key: string
    -
    - -
    _local: boolean
    -
    - -
    _localIdentifier: string
    -
    - -
    _user: string
    -
    -

    Accessors

    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
      -
    • get enabled(): boolean
    • -
    • -

      Returns boolean

    -
    - -
    -
    - -
    -
    - -
    -
    - -
      -
    • get logMgr(): LogManager
    • -
    • -

      Returns LogManager

    -
    - -
      -
    • get uiplatform(): UiPlatform
    • -
    • -

      Returns UiPlatform

    -
    - -
    -
    -

    Methods

    -
    - -
    -
    - -
    -
    - -
    -
    - -
      - -
    • -
      -

      Type Parameters

      -
        -
      • -

        K extends "user" | "key" | "debug" | "logMgr" | "uiplatform" | "app" | "remoteOptions" | "enabled" | "local" | "localIdentifier" | "apiUrl" | "api"

      • -
      • -

        V extends string | boolean | object | LogManager | BrowserStackAppAutomateApi

      -
      -

      Parameters

      -
        -
      • -
        key: K
      • -
      • -
        Optional defaultVal: V
      -

      Returns V

    -
    - -
    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/classes/aft_ui_mobile_apps.MobileAppFacet.html b/docs/classes/aft_ui_mobile_apps.MobileAppFacet.html deleted file mode 100644 index 3d57e18d..00000000 --- a/docs/classes/aft_ui_mobile_apps.MobileAppFacet.html +++ /dev/null @@ -1,285 +0,0 @@ -MobileAppFacet | automated-functional-testing
    -
    - -
    -
    -
    - -
    -

    Hierarchy

    -
    -
    -
    -
    - -
    -
    -

    Constructors

    -
    - -
    -
    -

    Accessors

    -
    - -
      -
    • get index(): number
    • -
    • -

      Returns number

    -
    - -
    -
    - -
      -
    • get logMgr(): LogManager
    • -
    • -

      Returns LogManager

    -
    - -
      -
    • get maxWaitMs(): number
    • -
    • -

      Returns number

    -
    - -
    -
    - -
      -
    • get retryDelayBackOff(): RetryBackOffType
    • -
    • -

      Returns RetryBackOffType

    -
    - -
      -
    • get retryDelayMs(): number
    • -
    • -

      Returns number

    -
    - -
    -
    -

    Methods

    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
      - -
    • -
      -

      Type Parameters

      -
      -
      -

      Parameters

      -
        -
      • -
        key: K
      • -
      • -
        Optional defaultVal: V
      -

      Returns V

    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/classes/aft_ui_mobile_apps.MobileAppSession.html b/docs/classes/aft_ui_mobile_apps.MobileAppSession.html deleted file mode 100644 index 5f9e9a1c..00000000 --- a/docs/classes/aft_ui_mobile_apps.MobileAppSession.html +++ /dev/null @@ -1,230 +0,0 @@ -MobileAppSession | automated-functional-testing
    -
    - -
    -
    -
    - -
    -

    Type Parameters

    -
    -
    -

    Hierarchy

    -
    -
    -
    -
    - -
    -
    -

    Constructors

    -
    -
    -

    Properties

    -
    -
    -

    Accessors

    -
    -
    -

    Methods

    -
    -
    -

    Constructors

    -
    - -
      - -
    • -
      -

      Type Parameters

      -
      -
      -

      Parameters

      -
        -
      • -
        Optional options: T
      -

      Returns MobileAppSession<T>

    -
    -

    Properties

    -
    - -
    _driver: BrowserAsync
    -
    -

    Accessors

    -
    - -
    -
    - -
      -
    • get logMgr(): LogManager
    • -
    • -

      Returns LogManager

    -
    - -
      -
    • get platform(): UiPlatform
    • -
    • -

      Returns UiPlatform

    -
    -

    Methods

    -
    - -
    -
    - -
      - -
    • -
      -

      Type Parameters

      -
        -
      • -

        T extends UiFacet<To, T>

      • -
      • -

        To extends UiFacetOptions

      -
      -

      Parameters

      -
        -
      • -
        facetType: Class<T>
      • -
      • -
        Optional options: To
      -

      Returns Promise<T>

    -
    - -
      - -
    • -
      -

      Type Parameters

      -
        -
      • -

        K extends string | number | symbol

      • -
      • -

        V

      -
      -

      Parameters

      -
        -
      • -
        key: K
      • -
      • -
        Optional defaultVal: V
      -

      Returns V

    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/classes/aft_ui_mobile_apps.MobileAppSessionGeneratorPlugin.html b/docs/classes/aft_ui_mobile_apps.MobileAppSessionGeneratorPlugin.html deleted file mode 100644 index d597159f..00000000 --- a/docs/classes/aft_ui_mobile_apps.MobileAppSessionGeneratorPlugin.html +++ /dev/null @@ -1,263 +0,0 @@ -MobileAppSessionGeneratorPlugin | automated-functional-testing
    -
    - -
    -
    -
    -
    - -

    Class MobileAppSessionGeneratorPlugin<T>Abstract

    -
    -

    Type Parameters

    -
    -
    -

    Hierarchy

    -
    -
    -
    -
    - -
    -
    -

    Constructors

    -
    -
    -

    Properties

    -
    -
    -

    Accessors

    -
    -
    -

    Methods

    -
    -
    -

    Constructors

    -
    - -
    -
    -

    Properties

    -
    - -
    _app: string
    -
    -

    Accessors

    -
    - -
    -
    - -
      -
    • get enabled(): boolean
    • -
    • -

      Returns boolean

    -
    - -
      -
    • get logMgr(): LogManager
    • -
    • -

      Returns LogManager

    -
    - -
      -
    • get uiplatform(): UiPlatform
    • -
    • -

      Returns UiPlatform

    -
    -

    Methods

    -
    - -
    -
    - -
    -
    - -
    -
    - -
      - -
    • -
      -

      Type Parameters

      -
        -
      • -

        K extends string | number | symbol

      • -
      • -

        V

      -
      -

      Parameters

      -
        -
      • -
        key: K
      • -
      • -
        Optional defaultVal: V
      -

      Returns V

    -
    - -
    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/classes/aft_ui_mobile_apps.MobileAppVerifier.html b/docs/classes/aft_ui_mobile_apps.MobileAppVerifier.html deleted file mode 100644 index 3de2a1c1..00000000 --- a/docs/classes/aft_ui_mobile_apps.MobileAppVerifier.html +++ /dev/null @@ -1,761 +0,0 @@ -MobileAppVerifier | automated-functional-testing
    -
    - -
    -
    -
    - -
    -

    Hierarchy

    -
      -
    • Verifier -
        -
      • MobileAppVerifier
    -
    -
    -
    - -
    -
    -

    Constructors

    -
    - -
    -
    -

    Properties

    -
    - -
    _assertion: Func<MobileAppVerifier, any>
    -
    - -
    _buildMgr: BuildInfoManager
    -
    - -
    _defectMgr: DefectManager
    -
    - -
    _defects: Set<string>
    -
    - -
    _description: string
    -
    - -
    _innerPromise: Promise<void>
    -
    - -
    _logMgr: LogManager
    -
    - -
    _matcher: VerifierMatcher
    -
    - -
    _session: MobileAppSession<any>
    -
    - -
    _sessionMgr: MobileAppSessionGeneratorManager
    -
    - -
    _sessionOptions: MobileAppSessionOptions
    -
    - -
    _startTime: number
    -
    - -
    _testMgr: TestCaseManager
    -
    - -
    _tests: Set<string>
    -
    -

    Accessors

    -
    - -
      -
    • get and(): this
    • -
    • -

      a syntactic way of connecting fluent functions for the Verifier

      -
      -

      Returns this

    -
    - -
      -
    • get buildMgr(): BuildInfoManager
    • -
    • -

      Returns BuildInfoManager

    -
    - -
      -
    • get defectMgr(): DefectManager
    • -
    • -

      Returns DefectManager

    -
    - -
      -
    • get logMgr(): LogManager
    • -
    • -

      a LogManager that uses either the Description -or a list of Test Ids or a uuid as the logName depending -on which is available (NOTE: description is preferred most and -will be used if other values are also present)

      -
      -

      Returns LogManager

    -
    - -
    -
    - -
    -
    - -
    -
    - -
      -
    • get testMgr(): TestCaseManager
    • -
    • -

      Returns TestCaseManager

    -
    -

    Methods

    -
    - -
      - -
    • -
      -

      Parameters

      -
        -
      • -
        status: TestStatus
      • -
      • -
        logMessage: string
      • -
      • -
        Optional testId: string
      -

      Returns Promise<TestResult>

    -
    - -
      - -
    • -
      -

      Parameters

      -
        -
      • -
        status: TestStatus
      • -
      • -
        logMessage: string
      • -
      • -
        Rest ...testIds: string[]
      -

      Returns Promise<TestResult[]>

    -
    - -
      - -
    • -

      Returns Promise<void>

    -
    - -
      - -
    • -
      -

      Parameters

      -
        -
      • -
        status: TestStatus
      • -
      • -
        Optional message: string
      -

      Returns Promise<void>

    -
    - -
      - -
    • -

      creates TestResult objects for each testId and sends these -to the LogManager.logResult function

      -
      -
      -

      Parameters

      -
        -
      • -
        status: TestStatus
      • -
      • -
        Optional message: string
      -

      Returns Promise<void>

    -
    - -
    -
    - -
      - -
    • -
      -

      Parameters

      -
        -
      • -
        Rest ...defects: string[]
      -

      Returns Promise<ProcessingResult>

    -
    - -
      - -
    • -
      -

      Parameters

      -
        -
      • -
        Rest ...tests: string[]
      -

      Returns Promise<ProcessingResult>

    -
    - -
      - -
    • -

      allows for specifying either the expected return value or a VerifierMatcher -to be used to compare the return value using the VerifierMatcher.compare() -function. if not set then only exceptions will cause a failed result on -the executed assertion

      - -

      Returns

      this Verifier instance

      -
      -
      -

      Parameters

      -
        -
      • -
        result: any
        -

        the expected result or a VerifierMatcher implementation

        -
      -

      Returns MobileAppVerifier

    -
    - -
      - -
    • -
      -

      Type Parameters

      -
        -
      • -

        TResult1 = Verifier

      • -
      • -

        TResult2 = never

      -
      -

      Parameters

      -
        -
      • -
        Optional onfulfilled: ((value: void) => TResult1 | PromiseLike<TResult1>)
        -
          -
        • -
            -
          • (value: void): TResult1 | PromiseLike<TResult1>
          • -
          • -
            -

            Parameters

            -
              -
            • -
              value: void
            -

            Returns TResult1 | PromiseLike<TResult1>

      • -
      • -
        Optional onrejected: ((reason: any) => TResult2 | PromiseLike<TResult2>)
        -
          -
        • -
            -
          • (reason: any): TResult2 | PromiseLike<TResult2>
          • -
          • -
            -

            Parameters

            -
              -
            • -
              reason: any
            -

            Returns TResult2 | PromiseLike<TResult2>

      -

      Returns Promise<TResult1 | TResult2>

    -
    - -
      - -
    • -

      the starting point for setting up a Verifier execution. Generally it is preferred -to use the verify(...) const instead of creating individual Verifier instances. -ex:

      -
      await verify(async (v: Verifier) => {
      await v.logMgr.info('doing some testing...');
      let feature = new FeatureObj();
      return await feature.returnExpectedValue();
      }).withDescription('example usage for Verifier')
      .and.withTestId('C1234')
      .returns('expected value'); -
      - -

      Returns

      this Verifier instance

      -
      -
      -

      Parameters

      -
        -
      • -
        assertion: Func<Verifier, any>
        -

        the Func<Verifier, any> function to be executed by this Verifier

        -
      -

      Returns MobileAppVerifier

    -
    - -
      - -
    • -

      allows for using a specific BuildInfoManager instance. if not -set then the global BuildInfoManager.instance() will be used

      - -

      Returns

      this Verifier instance

      -
      -
      -

      Parameters

      -
        -
      • -
        buildMgr: BuildInfoManager
        -

        a BuildInfoManager instance

        -
      -

      Returns MobileAppVerifier

    -
    - -
      - -
    • -

      allows for using a specific DefectManager instance. if not -set then the global DefectManager.instance() will be used

      - -

      Returns

      this Verifier instance

      -
      -
      -

      Parameters

      -
        -
      • -
        defectMgr: DefectManager
        -

        a DefectManager instance

        -
      -

      Returns MobileAppVerifier

    -
    - -
      - -
    • -

      allows for setting the description to be used as the logName in any -logging output from this Verifier

      - -

      Returns

      this Verifier instance

      -
      -
      -

      Parameters

      -
        -
      • -
        description: string
        -

        the description of this Verifier

        -
      -

      Returns MobileAppVerifier

    -
    - -
      - -
    • -

      allows for setting a defectId to be checked before executing the assertion. -if the referenced defectId is open then the assertion will not be run.

      - -

      Returns

      this Verifier instance

      -
      -
      -

      Parameters

      -
        -
      • -
        Rest ...defectIds: string[]
        -

        a defect identifier for your connected DefectPlugin

        -
      -

      Returns MobileAppVerifier

    -
    - -
      - -
    • -

      allows for using a specific LogManager instance. if not -set then one will be created for use by this Verifier

      - -

      Returns

      this Verifier instance

      -
      -
      -

      Parameters

      -
        -
      • -
        logMgr: LogManager
        -

        a LogManager instance

        -
      -

      Returns MobileAppVerifier

    -
    - -
      - -
    • -

      allows for passing in an instance of MobileAppSessionGeneratorManager to be -used in locating a MobileAppSessionGeneratorPlugin instance to use in -generating a MobileAppSession. -NOTE: if not set then the global const mobileAppSessionGeneratorMgr -will be used

      - -

      Returns

      this MobileAppVerifier instance

      -
      -
      -

      Parameters

      -
        -
      • -
        sessionMgr: MobileAppSessionGeneratorManager
        -

        a MobileAppSessionGeneratorManager to be used instead of the Global instance

        -
      -

      Returns MobileAppVerifier

    -
    - -
    -
    - -
      - -
    • -

      allows for using a specific TestCaseManager instance. if not -set then the global TestCaseManager.instance() will be used

      - -

      Returns

      this Verifier instance

      -
      -
      -

      Parameters

      -
        -
      • -
        testMgr: TestCaseManager
        -

        a TestCaseManager instance

        -
      -

      Returns MobileAppVerifier

    -
    - -
      - -
    • -

      allows for setting a testId to be checked before executing the assertion -and to be reported to from any connected logging plugins that connect to -your test case management system. if all the referenced testId values should not be -run (as returned by your AbstractTestCasePlugin.shouldRun(testId)) then -the assertion will not be run. -NOTE: multiple testId values can be chained together

      - -

      Returns

      this Verifier instance

      -
      -
      -

      Parameters

      -
        -
      • -
        Rest ...testIds: string[]
        -

        a test identifier for your connected AbstractTestCasePlugin

        -
      -

      Returns MobileAppVerifier

    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/classes/aft_ui_mobile_apps.SauceLabsMobileAppSession.html b/docs/classes/aft_ui_mobile_apps.SauceLabsMobileAppSession.html deleted file mode 100644 index adf2671e..00000000 --- a/docs/classes/aft_ui_mobile_apps.SauceLabsMobileAppSession.html +++ /dev/null @@ -1,278 +0,0 @@ -SauceLabsMobileAppSession | automated-functional-testing
    -
    - -
    -
    -
    - -
    -

    Hierarchy

    -
    -
    -
    -
    - -
    -
    -

    Constructors

    -
    -
    -

    Properties

    -
    -
    -

    Accessors

    -
    -
    -

    Methods

    -
    -
    -

    Constructors

    -
    - -
    -
    -

    Properties

    -
    - -
    _accessKey: string
    -
    - -
    _tunnel: boolean
    -
    - -
    _tunnelIdentifier: string
    -
    - -
    _username: string
    -
    -

    Accessors

    -
    - -
    -
    - -
    -
    - -
      -
    • get logMgr(): LogManager
    • -
    • -

      Returns LogManager

    -
    - -
      -
    • get platform(): UiPlatform
    • -
    • -

      Returns UiPlatform

    -
    - -
    -
    - -
    -
    - -
    -
    -

    Methods

    -
    - -
    -
    - -
    -
    - -
      - -
    • -
      -

      Type Parameters

      -
        -
      • -

        K extends keyof UiSessionOptions | "app" | "remoteOptions" | "tunnelIdentifier" | "accessKey" | "username" | "tunnel"

      • -
      • -

        V extends string | boolean | BrowserAsync | RemoteOptions | LogManager

      -
      -

      Parameters

      -
        -
      • -
        key: K
      • -
      • -
        Optional defaultVal: V
      -

      Returns V

    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/classes/aft_ui_mobile_apps.SauceLabsMobileAppSessionGeneratorPlugin.html b/docs/classes/aft_ui_mobile_apps.SauceLabsMobileAppSessionGeneratorPlugin.html deleted file mode 100644 index 29112252..00000000 --- a/docs/classes/aft_ui_mobile_apps.SauceLabsMobileAppSessionGeneratorPlugin.html +++ /dev/null @@ -1,331 +0,0 @@ -SauceLabsMobileAppSessionGeneratorPlugin | automated-functional-testing
    -
    - -
    -
    -
    - -
    -

    Hierarchy

    -
    -
    -
    -
    - -
    -
    -

    Constructors

    -
    - -
    -
    -

    Properties

    -
    - -
    _accessKey: string
    -
    - -
    _apiUrl: string
    -
    - -
    _tunnel: boolean
    -
    - -
    _tunnelIdentifier: string
    -
    - -
    _username: string
    -
    -

    Accessors

    -
    - -
    -
    - -
    -
    - -
    -
    - -
      -
    • get enabled(): boolean
    • -
    • -

      Returns boolean

    -
    - -
      -
    • get logMgr(): LogManager
    • -
    • -

      Returns LogManager

    -
    - -
    -
    - -
    -
    - -
      -
    • get uiplatform(): UiPlatform
    • -
    • -

      Returns UiPlatform

    -
    - -
    -
    -

    Methods

    -
    - -
    -
    - -
    -
    - -
    -
    - -
      - -
    • -
      -

      Type Parameters

      -
        -
      • -

        K extends "logMgr" | "uiplatform" | "app" | "remoteOptions" | "enabled" | "tunnelIdentifier" | "accessKey" | "apiUrl" | "username" | "tunnel"

      • -
      • -

        V extends string | boolean | object | LogManager

      -
      -

      Parameters

      -
        -
      • -
        key: K
      • -
      • -
        Optional defaultVal: V
      -

      Returns V

    -
    - -
    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/classes/aft_ui_selenium.GridSessionGeneratorPlugin.html b/docs/classes/aft_ui_selenium.GridSessionGeneratorPlugin.html new file mode 100644 index 00000000..04e98dd0 --- /dev/null +++ b/docs/classes/aft_ui_selenium.GridSessionGeneratorPlugin.html @@ -0,0 +1,184 @@ +GridSessionGeneratorPlugin | automated-functional-testing
    +
    + +
    +
    +
    + +
    +

    Hierarchy

    +
      +
    • UiSessionGeneratorPlugin +
        +
      • GridSessionGeneratorPlugin
    +
    +
    +
    + +
    +
    +

    Constructors

    +
    +
    +

    Properties

    +
    +
    +

    Accessors

    +
    +
    +

    Methods

    +
    +
    +

    Constructors

    +
    + +
      + +
    • +
      +

      Parameters

      +
        +
      • +
        Optional aftCfg: AftConfig
      +

      Returns GridSessionGeneratorPlugin

    +
    +

    Properties

    +
    + +
    _reporter: Reporter
    +
    +

    Accessors

    +
    + +
      +
    • get aftCfg(): AftConfig
    • +
    • +

      Returns AftConfig

    +
    + +
      +
    • get aftLogger(): AftLogger
    • +
    • +

      Returns AftLogger

    +
    + +
      +
    • get enabled(): boolean
    • +
    • +

      Returns boolean

    +
    + +
    +
    +

    Methods

    +
    + +
    +
    +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/classes/aft_ui_selenium.LocalSessionGeneratorPlugin.html b/docs/classes/aft_ui_selenium.LocalSessionGeneratorPlugin.html new file mode 100644 index 00000000..6bc17555 --- /dev/null +++ b/docs/classes/aft_ui_selenium.LocalSessionGeneratorPlugin.html @@ -0,0 +1,162 @@ +LocalSessionGeneratorPlugin | automated-functional-testing
    +
    + +
    +
    +
    + +
    +

    Hierarchy

    +
      +
    • UiSessionGeneratorPlugin +
        +
      • LocalSessionGeneratorPlugin
    +
    +
    +
    + +
    +
    +

    Constructors

    +
    +
    +

    Accessors

    +
    +
    +

    Methods

    +
    +
    +

    Constructors

    +
    + +
      + +
    • +
      +

      Parameters

      +
        +
      • +
        Optional aftCfg: AftConfig
      +

      Returns LocalSessionGeneratorPlugin

    +
    +

    Accessors

    +
    + +
      +
    • get aftCfg(): AftConfig
    • +
    • +

      Returns AftConfig

    +
    + +
      +
    • get aftLogger(): AftLogger
    • +
    • +

      Returns AftLogger

    +
    + +
      +
    • get enabled(): boolean
    • +
    • +

      Returns boolean

    +
    +

    Methods

    +
    + +
    +
    +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/classes/aft_ui_selenium.SeleniumComponent.html b/docs/classes/aft_ui_selenium.SeleniumComponent.html new file mode 100644 index 00000000..5b3019c6 --- /dev/null +++ b/docs/classes/aft_ui_selenium.SeleniumComponent.html @@ -0,0 +1,225 @@ +SeleniumComponent | automated-functional-testing
    +
    + +
    +
    +
    + +
    +

    Hierarchy

    +
      +
    • UiComponent +
        +
      • SeleniumComponent
    +
    +
    +
    + +
    +
    +

    Constructors

    +
    +
    +

    Properties

    +
    +
    +

    Accessors

    +
    +
    +

    Methods

    +
    +
    +

    Constructors

    +
    + +
      + +
    • +
      +

      Parameters

      +
        +
      • +
        options: UiComponentOptions
      +

      Returns SeleniumComponent

    +
    +

    Properties

    +
    + +
    _driver: unknown
    +
    + +
    _locator: unknown
    +
    + +
    _parent: Func<void, Promise<unknown>>
    +
    + +
    aftCfg: AftConfig
    +
    + +
    reporter: Reporter
    +
    +

    Accessors

    +
    + +
    +
    + +
    +
    + +
    +
    +

    Methods

    +
    + +
      + +
    • +
      +

      Type Parameters

      +
        +
      • +

        F extends UiComponent<F>

      +
      +

      Parameters

      +
        +
      • +
        componentType: Class<F>
      • +
      • +
        Optional options: Partial<UiComponentOptions>
      +

      Returns F

    +
    + +
    +
    +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/classes/aft_ui_selenium.SeleniumVerifier.html b/docs/classes/aft_ui_selenium.SeleniumVerifier.html new file mode 100644 index 00000000..08dab7de --- /dev/null +++ b/docs/classes/aft_ui_selenium.SeleniumVerifier.html @@ -0,0 +1,667 @@ +SeleniumVerifier | automated-functional-testing
    +
    + +
    +
    +
    + +
    +

    Hierarchy

    +
      +
    • Verifier +
        +
      • SeleniumVerifier
    +
    +
    +
    + +
    +
    +

    Constructors

    +
    + +
      + +
    • +

      Returns SeleniumVerifier

    +
    +

    Properties

    +
    + +
    _actionMap: Map<VerifierEvent, Action<void>>
    +
    + +
    _aftCfg?: AftConfig
    +
    + +
    _assertion: Func<SeleniumVerifier, any>
    +
    + +
    _buildInfoMgr: BuildInfoManager
    +
    + +
    _description: string
    +
    + +
    _driver: unknown
    +
    + +
    _innerPromise: Promise<void>
    +
    + +
    _matcher: VerifierMatcher
    +
    + +
    _policyEngMgr: TestExecutionPolicyManager
    +
    + +
    _reporter: Reporter
    +
    + +
    _sessionMgr: UiSessionGeneratorManager
    +
    + +
    _sessionOptions: Record<string, any> = {}
    +
    + +
    _startTime: number
    +
    + +
    _testIds: Set<string>
    +
    +

    Accessors

    +
    + +
      +
    • get aftCfg(): AftConfig
    • +
    • +

      Returns AftConfig

    +
    + +
      +
    • get and(): this
    • +
    • +

      a syntactic way of connecting fluent functions for the Verifier

      +
      +

      Returns this

    +
    + +
      +
    • get buildInfoMgr(): BuildInfoManager
    • +
    • +

      Returns BuildInfoManager

    +
    + +
    +
    + +
    +
    + +
      +
    • get policyEngMgr(): TestExecutionPolicyManager
    • +
    • +

      Returns TestExecutionPolicyManager

    +
    + +
      +
    • get reporter(): Reporter
    • +
    • +

      a Reporter that uses either the Description +or a list of Test Ids or a uuid as the logName depending +on which is available (NOTE: description is preferred most and +will be used if other values are also present)

      +
      +

      Returns Reporter

    +
    + +
    +
    +

    Methods

    +
    + +
      + +
    • +
      +

      Parameters

      +
        +
      • +
        status: TestStatus
      • +
      • +
        logMessage: string
      • +
      • +
        Optional testId: string
      +

      Returns Promise<TestResult>

    +
    + +
      + +
    • +
      +

      Parameters

      +
        +
      • +
        status: TestStatus
      • +
      • +
        logMessage: string
      • +
      • +
        Rest ...testIds: string[]
      +

      Returns Promise<TestResult[]>

    +
    + +
      + +
    • +

      Returns Promise<void>

    +
    + +
      + +
    • +
      +

      Parameters

      +
        +
      • +
        status: TestStatus
      • +
      • +
        Optional message: string
      +

      Returns Promise<void>

    +
    + +
      + +
    • +

      creates TestResult objects for each testId and sends these +to the Reporter.logResult function

      +
      +
      +

      Parameters

      +
        +
      • +
        status: TestStatus
      • +
      • +
        Optional message: string
      +

      Returns Promise<void>

    +
    + +
    +
    + +
    +
    + +
      + +
    • +

      allows for specifying actions to be called on certain events

      + +

      Returns

      a reference to this {Verifier} instance

      +
      +
      +

      Parameters

      +
        +
      • +
        event: VerifierEvent
        +

        an event trigger

        +
      • +
      • +
        action: Action<void>
        +

        the action to be run on the event

        +
      +

      Returns SeleniumVerifier

    +
    + +
      + +
    • +

      allows for specifying either the expected return value or a VerifierMatcher +to be used to compare the return value using the VerifierMatcher.compare() +function. if not set then only exceptions will cause a failed result on +the executed assertion

      + +

      Returns

      this Verifier instance

      +
      +
      +

      Parameters

      +
        +
      • +
        result: any
        +

        the expected result or a VerifierMatcher implementation

        +
      +

      Returns SeleniumVerifier

    +
    + +
      + +
    • +

      checks if any of the supplied test ids should be run and returns true if at least +one of them should

      + +

      Returns

      a ProcessingResult<boolean> indicating if the testing should proceed

      +
      +

      Returns Promise<ProcessingResult<boolean>>

    +
    + +
      + +
    • +
      +

      Type Parameters

      +
        +
      • +

        TResult1 = Verifier

      • +
      • +

        TResult2 = never

      +
      +

      Parameters

      +
        +
      • +
        Optional onfulfilled: ((value: void) => TResult1 | PromiseLike<TResult1>)
        +
          +
        • +
            +
          • (value: void): TResult1 | PromiseLike<TResult1>
          • +
          • +
            +

            Parameters

            +
              +
            • +
              value: void
            +

            Returns TResult1 | PromiseLike<TResult1>

      • +
      • +
        Optional onrejected: ((reason: any) => TResult2 | PromiseLike<TResult2>)
        +
          +
        • +
            +
          • (reason: any): TResult2 | PromiseLike<TResult2>
          • +
          • +
            +

            Parameters

            +
              +
            • +
              reason: any
            +

            Returns TResult2 | PromiseLike<TResult2>

      +

      Returns Promise<TResult1 | TResult2>

    +
    + +
      + +
    • +

      the starting point for setting up a Verifier execution. Generally it is preferred +to use the verify(...) const instead of creating individual Verifier instances. +ex:

      +
      await verify(async (v: Verifier) => {
      await v.reporter.info('doing some testing...');
      let feature = new FeatureObj();
      return await feature.returnExpectedValue();
      }).withDescription('example usage for Verifier')
      .and.withTestId('C1234')
      .returns('expected value'); +
      + +

      Returns

      this Verifier instance

      +
      +
      +

      Parameters

      +
        +
      • +
        assertion: Func<Verifier, any>
        +

        the Func<Verifier, any> function to be executed by this Verifier

        +
      +

      Returns SeleniumVerifier

    +
    + +
      + +
    • +

      allows specifying additional session options to be merged with those +specified in your aftconfig.json file under the UiSessionConfig.options +property. for example, if your aftconfig.json already contained the +following options:

      +
      // aftconfig.json
      {
      "UiSessionConfig": {
      "generatorName": "foo-bar-baz",
      "options": {
      "bstack:options": {
      "user": "foo1234",
      "key": "klajsdflk1241234"
      }
      }
      }
      } +
      +

      and you provided the following via opts here:

      +
      verifyWithSelenium(...).withAdditionalSessionOptions({
      "bstack:options": {
      "sessionName": "FooBarBaz"
      }
      }); +
      +

      your resulting options passed to the {UiSessionGeneratorManager} would +look like:

      +
      {
      "bstack:options": {
      "user": "foo1234",
      "key": "klajsdflk1241234",
      "sessionName": "FooBarBaz"
      }
      } +
      + +

      Returns

      a reference to {this}

      +
      +
      +

      Parameters

      +
        +
      • +
        opts: Record<string, any>
        +

        a {Record<string, any>} containing capabilities to be used

        +
      +

      Returns SeleniumVerifier

    +
    + +
      + +
    • +

      allows for setting the description to be used as the logName in any +logging output from this Verifier

      + +

      Returns

      this Verifier instance

      +
      +
      +

      Parameters

      +
        +
      • +
        description: string
        +

        the description of this Verifier

        +
      +

      Returns SeleniumVerifier

    +
    + +
      + +
    • +

      allows for setting a testId to be checked before executing the assertion +and to be reported to from any connected logging plugins that connect to +your test case management system. if all the referenced testId values should not be +run (as returned by your TestExecutionPolicyPlugin.shouldRun(testId)) then +the assertion will not be run. +NOTE: multiple testId values can be chained together

      + +

      Returns

      this Verifier instance

      +
      +
      +

      Parameters

      +
        +
      • +
        Rest ...testIds: string[]
        +

        a test identifier for your connected TestExecutionPolicyPlugin

        +
      +

      Returns SeleniumVerifier

    +
    +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/classes/aft_ui_webdriverio.WebdriverIoComponent.html b/docs/classes/aft_ui_webdriverio.WebdriverIoComponent.html new file mode 100644 index 00000000..036e0f64 --- /dev/null +++ b/docs/classes/aft_ui_webdriverio.WebdriverIoComponent.html @@ -0,0 +1,225 @@ +WebdriverIoComponent | automated-functional-testing
    +
    + +
    +
    +
    + +
    +

    Hierarchy

    +
      +
    • UiComponent +
        +
      • WebdriverIoComponent
    +
    +
    +
    + +
    +
    +

    Constructors

    +
    +
    +

    Properties

    +
    +
    +

    Accessors

    +
    +
    +

    Methods

    +
    +
    +

    Constructors

    +
    + +
      + +
    • +
      +

      Parameters

      +
        +
      • +
        options: UiComponentOptions
      +

      Returns WebdriverIoComponent

    +
    +

    Properties

    +
    + +
    _driver: unknown
    +
    + +
    _locator: unknown
    +
    + +
    _parent: Func<void, Promise<unknown>>
    +
    + +
    aftCfg: AftConfig
    +
    + +
    reporter: Reporter
    +
    +

    Accessors

    +
    + +
    +
    + +
    +
    + +
    +
    +

    Methods

    +
    + +
      + +
    • +
      +

      Type Parameters

      +
        +
      • +

        F extends UiComponent<F>

      +
      +

      Parameters

      +
        +
      • +
        componentType: Class<F>
      • +
      • +
        Optional options: Partial<UiComponentOptions>
      +

      Returns F

    +
    + +
    +
    +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/classes/aft_ui_webdriverio.WebdriverIoRemoteSessionGeneratorPlugin.html b/docs/classes/aft_ui_webdriverio.WebdriverIoRemoteSessionGeneratorPlugin.html new file mode 100644 index 00000000..634ebef7 --- /dev/null +++ b/docs/classes/aft_ui_webdriverio.WebdriverIoRemoteSessionGeneratorPlugin.html @@ -0,0 +1,162 @@ +WebdriverIoRemoteSessionGeneratorPlugin | automated-functional-testing
    +
    + +
    +
    +
    + +
    +

    Hierarchy

    +
      +
    • UiSessionGeneratorPlugin +
        +
      • WebdriverIoRemoteSessionGeneratorPlugin
    +
    +
    +
    + +
    +
    +

    Constructors

    +
    +
    +

    Accessors

    +
    +
    +

    Methods

    +
    +
    +

    Constructors

    +
    + +
    +
    +

    Accessors

    +
    + +
      +
    • get aftCfg(): AftConfig
    • +
    • +

      Returns AftConfig

    +
    + +
      +
    • get aftLogger(): AftLogger
    • +
    • +

      Returns AftLogger

    +
    + +
      +
    • get enabled(): boolean
    • +
    • +

      Returns boolean

    +
    +

    Methods

    +
    + +
    +
    +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/classes/aft_ui_webdriverio.WebdriverIoVerifier.html b/docs/classes/aft_ui_webdriverio.WebdriverIoVerifier.html new file mode 100644 index 00000000..b4904b34 --- /dev/null +++ b/docs/classes/aft_ui_webdriverio.WebdriverIoVerifier.html @@ -0,0 +1,667 @@ +WebdriverIoVerifier | automated-functional-testing
    +
    + +
    +
    +
    + +
    +

    Hierarchy

    +
      +
    • Verifier +
        +
      • WebdriverIoVerifier
    +
    +
    +
    + +
    +
    +

    Constructors

    +
    + +
    +
    +

    Properties

    +
    + +
    _actionMap: Map<VerifierEvent, Action<void>>
    +
    + +
    _aftCfg?: AftConfig
    +
    + +
    _assertion: Func<WebdriverIoVerifier, any>
    +
    + +
    _browser: unknown
    +
    + +
    _buildInfoMgr: BuildInfoManager
    +
    + +
    _description: string
    +
    + +
    _innerPromise: Promise<void>
    +
    + +
    _matcher: VerifierMatcher
    +
    + +
    _policyEngMgr: TestExecutionPolicyManager
    +
    + +
    _reporter: Reporter
    +
    + +
    _sessionMgr: UiSessionGeneratorManager
    +
    + +
    _sessionOptions: Record<string, any>
    +
    + +
    _startTime: number
    +
    + +
    _testIds: Set<string>
    +
    +

    Accessors

    +
    + +
      +
    • get aftCfg(): AftConfig
    • +
    • +

      Returns AftConfig

    +
    + +
      +
    • get and(): this
    • +
    • +

      a syntactic way of connecting fluent functions for the Verifier

      +
      +

      Returns this

    +
    + +
    +
    + +
      +
    • get buildInfoMgr(): BuildInfoManager
    • +
    • +

      Returns BuildInfoManager

    +
    + +
    +
    + +
      +
    • get policyEngMgr(): TestExecutionPolicyManager
    • +
    • +

      Returns TestExecutionPolicyManager

    +
    + +
      +
    • get reporter(): Reporter
    • +
    • +

      a Reporter that uses either the Description +or a list of Test Ids or a uuid as the logName depending +on which is available (NOTE: description is preferred most and +will be used if other values are also present)

      +
      +

      Returns Reporter

    +
    + +
    +
    +

    Methods

    +
    + +
      + +
    • +
      +

      Parameters

      +
        +
      • +
        status: TestStatus
      • +
      • +
        logMessage: string
      • +
      • +
        Optional testId: string
      +

      Returns Promise<TestResult>

    +
    + +
      + +
    • +
      +

      Parameters

      +
        +
      • +
        status: TestStatus
      • +
      • +
        logMessage: string
      • +
      • +
        Rest ...testIds: string[]
      +

      Returns Promise<TestResult[]>

    +
    + +
      + +
    • +

      Returns Promise<void>

    +
    + +
      + +
    • +
      +

      Parameters

      +
        +
      • +
        status: TestStatus
      • +
      • +
        Optional message: string
      +

      Returns Promise<void>

    +
    + +
      + +
    • +

      creates TestResult objects for each testId and sends these +to the Reporter.logResult function

      +
      +
      +

      Parameters

      +
        +
      • +
        status: TestStatus
      • +
      • +
        Optional message: string
      +

      Returns Promise<void>

    +
    + +
    +
    + +
    +
    + +
      + +
    • +

      allows for specifying actions to be called on certain events

      + +

      Returns

      a reference to this {Verifier} instance

      +
      +
      +

      Parameters

      +
        +
      • +
        event: VerifierEvent
        +

        an event trigger

        +
      • +
      • +
        action: Action<void>
        +

        the action to be run on the event

        +
      +

      Returns WebdriverIoVerifier

    +
    + +
      + +
    • +

      allows for specifying either the expected return value or a VerifierMatcher +to be used to compare the return value using the VerifierMatcher.compare() +function. if not set then only exceptions will cause a failed result on +the executed assertion

      + +

      Returns

      this Verifier instance

      +
      +
      +

      Parameters

      +
        +
      • +
        result: any
        +

        the expected result or a VerifierMatcher implementation

        +
      +

      Returns WebdriverIoVerifier

    +
    + +
      + +
    • +

      checks if any of the supplied test ids should be run and returns true if at least +one of them should

      + +

      Returns

      a ProcessingResult<boolean> indicating if the testing should proceed

      +
      +

      Returns Promise<ProcessingResult<boolean>>

    +
    + +
      + +
    • +
      +

      Type Parameters

      +
        +
      • +

        TResult1 = Verifier

      • +
      • +

        TResult2 = never

      +
      +

      Parameters

      +
        +
      • +
        Optional onfulfilled: ((value: void) => TResult1 | PromiseLike<TResult1>)
        +
          +
        • +
            +
          • (value: void): TResult1 | PromiseLike<TResult1>
          • +
          • +
            +

            Parameters

            +
              +
            • +
              value: void
            +

            Returns TResult1 | PromiseLike<TResult1>

      • +
      • +
        Optional onrejected: ((reason: any) => TResult2 | PromiseLike<TResult2>)
        +
          +
        • +
            +
          • (reason: any): TResult2 | PromiseLike<TResult2>
          • +
          • +
            +

            Parameters

            +
              +
            • +
              reason: any
            +

            Returns TResult2 | PromiseLike<TResult2>

      +

      Returns Promise<TResult1 | TResult2>

    +
    + +
      + +
    • +

      the starting point for setting up a Verifier execution. Generally it is preferred +to use the verify(...) const instead of creating individual Verifier instances. +ex:

      +
      await verify(async (v: Verifier) => {
      await v.reporter.info('doing some testing...');
      let feature = new FeatureObj();
      return await feature.returnExpectedValue();
      }).withDescription('example usage for Verifier')
      .and.withTestId('C1234')
      .returns('expected value'); +
      + +

      Returns

      this Verifier instance

      +
      +
      +

      Parameters

      +
        +
      • +
        assertion: Func<Verifier, any>
        +

        the Func<Verifier, any> function to be executed by this Verifier

        +
      +

      Returns WebdriverIoVerifier

    +
    + +
      + +
    • +

      allows specifying additional session options to be merged with those +specified in your aftconfig.json file under the UiSessionConfig.options +property. for example, if your aftconfig.json already contained the +following options:

      +
      // aftconfig.json
      {
      "UiSessionConfig": {
      "generatorName": "foo-bar-baz",
      "options": {
      "bstack:options": {
      "user": "foo1234",
      "key": "klajsdflk1241234"
      }
      }
      }
      } +
      +

      and you provided the following via opts here:

      +
      verifyWithWebdriverIO(...).withAdditionalSessionOptions({
      "bstack:options": {
      "sessionName": "FooBarBaz"
      }
      }); +
      +

      your resulting options passed to the {UiSessionGeneratorManager} would +look like:

      +
      {
      "bstack:options": {
      "user": "foo1234",
      "key": "klajsdflk1241234",
      "sessionName": "FooBarBaz"
      }
      } +
      + +

      Returns

      a reference to {this}

      +
      +
      +

      Parameters

      +
        +
      • +
        opts: Record<string, any>
        +

        a {Record<string, any>} containing capabilities to be used

        +
      +

      Returns WebdriverIoVerifier

    +
    + +
      + +
    • +

      allows for setting the description to be used as the logName in any +logging output from this Verifier

      + +

      Returns

      this Verifier instance

      +
      +
      +

      Parameters

      +
        +
      • +
        description: string
        +

        the description of this Verifier

        +
      +

      Returns WebdriverIoVerifier

    +
    + +
      + +
    • +

      allows for setting a testId to be checked before executing the assertion +and to be reported to from any connected logging plugins that connect to +your test case management system. if all the referenced testId values should not be +run (as returned by your TestExecutionPolicyPlugin.shouldRun(testId)) then +the assertion will not be run. +NOTE: multiple testId values can be chained together

      + +

      Returns

      this Verifier instance

      +
      +
      +

      Parameters

      +
        +
      • +
        Rest ...testIds: string[]
        +

        a test identifier for your connected TestExecutionPolicyPlugin

        +
      +

      Returns WebdriverIoVerifier

    +
    +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/classes/aft_web_services.HttpService.html b/docs/classes/aft_web_services.HttpService.html new file mode 100644 index 00000000..6f483e58 --- /dev/null +++ b/docs/classes/aft_web_services.HttpService.html @@ -0,0 +1,210 @@ +HttpService | automated-functional-testing
    +
    + +
    +
    +
    + +
    +

    supports performing requests over http / https returning the response as a +HttpResponse object. Requests should include a URL at a minimum, +but may also specify additional details such as headers, auto redirect, +post data and the request method (GET|POST|PUT|DELETE|UPDATE) +ex:

    +
    await httpService.performRequest({url: 'https://some.domain/path'});
    +
    +

    or fully as:

    +
    await httpService.performRequest({
    url: 'https://some.domain/path',
    allowAutoRedirect: false,
    headers: {"Authorization": "basic AS0978FASLKLJA/=="},
    method: 'POST',
    postData: someObject,
    multipart: false
    }); +
    +

    or multipart post as:

    +
    let formData = new FormData();
    formData.append("Authorization": "basic AS0978FASLKLJA/==");
    await httpService.performRequest({
    url: 'https://some.domain/path',
    allowAutoRedirect: false,
    method: 'POST',
    postData: formData,
    multipart: true
    }); +
    +
    +
    +

    Hierarchy

    +
      +
    • HttpService
    +
    +
    +
    + +
    +
    +

    Constructors

    +
    +
    +

    Properties

    +
    +
    +

    Methods

    +
    +
    +

    Constructors

    +
    + +
    +
    +

    Properties

    +
    + +
    aftCfg: AftConfig
    +
    +

    Methods

    +
    + +
    +
    + +
    +
    + +
      + +
    • +

      issues a request over http / https and returns the response as a +HttpResponse object. Requests should include a URL at a minimum, +but may also specify additional details such as headers, auto redirect, +post data and the request method (GET|POST|PUT|DELETE|UPDATE) +ex:

      +
      await httpService.performRequest({url: 'https://some.domain/path'});
      +
      +

      or fully as:

      +
      await httpService.performRequest({
      url: 'https://some.domain/path',
      allowAutoRedirect: false,
      headers: {"Authorization": "basic AS0978FASLKLJA/=="},
      method: 'POST',
      postData: someObject,
      multipart: false
      }); +
      +

      or multipart post as:

      +
      let formData = new FormData();
      formData.append("Authorization": "basic AS0978FASLKLJA/==");
      await httpService.performRequest({
      url: 'https://some.domain/path',
      allowAutoRedirect: false,
      method: 'POST',
      postData: formData,
      multipart: true
      }); +
      +
      +
      +

      Parameters

      +
        +
      • +
        Optional req: HttpRequest
        +

        a HttpResponse object that specifies details of the request

        +
      +

      Returns Promise<HttpResponse>

    +
    + +
    +
    +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/classes/aft_web_services.HttpServiceConfig.html b/docs/classes/aft_web_services.HttpServiceConfig.html new file mode 100644 index 00000000..e5f71802 --- /dev/null +++ b/docs/classes/aft_web_services.HttpServiceConfig.html @@ -0,0 +1,140 @@ +HttpServiceConfig | automated-functional-testing
    +
    + +
    +
    +
    + +
    +

    Hierarchy

    +
      +
    • HttpServiceConfig
    +
    +
    +
    + +
    +
    +

    Constructors

    +
    + +
    +
    +

    Properties

    +
    + +
    defaultAllowRedirect: boolean = true
    +
    + +
    defaultHeaders: OutgoingHttpHeaders = {}
    +
    + +
    defaultMethod: HttpMethod = 'GET'
    +
    + +
    defaultMultipart: boolean = false
    +
    + +
    defaultPostData: string
    +
    + +
    defaultUrl: string = 'http://127.0.0.1'
    +
    +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/functions/aft_core.Err.full.html b/docs/functions/aft_core.Err.full.html index 2664289d..bfff28c3 100644 --- a/docs/functions/aft_core.Err.full.html +++ b/docs/functions/aft_core.Err.full.html @@ -21,7 +21,7 @@

    Function full

  • Returns

    a full length string formatted as

    -
    Error.name: Error.message
    Error.stack +
    Error.name: Error.message
    Error.stack

    where the full Error details are preserved

    @@ -34,7 +34,7 @@
    err: any
  • Returns string

    +
  • Defined in aft-core/src/helpers/err.ts:177
  • Generated using TypeDoc

    diff --git a/docs/functions/aft_core.Err.handle.html b/docs/functions/aft_core.Err.handle.html index 5fc4a7fa..adf44587 100644 --- a/docs/functions/aft_core.Err.handle.html +++ b/docs/functions/aft_core.Err.handle.html @@ -17,9 +17,9 @@

    Function handle

      - +
    • -

      calls the passed in Func<void, T | PromiseLike<T>> and handles any errors

      +

      calls the passed in Func<void, T> and handles any errors

      Returns

      the result of the passed in func or null if an error is thrown

      @@ -27,26 +27,21 @@

      Returns

      the result of the passed in func or nullType Parameters

      • -

        T extends unknown

    +

    T

    Parameters

    • -
      func: Func<void, T | PromiseLike<T>>
      +
      func: Func<void, T>

      a function to be run inside a try-catch

    • -
      Optional optsOrLogMgr: LogManager | ErrOptions
      -

      an ErrOptions object containing options for this handler or a -LogManager used to log any captured Error (defaults to undefined)

      -
      -

      WARNING passing a LogManager is deprecated and you should instead add the -LogManager using the logMgr field in the ErrOptions instance)

      -
      +
      Optional opts: Partial<ErrOptions>
      +

      an ErrOptions object containing options for this call to handle

    -

    Returns Promise<T>

    Generated using TypeDoc

    diff --git a/docs/interfaces/aft_core.IHasOptions.html b/docs/functions/aft_core.Err.handleAsync.html similarity index 51% rename from docs/interfaces/aft_core.IHasOptions.html rename to docs/functions/aft_core.Err.handleAsync.html index e40a8a4c..4274aeb0 100644 --- a/docs/interfaces/aft_core.IHasOptions.html +++ b/docs/functions/aft_core.Err.handleAsync.html @@ -1,4 +1,4 @@ -IHasOptions | automated-functional-testing
    +handleAsync | automated-functional-testing
    -
    -

    Type Parameters

    -
      -
    • -

      T extends object

    -
    -

    Hierarchy

    -
      -
    • IHasOptions
    +
  • Err
  • +
  • handleAsync
  • +

    Function handleAsync

    -

    Implemented by

    -
    -
    -
    -
    - -
    -
    -

    Methods

    -
    -
    -

    Methods

    -
    - -
      - +
        +
      • +

        calls the passed in Func<void, PromiseLike<T>> and handles any errors

        + +

        Returns

        the result of the passed in func or null if an error is thrown

        +

        Type Parameters

        • -

          K extends string | number | symbol

        • -
        • -

          V

        +

        T

    Parameters

    • -
      key: K
    • +
      func: Func<void, PromiseLike<T>>
      +

      a function to be run inside a try-catch

      +
    • -
      Optional defaultVal: V
    -

    Returns V

    +
  • Defined in aft-core/src/helpers/err.ts:216
  • +
  • full
  • +
  • handle
  • +
  • handleAsync
  • +
  • short
  • Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/functions/aft_core.Err.short.html b/docs/functions/aft_core.Err.short.html index 9090e75e..c02a7f9a 100644 --- a/docs/functions/aft_core.Err.short.html +++ b/docs/functions/aft_core.Err.short.html @@ -32,7 +32,7 @@
    err: any

    Returns string

    +
  • Defined in aft-core/src/helpers/err.ts:162
  • Generated using TypeDoc

    diff --git a/docs/functions/aft_core.ExpiringFileLock.get.html b/docs/functions/aft_core.ExpiringFileLock.get.html new file mode 100644 index 00000000..e640624a --- /dev/null +++ b/docs/functions/aft_core.ExpiringFileLock.get.html @@ -0,0 +1,96 @@ +get | automated-functional-testing
    +
    + +
    +
    +
    + +
    +
      + +
    • +

      creates a new {ExpiringFileLock} that can be used to ensure separate processes cannot cause +a race condition when accessing a shared resource

      + +

      Returns

      an {ExpiringFileLock} instance

      +
      +
      +

      Parameters

      +
        +
      • +
        name: string
        +

        the name of the lock file

        +
      • +
      • +
        Optional wait: number
        +

        the number of milliseconds to wait for a lock to be acquired

        +
      • +
      • +
        Optional hold: number
        +

        the number of milliseconds that a lock can be held before it automatically releases

        +
      +

      Returns ExpiringFileLock

    +
    +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/functions/aft_core.LogLevel.isType.html b/docs/functions/aft_core.LogLevel.isType.html index 1139b9d0..bad0fef9 100644 --- a/docs/functions/aft_core.LogLevel.isType.html +++ b/docs/functions/aft_core.LogLevel.isType.html @@ -33,7 +33,7 @@
    level: unknown

    Returns level is "trace" | "debug" | "info" | "step" | "warn" | "pass" | "fail" | "error" | "none"

    +
  • Defined in aft-core/src/logging/log-level.ts:25
  • Returns number

    +
  • Defined in aft-core/src/logging/log-level.ts:37
  • Returns NumberBetween

    +
  • Defined in aft-core/src/verification/verifier-matcher.ts:115
  • Returns ValueContaining

    +
  • Defined in aft-core/src/verification/verifier-matcher.ts:170
  • Returns string

    +
  • Defined in aft-core/src/helpers/ellide.ts:3
  • Returns Equaling

    +
  • Defined in aft-core/src/verification/verifier-matcher.ts:37
  • Returns Exactly

    +
  • Defined in aft-core/src/verification/verifier-matcher.ts:70
  • Returns GreaterThan

    +
  • Defined in aft-core/src/verification/verifier-matcher.ts:235
  • Returns HavingValue

    +
  • Defined in aft-core/src/verification/verifier-matcher.ts:201
  • Returns LessThan

    +
  • Defined in aft-core/src/verification/verifier-matcher.ts:269
  • +
  • Defined in aft-core/src/verification/verifier-matcher.ts:302
    • - +
    • generates a new Retry<T> instance that runs a given retryable until it successfully passes a condition

      -

      Ex:

      -
      const result = await retry<NullableObj>(() => returnsNullableObj()); // will call until returns non-nullish value

      const result = await retry<number>(() => someAction())
      .withStartDelayBetweenAttempts(1000) // wait 1 second before retrying
      .withBackOff('exponential') // increase the delay between retries exponentially
      .withMaxAttempts(10) // stop after 10 retries if not successful
      .withMaxDuration(30000) // stop after 30 seconds if not successful
      .until((res: number) => res === 5); // expect result to equal 5 +

      Ex: using aftconfig.json to control conditions

      +
      // aftconfig.json
      {
      "retryDelayMs": 1000,
      "retryBackOffType": "exponential",
      "retryMaxAttempts": 10,
      "retryMaxDurationMs": 30000
      } +
      +
      // in your code
      const result = await retry<number>(() => someAction()).until((res: number) => res === 5); +
      +

      Ex: overriding aftconfig.json to control conditions

      +
      // in your code
      const result = await retry<number>(() => someAction(), new AftConfig({
      retryDelayMs: 1000,
      retryBackOffType: 'exponential',
      retryMaxAttempts: 10,
      retryMaxDurationMs: 30000
      })).unti((res: number) => res === 5);

      Returns

      a new Retry<T> instance

      @@ -38,10 +43,14 @@

      Parameters

      retryable: Func<void, T | PromiseLike<T>>

      the function to be retried until it passes a default condition of return value != null or a custom condition

      +
    • +
    • +
      Optional aftCfg: AftConfig
      +

      an optional AftConfig instance allowing you to override the default settings in aftconfig.json

    Returns Retry<T>

    +
  • Defined in aft-core/src/helpers/retry.ts:252
  • and then calling the dispose method on the Disposable when execution of the function is done. Usage Example:

    -
    await using(new ImplementsDisposable(), async (disposable) => {
    await disposable.interact();
    // do stuff...
    }); // `disposable.dispose` is called here +
    await using(new ImplementsDisposable(), async (disposable) => {
    await disposable.interact();
    // do stuff...
    }); // `disposable.dispose` is called here
    @@ -43,7 +43,7 @@
    func:

    Returns Promise<void>

    +
  • Defined in aft-core/src/helpers/using.ts:36
  • creates a new Verifier instace to be used for executing some Functional Test Assertion.

    Ex:

    -
    await verify(async (v: Verifier) => {
    await v.logMgr.info('doing some testing...');
    let feature = new FeatureObj();
    return await feature.returnExpectedValue();
    }).withDescription('example usage for Verifier')
    .and.withTestIds('C1234') // if TestCasePlugin.shouldRun('C1234') returns `false` the assertion is not run
    .and.withKnownDefectIds('AUTO-123') // if DefectPlugin.getDefect('AUTO-123').status === 'open' the assertion is not run
    .returns('expected value'); +
    await verify(async (v: Verifier) => {
    await v.reporter.info('doing some testing...');
    let feature = new FeatureObj();
    return await feature.returnExpectedValue();
    }).withDescription('example usage for Verifier')
    .and.withTestIds('C1234') // if TestExecutionPolicyManager.shouldRun('C1234') returns `false` the assertion is not run
    .returns('expected value');

    Returns

    a new Verifier instance

    @@ -35,7 +35,7 @@
    assertion:

    Returns Verifier

    +
  • Defined in aft-core/src/verification/verifier.ts:424
  • +
    +
    +
  • Acc
  • +
  • get
  • Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/functions/aft_web_services.HttpHeaders.Authorization.basic.html b/docs/functions/aft_web_services.HttpHeaders.Authorization.basic.html new file mode 100644 index 00000000..b0e34665 --- /dev/null +++ b/docs/functions/aft_web_services.HttpHeaders.Authorization.basic.html @@ -0,0 +1,87 @@ +basic | automated-functional-testing
    +
    + +
    +
    +
    + +
    +
    +
    +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/functions/aft_web_services.HttpHeaders.Authorization.digest.html b/docs/functions/aft_web_services.HttpHeaders.Authorization.digest.html new file mode 100644 index 00000000..856dbdc6 --- /dev/null +++ b/docs/functions/aft_web_services.HttpHeaders.Authorization.digest.html @@ -0,0 +1,85 @@ +digest | automated-functional-testing
    +
    + +
    + +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/functions/aft_web_services.HttpHeaders.ContentType.get.html b/docs/functions/aft_web_services.HttpHeaders.ContentType.get.html new file mode 100644 index 00000000..f5f727b0 --- /dev/null +++ b/docs/functions/aft_web_services.HttpHeaders.ContentType.get.html @@ -0,0 +1,83 @@ +get | automated-functional-testing
    +
    + +
    +
    +
    + +
    +
    +
    +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/functions/aft_web_services.HttpHeaders.Cookies.cookie-1.html b/docs/functions/aft_web_services.HttpHeaders.Cookies.cookie-1.html new file mode 100644 index 00000000..186e8adf --- /dev/null +++ b/docs/functions/aft_web_services.HttpHeaders.Cookies.cookie-1.html @@ -0,0 +1,86 @@ +cookie | automated-functional-testing
    +
    + +
    +
    +
    + +
    +
    +
    +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/functions/aft_web_services.HttpHeaders.Cookies.setCookie-1.html b/docs/functions/aft_web_services.HttpHeaders.Cookies.setCookie-1.html new file mode 100644 index 00000000..8e0273a3 --- /dev/null +++ b/docs/functions/aft_web_services.HttpHeaders.Cookies.setCookie-1.html @@ -0,0 +1,86 @@ +setCookie | automated-functional-testing
    +
    + +
    + +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/functions/aft_web_services.XML.toObject.html b/docs/functions/aft_web_services.XML.toObject.html index 29d0c168..9a271a81 100644 --- a/docs/functions/aft_web_services.XML.toObject.html +++ b/docs/functions/aft_web_services.XML.toObject.html @@ -31,7 +31,7 @@

    Parameters

    oXMLParent: Document | Element | DocumentFragment

    Returns T

    +
  • Defined in aft-web-services/src/helpers/xml.ts:13
  • Generated using TypeDoc

    diff --git a/docs/interfaces/aft_core.Disposable.html b/docs/interfaces/aft_core.Disposable.html index 295dad45..6c2e3143 100644 --- a/docs/interfaces/aft_core.Disposable.html +++ b/docs/interfaces/aft_core.Disposable.html @@ -19,7 +19,7 @@

    Interface Disposable

    some disposal after their use. automatic disposal is handled by using the Disposable within the using object like follows:

    -
    async using(new ImplementsDisposable(), async (disp) => {
    await disp.doSomethingAsync();
    disp.doSomethingSync();
    }); +
    async using(new ImplementsDisposable(), async (disp) => {
    await disp.doSomethingAsync();
    disp.doSomethingSync();
    });

    where the dispose function would be called automatically upon completion or in the case of an @@ -28,14 +28,9 @@

    Interface Disposable

    Hierarchy

      -
    • Disposable
    -
    -

    Implemented by

    -
    @@ -59,7 +54,7 @@

    Parameters

    Optional error: any

    Returns void

    +
  • Defined in aft-core/src/helpers/using.ts:19
  • Returns VerifierMatcher

    +
  • Defined in aft-core/src/verification/verifier-matcher.ts:3
  • Generated using TypeDoc

    diff --git a/docs/modules/aft_core.Err.html b/docs/modules/aft_core.Err.html index 08a310a4..7509cb7c 100644 --- a/docs/modules/aft_core.Err.html +++ b/docs/modules/aft_core.Err.html @@ -15,8 +15,8 @@
  • Err
  • Namespace Err

    +
  • Defined in aft-core/src/helpers/err.ts:62
  • +
  • Defined in aft-core/src/helpers/err.ts:156
  • Index

    @@ -24,6 +24,7 @@

    Index

    Functions

    Generated using TypeDoc

    diff --git a/docs/modules/aft_core.LogManager.html b/docs/modules/aft_core.ExpiringFileLock.html similarity index 70% rename from docs/modules/aft_core.LogManager.html rename to docs/modules/aft_core.ExpiringFileLock.html index 864d08c7..b4d36ac7 100644 --- a/docs/modules/aft_core.LogManager.html +++ b/docs/modules/aft_core.ExpiringFileLock.html @@ -1,4 +1,4 @@ -LogManager | automated-functional-testing
    +ExpiringFileLock | automated-functional-testing
    +
  • Defined in aft-core/src/helpers/expiring-file-lock.ts:36
  • +
  • Defined in aft-core/src/helpers/expiring-file-lock.ts:94
  • Index

    Functions

    -
    +
  • get
  • Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/modules/aft_core.LogLevel.html b/docs/modules/aft_core.LogLevel.html index 5b9e94bd..4aae7626 100644 --- a/docs/modules/aft_core.LogLevel.html +++ b/docs/modules/aft_core.LogLevel.html @@ -31,8 +31,8 @@

    Namespace LogLevel

    +
  • Defined in aft-core/src/logging/log-level.ts:2
  • +
  • Defined in aft-core/src/logging/log-level.ts:18
  • Index

    @@ -65,20 +65,27 @@

    aft-core
  • aft-jasmine-reporter
  • -
  • aft-logging-awskinesis
  • -
  • aft-logging-filesystem
  • -
  • aft-logging-html
  • aft-mocha-reporter
  • +
  • aft-reporting-aws-kinesis-firehose
  • +
  • aft-reporting-filesystem
  • +
  • aft-reporting-html
  • aft-testrail
  • aft-ui
  • -
  • aft-ui-browsers
  • -
  • aft-ui-mobile-apps
  • +
  • aft-ui-selenium
  • +
  • aft-ui-webdriverio
  • aft-web-services
  • +
  • Defined in aft-core/src/helpers/convert.ts:14
  • +
  • Defined in aft-core/src/helpers/convert.ts:23
  • Index

    @@ -52,20 +52,27 @@

    aft-core
  • aft-jasmine-reporter
  • -
  • aft-logging-awskinesis
  • -
  • aft-logging-filesystem
  • -
  • aft-logging-html
  • aft-mocha-reporter
  • +
  • aft-reporting-aws-kinesis-firehose
  • +
  • aft-reporting-filesystem
  • +
  • aft-reporting-html
  • aft-testrail
  • aft-ui
  • -
  • aft-ui-browsers
  • -
  • aft-ui-mobile-apps
  • +
  • aft-ui-selenium
  • +
  • aft-ui-webdriverio
  • aft-web-services
  • +
  • HtmlReportingPlugin
  • +
  • HtmlReportingPluginConfig
  • Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/modules/aft_testrail.html b/docs/modules/aft_testrail.html index c484a1cf..42fc4829 100644 --- a/docs/modules/aft_testrail.html +++ b/docs/modules/aft_testrail.html @@ -14,7 +14,7 @@
  • aft-testrail
  • Module aft-testrail

    +
  • Defined in aft-testrail/src/index.ts:2
  • @@ -23,18 +23,8 @@

    Index

    Classes

    -
    -

    Type Aliases

    -
    -
    -

    Variables

    -
    +
  • TestRailReportingPlugin
  • +
  • TestRailTestExecutionPolicyPlugin
  • Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/modules/aft_ui.html b/docs/modules/aft_ui.html index 9137a7eb..acf38b36 100644 --- a/docs/modules/aft_ui.html +++ b/docs/modules/aft_ui.html @@ -14,7 +14,7 @@
  • aft-ui
  • Module aft-ui

    +
  • Defined in aft-ui/src/index.ts:2
  • @@ -22,20 +22,14 @@

    Module aft-ui

    +
  • UiComponentOptions
  • Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/modules/aft_ui_browsers.html b/docs/modules/aft_ui_browsers.html deleted file mode 100644 index e66f0d41..00000000 --- a/docs/modules/aft_ui_browsers.html +++ /dev/null @@ -1,116 +0,0 @@ -aft-ui-browsers | automated-functional-testing
    -
    - -
    -
    - -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/modules/aft_ui_mobile_apps.html b/docs/modules/aft_ui_mobile_apps.html deleted file mode 100644 index 1cf0453a..00000000 --- a/docs/modules/aft_ui_mobile_apps.html +++ /dev/null @@ -1,132 +0,0 @@ -aft-ui-mobile-apps | automated-functional-testing
    -
    - -
    -
    - -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/modules/aft_ui_selenium.html b/docs/modules/aft_ui_selenium.html new file mode 100644 index 00000000..f6eec637 --- /dev/null +++ b/docs/modules/aft_ui_selenium.html @@ -0,0 +1,94 @@ +aft-ui-selenium | automated-functional-testing
    +
    + +
    + +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/modules/aft_ui_webdriverio.html b/docs/modules/aft_ui_webdriverio.html new file mode 100644 index 00000000..37ce8ab1 --- /dev/null +++ b/docs/modules/aft_ui_webdriverio.html @@ -0,0 +1,92 @@ +aft-ui-webdriverio | automated-functional-testing
    +
    + +
    + +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/modules/aft_logging_filesystem.html b/docs/modules/aft_web_services.HttpHeaders.Accept.html similarity index 62% rename from docs/modules/aft_logging_filesystem.html rename to docs/modules/aft_web_services.HttpHeaders.Accept.html index 98a3762f..8aa1f40b 100644 --- a/docs/modules/aft_logging_filesystem.html +++ b/docs/modules/aft_web_services.HttpHeaders.Accept.html @@ -1,4 +1,4 @@ -aft-logging-filesystem | automated-functional-testing
    +Accept | automated-functional-testing
    -
    -
    +
  • Defined in aft-web-services/src/http/http-headers.ts:41
  • Index

    -

    Classes

    -
    -

    Type Aliases

    -
    +
  • Acc
  • +
  • get
  • Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/modules/aft_web_services.HttpHeaders.Authorization.html b/docs/modules/aft_web_services.HttpHeaders.Authorization.html new file mode 100644 index 00000000..cee0d9a8 --- /dev/null +++ b/docs/modules/aft_web_services.HttpHeaders.Authorization.html @@ -0,0 +1,87 @@ +Authorization | automated-functional-testing
    +
    + +
    + +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/modules/aft_logging_awskinesis.html b/docs/modules/aft_web_services.HttpHeaders.ContentType.html similarity index 61% rename from docs/modules/aft_logging_awskinesis.html rename to docs/modules/aft_web_services.HttpHeaders.ContentType.html index ad6766cf..1890749f 100644 --- a/docs/modules/aft_logging_awskinesis.html +++ b/docs/modules/aft_web_services.HttpHeaders.ContentType.html @@ -1,4 +1,4 @@ -aft-logging-awskinesis | automated-functional-testing
    +ContentType | automated-functional-testing
    -
    -
    +
  • Defined in aft-web-services/src/http/http-headers.ts:31
  • Index

    -

    Classes

    -
    KinesisLoggingPlugin +

    Type Aliases

    +
    -

    Type Aliases

    -
    +
  • CT
  • +
  • get
  • Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/modules/aft_web_services.HttpHeaders.Cookies.html b/docs/modules/aft_web_services.HttpHeaders.Cookies.html new file mode 100644 index 00000000..04b0a907 --- /dev/null +++ b/docs/modules/aft_web_services.HttpHeaders.Cookies.html @@ -0,0 +1,89 @@ +Cookies | automated-functional-testing
    +
    + +
    + +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/modules/aft_web_services.HttpHeaders.MimeType.html b/docs/modules/aft_web_services.HttpHeaders.MimeType.html new file mode 100644 index 00000000..0ecf31e7 --- /dev/null +++ b/docs/modules/aft_web_services.HttpHeaders.MimeType.html @@ -0,0 +1,92 @@ +MimeType | automated-functional-testing
    +
    + +
    + +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/modules/aft_web_services.HttpHeaders.html b/docs/modules/aft_web_services.HttpHeaders.html new file mode 100644 index 00000000..a3f609a9 --- /dev/null +++ b/docs/modules/aft_web_services.HttpHeaders.html @@ -0,0 +1,85 @@ +HttpHeaders | automated-functional-testing
    +
    + +
    +
    +
    + +
    +

    a module containing helper const and functions to generate +HTTP headers that can then be appended to your header object using:

    +
    const headers = {
    ...HttpHeaders.Authorization.basic('myUsername', 'myPassword'),
    ...HttpHeaders.ContentType.get(HttpHeaders.MimeType.applicationJson)
    ...HttpHeaders.Cookies.setCookie({
    key: 'foo',
    val: 'bar',
    expiration: new Date().toString('u'),
    secure: true,
    httpOnly: true
    })
    }; +
    +
    +
    +
    +

    Index

    +
    +

    Namespaces

    +
    +
    +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/modules/aft_web_services.XML.html b/docs/modules/aft_web_services.XML.html index d6b4f68a..aac81538 100644 --- a/docs/modules/aft_web_services.XML.html +++ b/docs/modules/aft_web_services.XML.html @@ -15,7 +15,7 @@
  • XML
  • Namespace XML

    +
  • Defined in aft-web-services/src/helpers/xml.ts:4
  • Index

    @@ -47,20 +47,27 @@

    aft-core
  • aft-jasmine-reporter
  • -
  • aft-logging-awskinesis
  • -
  • aft-logging-filesystem
  • -
  • aft-logging-html
  • aft-mocha-reporter
  • +
  • aft-reporting-aws-kinesis-firehose
  • +
  • aft-reporting-filesystem
  • +
  • aft-reporting-html
  • aft-testrail
  • aft-ui
  • -
  • aft-ui-browsers
  • -
  • aft-ui-mobile-apps
  • +
  • aft-ui-selenium
  • +
  • aft-ui-webdriverio
  • aft-web-services
  • +
  • httpService
  • Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/types/aft_core.Action.html b/docs/types/aft_core.Action.html index 3ac9ba7b..8d60e0cf 100644 --- a/docs/types/aft_core.Action.html +++ b/docs/types/aft_core.Action.html @@ -29,7 +29,7 @@

    Type declaration

  • Type to represent any function accepting a single argument of type T that returns void. an alternative to writing:

    -
    (input: T): void
    +
    (input: T): void
     
    @@ -39,7 +39,7 @@

    Parameters

    item: T
  • Returns void

    +
  • Defined in aft-core/src/helpers/custom-types.ts:8
  • +
  • Defined in aft-core/src/helpers/custom-types.ts:93
  • +
  • Defined in aft-core/src/helpers/custom-types.ts:36
  • EllipsisLocation: "beginning" | "middle" | "end"
    +
  • Defined in aft-core/src/helpers/ellide.ts:1
  • -
    ErrOptions: { errLevel?: LogLevel; logMgr?: LogManager; verbosity?: ErrVerbosity }
    +
    ErrOptions: { errLevel: LogLevel; logger: Reporter; verbosity: ErrVerbosity }

    Type declaration

    • -
      Optional errLevel?: LogLevel
      +
      errLevel: LogLevel

      the LogLevel to use when logging any caught Error. defaults to warn

    • -
      Optional logMgr?: LogManager
      -

      an optional LogManager instance to use in logging the error message +

      logger: Reporter
      +

      an optional Reporter instance to use in logging the error message and stack

    • -
      Optional verbosity?: ErrVerbosity
      +
      verbosity: ErrVerbosity

      the amount of detail to include in the output message. defaults to full

    +
  • Defined in aft-core/src/helpers/err.ts:10
  • ErrVerbosity: "full" | "short"
    +
  • Defined in aft-core/src/helpers/err.ts:8
  • Returns TResult

    +
  • Defined in aft-core/src/helpers/custom-types.ts:49
  • a valid key that can be used in any JSON object

    +
  • Defined in aft-core/src/helpers/custom-types.ts:54
  • a valid JSON object

    +
  • Defined in aft-core/src/helpers/custom-types.ts:65
  • any JSON object

    +
  • Defined in aft-core/src/helpers/custom-types.ts:60
  • LogLevel: typeof levels[number]
    +
  • Defined in aft-core/src/logging/log-level.ts:2
  • +
  • Defined in aft-core/src/logging/log-level.ts:18
  • -
    LogMessageData: { level?: LogLevel; message?: string; name?: string }
    +
    LogMessageData: { args?: any[]; level: LogLevel; message: string; name: string }

    Type declaration

    • -
      Optional level?: LogLevel
    • +
      Optional args?: any[]
    • -
      Optional message?: string
    • +
      level: LogLevel
    • -
      Optional name?: string
    +
  • Defined in aft-core/src/helpers/machine-info.ts:43
  • a type representing the merging of two or more specified types

    NOTE: if you need to merge more than 6 types then create intermediate types and use the merging of those like:

    -
    const type foo = Merge<t1, t2, t3, t4, t5, t6>;
    const type bar = Merge<t7, t8, t9, t10, t11, t12>;
    const type foobar = Merge<foo, bar>; +
    const type foo = Merge<t1, t2, t3, t4, t5, t6>;
    const type bar = Merge<t7, t8, t9, t10, t11, t12>;
    const type foobar = Merge<foo, bar>;
    @@ -37,7 +37,7 @@

    T5 = {}

  • T6 = {}

  • +
  • Defined in aft-core/src/helpers/custom-types.ts:109
  • -
    ProcessingResult: { message?: string; obj?: any; success?: boolean }
    -

    this type allows for more complex return values -to be expressed from functions that would normally -return a simple boolean

    +

    Type alias ProcessingResult<T>

    +
    ProcessingResult<T>: { message?: string; result: T }
    +

    this type allows for a descriptive message to be +included in a result from functions that would normally +be limited to returning only a single value

    +

    ex:

    +
    function shouldDoWork(input: Worker): ProcessingResult<boolean> {
    try {
    const result = input.functionThatMightThrow();
    return { result: result };
    } catch (e) {
    return { result: false, message: Err.short(e) };
    }
    } +
    +
    +

    Type Parameters

    +
      +
    • +

      T

    Type declaration

    • Optional message?: string
    • -
      Optional obj?: any
    • -
    • -
      Optional success?: boolean
    on each iteration and exponential doubles the previous delay

    +
  • Defined in aft-core/src/helpers/custom-types.ts:116
  • used to identify characters or strings to be excluded and a replaceWith field containing a string to use as a replacement for each excluded value

    Ex:

    -
    const opts = [{exclude: /[\s]+/g, replaceWith: '_'}];
    convert.toSafeString('I am an example', opts); // returns 'I_am_an_example' +
    const opts = [{exclude: /[\s]+/g, replaceWith: '_'}];
    convert.toSafeString('I am an example', opts); // returns 'I_am_an_example'
    @@ -30,8 +30,8 @@
    exclude:
    replaceWith: string
    +
  • Defined in aft-core/src/helpers/convert.ts:14
  • +
  • Defined in aft-core/src/helpers/convert.ts:23
  • -
    TestResult: { created: number; defects?: Defect[]; metadata?: JsonObject; resultId: string; resultMessage?: string; status: TestStatus; testId?: string }
    +
    TestResult: { created: number; metadata?: JsonObject; resultId: string; resultMessage?: string; status: TestStatus; testId?: string; testName?: string }

    Type declaration

    • created: number
    • -
      Optional defects?: Defect[]
    • -
    • Optional metadata?: JsonObject
    • resultId: string
    • @@ -31,9 +29,11 @@
      Optional resultMessage
      status: TestStatus
    • -
      Optional testId?: string
    -
    TestStatus: "Untested" | "Passed" | "Blocked" | "Retest" | "Failed" | "Skipped"
    +
    VerifierEvent: "skipped" | "started" | "done"
    +
  • Defined in aft-core/src/verification/verifier.ts:14
  • +
    VerifierInternals: { usingAftConfig: ((cfg: AftConfig) => Verifier); usingBuildInfoManager: ((mgr: BuildInfoManager) => Verifier); usingReporter: ((mgr: Reporter) => Verifier); usingTestExecutionPolicyManager: ((mgr: TestExecutionPolicyManager) => Verifier) }
    +
    +

    Type declaration

    +
    +
  • Defined in aft-core/src/verification/verifier-internals.ts:7
  • +
    UiComponentOptions: { aftCfg?: AftConfig; driver: unknown; locator?: unknown; parent?: Func<void, Promise<unknown>>; reporter?: Reporter }

    Type declaration

    • -
      locator: unknown
    • +
      Optional aftCfg?: AftConfig
    • -
      Optional maxWaitMs?: number
    • +
      driver: unknown
    • -
      Optional retryDelayBackOff?: RetryBackOffType
    • +
      Optional locator?: unknown
    • -
      Optional retryDelayMs?: number
    +
  • UiComponentOptions
  • Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/types/aft_ui.UiFacetOptions.html b/docs/types/aft_ui.UiFacetOptions.html deleted file mode 100644 index fa4f3763..00000000 --- a/docs/types/aft_ui.UiFacetOptions.html +++ /dev/null @@ -1,93 +0,0 @@ -UiFacetOptions | automated-functional-testing
    -
    - -
    -
    -
    -
    - -

    Type alias UiFacetOptions

    -
    UiFacetOptions: { index?: number; locator?: unknown; logMgr?: LogManager; maxWaitMs?: number; parent?: UiFacet<any>; retryDelayBackOff?: RetryBackOffType; retryDelayMs?: number; session?: UiSession<any> }
    -
    -

    Type declaration

    -
      -
    • -
      Optional index?: number
    • -
    • -
      Optional locator?: unknown
    • -
    • -
      Optional logMgr?: LogManager
    • -
    • -
      Optional maxWaitMs?: number
    • -
    • -
      Optional parent?: UiFacet<any>
    • -
    • -
      Optional retryDelayBackOff?: RetryBackOffType
    • -
    • -
      Optional retryDelayMs?: number
    • -
    • -
      Optional session?: UiSession<any>
    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/types/aft_ui.UiSessionGeneratorPluginOptions.html b/docs/types/aft_ui.UiSessionGeneratorPluginOptions.html deleted file mode 100644 index fcc02453..00000000 --- a/docs/types/aft_ui.UiSessionGeneratorPluginOptions.html +++ /dev/null @@ -1,74 +0,0 @@ -UiSessionGeneratorPluginOptions | automated-functional-testing
    -
    - -
    - -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/types/aft_ui.UiTestPlatformOptions.html b/docs/types/aft_ui.UiTestPlatformOptions.html deleted file mode 100644 index b652ddd1..00000000 --- a/docs/types/aft_ui.UiTestPlatformOptions.html +++ /dev/null @@ -1,87 +0,0 @@ -UiTestPlatformOptions | automated-functional-testing
    -
    - -
    -
    -
    -
    - -

    Type alias UiTestPlatformOptions

    -
    UiTestPlatformOptions: { browser?: string; browserVersion?: string; deviceName?: string; os?: string; osVersion?: string }
    -
    -

    Type declaration

    -
      -
    • -
      Optional browser?: string
    • -
    • -
      Optional browserVersion?: string
    • -
    • -
      Optional deviceName?: string
    • -
    • -
      Optional os?: string
    • -
    • -
      Optional osVersion?: string
    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/types/aft_ui_browsers.BrowserFacetOptions.html b/docs/types/aft_ui_browsers.BrowserFacetOptions.html deleted file mode 100644 index ec54b5b6..00000000 --- a/docs/types/aft_ui_browsers.BrowserFacetOptions.html +++ /dev/null @@ -1,82 +0,0 @@ -BrowserFacetOptions | automated-functional-testing
    -
    - -
    - -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/types/aft_ui_browsers.BrowserSessionGeneratorPluginOptions.html b/docs/types/aft_ui_browsers.BrowserSessionGeneratorPluginOptions.html deleted file mode 100644 index 91d4cc7d..00000000 --- a/docs/types/aft_ui_browsers.BrowserSessionGeneratorPluginOptions.html +++ /dev/null @@ -1,82 +0,0 @@ -BrowserSessionGeneratorPluginOptions | automated-functional-testing
    -
    - -
    - -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/types/aft_ui_browsers.BrowserSessionOptions.html b/docs/types/aft_ui_browsers.BrowserSessionOptions.html deleted file mode 100644 index 95f701e2..00000000 --- a/docs/types/aft_ui_browsers.BrowserSessionOptions.html +++ /dev/null @@ -1,82 +0,0 @@ -BrowserSessionOptions | automated-functional-testing
    -
    - -
    - -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/types/aft_ui_browsers.BrowserStackBrowserSessionGeneratorPluginOptions.html b/docs/types/aft_ui_browsers.BrowserStackBrowserSessionGeneratorPluginOptions.html deleted file mode 100644 index 7cddd4ea..00000000 --- a/docs/types/aft_ui_browsers.BrowserStackBrowserSessionGeneratorPluginOptions.html +++ /dev/null @@ -1,82 +0,0 @@ -BrowserStackBrowserSessionGeneratorPluginOptions | automated-functional-testing
    -
    - -
    - -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/types/aft_ui_browsers.BrowserStackBrowserSessionOptions.html b/docs/types/aft_ui_browsers.BrowserStackBrowserSessionOptions.html deleted file mode 100644 index 9d5c1b8f..00000000 --- a/docs/types/aft_ui_browsers.BrowserStackBrowserSessionOptions.html +++ /dev/null @@ -1,82 +0,0 @@ -BrowserStackBrowserSessionOptions | automated-functional-testing
    -
    - -
    - -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/types/aft_ui_browsers.SauceLabsBrowserSessionGeneratorPluginOptions.html b/docs/types/aft_ui_browsers.SauceLabsBrowserSessionGeneratorPluginOptions.html deleted file mode 100644 index 9fc31fb0..00000000 --- a/docs/types/aft_ui_browsers.SauceLabsBrowserSessionGeneratorPluginOptions.html +++ /dev/null @@ -1,82 +0,0 @@ -SauceLabsBrowserSessionGeneratorPluginOptions | automated-functional-testing
    -
    - -
    - -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/types/aft_ui_browsers.SauceLabsBrowserSessionOptions.html b/docs/types/aft_ui_browsers.SauceLabsBrowserSessionOptions.html deleted file mode 100644 index 5578a70e..00000000 --- a/docs/types/aft_ui_browsers.SauceLabsBrowserSessionOptions.html +++ /dev/null @@ -1,82 +0,0 @@ -SauceLabsBrowserSessionOptions | automated-functional-testing
    -
    - -
    - -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/types/aft_ui_browsers.WebElementOptions.html b/docs/types/aft_ui_browsers.WebElementOptions.html deleted file mode 100644 index 2723002a..00000000 --- a/docs/types/aft_ui_browsers.WebElementOptions.html +++ /dev/null @@ -1,82 +0,0 @@ -WebElementOptions | automated-functional-testing
    -
    - -
    - -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/types/aft_ui_mobile_apps.AppiumGridSessionGeneratorPluginOptions.html b/docs/types/aft_ui_mobile_apps.AppiumGridSessionGeneratorPluginOptions.html deleted file mode 100644 index 34a24178..00000000 --- a/docs/types/aft_ui_mobile_apps.AppiumGridSessionGeneratorPluginOptions.html +++ /dev/null @@ -1,90 +0,0 @@ -AppiumGridSessionGeneratorPluginOptions | automated-functional-testing
    -
    - -
    -
    - -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/types/aft_ui_mobile_apps.BrowserStackAppAutomateApiOptions.html b/docs/types/aft_ui_mobile_apps.BrowserStackAppAutomateApiOptions.html deleted file mode 100644 index b641ed0d..00000000 --- a/docs/types/aft_ui_mobile_apps.BrowserStackAppAutomateApiOptions.html +++ /dev/null @@ -1,101 +0,0 @@ -BrowserStackAppAutomateApiOptions | automated-functional-testing
    -
    - -
    -
    -
    -
    - -

    Type alias BrowserStackAppAutomateApiOptions

    -
    BrowserStackAppAutomateApiOptions: { apiUrl?: string; key?: string; logMgr?: LogManager; user?: string }
    -
    -

    Type declaration

    -
      -
    • -
      Optional apiUrl?: string
    • -
    • -
      Optional key?: string
    • -
    • -
      Optional logMgr?: LogManager
    • -
    • -
      Optional user?: string
    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/types/aft_ui_mobile_apps.BrowserStackMobileApp.html b/docs/types/aft_ui_mobile_apps.BrowserStackMobileApp.html deleted file mode 100644 index eded85c8..00000000 --- a/docs/types/aft_ui_mobile_apps.BrowserStackMobileApp.html +++ /dev/null @@ -1,107 +0,0 @@ -BrowserStackMobileApp | automated-functional-testing
    -
    - -
    -
    -
    - -
    BrowserStackMobileApp: { app_id?: string; app_name?: string; app_url?: string; app_version?: string; custom_id?: string; shareable_id?: string; uploaded_at?: string }
    -
    -

    Type declaration

    -
      -
    • -
      Optional app_id?: string
    • -
    • -
      Optional app_name?: string
    • -
    • -
      Optional app_url?: string
    • -
    • -
      Optional app_version?: string
    • -
    • -
      Optional custom_id?: string
    • -
    • -
      Optional shareable_id?: string
    • -
    • -
      Optional uploaded_at?: string
    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/types/aft_ui_mobile_apps.BrowserStackMobileAppSessionGeneratorPluginOptions.html b/docs/types/aft_ui_mobile_apps.BrowserStackMobileAppSessionGeneratorPluginOptions.html deleted file mode 100644 index b3938344..00000000 --- a/docs/types/aft_ui_mobile_apps.BrowserStackMobileAppSessionGeneratorPluginOptions.html +++ /dev/null @@ -1,90 +0,0 @@ -BrowserStackMobileAppSessionGeneratorPluginOptions | automated-functional-testing
    -
    - -
    -
    -
    -
    - -

    Type alias BrowserStackMobileAppSessionGeneratorPluginOptions

    -
    BrowserStackMobileAppSessionGeneratorPluginOptions: Merge<MobileAppSessionGeneratorPluginOptions, { api?: BrowserStackAppAutomateApi; apiUrl?: string; debug?: boolean; key?: string; local?: boolean; localIdentifier?: string; user?: string }>
    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/types/aft_ui_mobile_apps.BrowserStackMobileAppSessionOptions.html b/docs/types/aft_ui_mobile_apps.BrowserStackMobileAppSessionOptions.html deleted file mode 100644 index 4a94ab75..00000000 --- a/docs/types/aft_ui_mobile_apps.BrowserStackMobileAppSessionOptions.html +++ /dev/null @@ -1,90 +0,0 @@ -BrowserStackMobileAppSessionOptions | automated-functional-testing
    -
    - -
    -
    -
    -
    - -

    Type alias BrowserStackMobileAppSessionOptions

    -
    BrowserStackMobileAppSessionOptions: Merge<MobileAppSessionOptions, { debug?: boolean; key?: string; local?: boolean; localIdentifier?: string; user?: string }>
    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/types/aft_ui_mobile_apps.MobileAppElementOptions.html b/docs/types/aft_ui_mobile_apps.MobileAppElementOptions.html deleted file mode 100644 index 08f7f0cb..00000000 --- a/docs/types/aft_ui_mobile_apps.MobileAppElementOptions.html +++ /dev/null @@ -1,90 +0,0 @@ -MobileAppElementOptions | automated-functional-testing
    -
    - -
    - -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/types/aft_ui_mobile_apps.MobileAppFacetOptions.html b/docs/types/aft_ui_mobile_apps.MobileAppFacetOptions.html deleted file mode 100644 index 5937da56..00000000 --- a/docs/types/aft_ui_mobile_apps.MobileAppFacetOptions.html +++ /dev/null @@ -1,90 +0,0 @@ -MobileAppFacetOptions | automated-functional-testing
    -
    - -
    -
    -
    - -
    MobileAppFacetOptions: Merge<UiFacetOptions, { locator?: string; parent?: MobileAppFacet; session?: MobileAppSession<any> }>
    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/types/aft_ui_mobile_apps.MobileAppSessionGeneratorPluginOptions.html b/docs/types/aft_ui_mobile_apps.MobileAppSessionGeneratorPluginOptions.html deleted file mode 100644 index 21b9df9a..00000000 --- a/docs/types/aft_ui_mobile_apps.MobileAppSessionGeneratorPluginOptions.html +++ /dev/null @@ -1,90 +0,0 @@ -MobileAppSessionGeneratorPluginOptions | automated-functional-testing
    -
    - -
    -
    -
    -
    - -

    Type alias MobileAppSessionGeneratorPluginOptions

    -
    MobileAppSessionGeneratorPluginOptions: Merge<UiSessionGeneratorPluginOptions, { app?: string; remoteOptions?: object }>
    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/types/aft_ui_mobile_apps.MobileAppSessionOptions.html b/docs/types/aft_ui_mobile_apps.MobileAppSessionOptions.html deleted file mode 100644 index 1a48875d..00000000 --- a/docs/types/aft_ui_mobile_apps.MobileAppSessionOptions.html +++ /dev/null @@ -1,90 +0,0 @@ -MobileAppSessionOptions | automated-functional-testing
    -
    - -
    -
    -
    - -
    MobileAppSessionOptions: Merge<UiSessionOptions, { app?: string; driver?: Browser<"async">; remoteOptions?: RemoteOptions }>
    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/types/aft_ui_mobile_apps.RecentGroupAppsResponse.html b/docs/types/aft_ui_mobile_apps.RecentGroupAppsResponse.html deleted file mode 100644 index 4585bd91..00000000 --- a/docs/types/aft_ui_mobile_apps.RecentGroupAppsResponse.html +++ /dev/null @@ -1,95 +0,0 @@ -RecentGroupAppsResponse | automated-functional-testing
    -
    - -
    -
    - -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/types/aft_ui_mobile_apps.SauceLabsMobileAppSessionGeneratorPluginOptions.html b/docs/types/aft_ui_mobile_apps.SauceLabsMobileAppSessionGeneratorPluginOptions.html deleted file mode 100644 index 0811bcc1..00000000 --- a/docs/types/aft_ui_mobile_apps.SauceLabsMobileAppSessionGeneratorPluginOptions.html +++ /dev/null @@ -1,90 +0,0 @@ -SauceLabsMobileAppSessionGeneratorPluginOptions | automated-functional-testing
    -
    - -
    -
    -
    -
    - -

    Type alias SauceLabsMobileAppSessionGeneratorPluginOptions

    -
    SauceLabsMobileAppSessionGeneratorPluginOptions: Merge<MobileAppSessionGeneratorPluginOptions, { accessKey?: string; apiUrl?: string; tunnel?: boolean; tunnelIdentifier?: string; username?: string }>
    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/types/aft_ui_mobile_apps.SauceLabsMobileAppSessionOptions.html b/docs/types/aft_ui_mobile_apps.SauceLabsMobileAppSessionOptions.html deleted file mode 100644 index 7444de0c..00000000 --- a/docs/types/aft_ui_mobile_apps.SauceLabsMobileAppSessionOptions.html +++ /dev/null @@ -1,90 +0,0 @@ -SauceLabsMobileAppSessionOptions | automated-functional-testing
    -
    - -
    -
    -
    -
    - -

    Type alias SauceLabsMobileAppSessionOptions

    -
    SauceLabsMobileAppSessionOptions: Merge<MobileAppSessionOptions, { accessKey?: string; tunnel?: boolean; tunnelIdentifier?: string; username?: string }>
    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/types/aft_ui_mobile_apps.SetSessionStatusRequest.html b/docs/types/aft_ui_mobile_apps.SetSessionStatusRequest.html deleted file mode 100644 index c7b7130a..00000000 --- a/docs/types/aft_ui_mobile_apps.SetSessionStatusRequest.html +++ /dev/null @@ -1,99 +0,0 @@ -SetSessionStatusRequest | automated-functional-testing
    -
    - -
    -
    -
    - -
    SetSessionStatusRequest: { message?: string; sessionId: string; status: "passed" | "failed" }
    -
    -

    Type declaration

    -
      -
    • -
      Optional message?: string
    • -
    • -
      sessionId: string
    • -
    • -
      status: "passed" | "failed"
    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/types/aft_ui_mobile_apps.UploadRequest.html b/docs/types/aft_ui_mobile_apps.UploadRequest.html deleted file mode 100644 index b34670f1..00000000 --- a/docs/types/aft_ui_mobile_apps.UploadRequest.html +++ /dev/null @@ -1,97 +0,0 @@ -UploadRequest | automated-functional-testing
    -
    - -
    -
    -
    - -
    UploadRequest: { custom_id?: string; file?: string }
    -
    -

    Type declaration

    -
      -
    • -
      Optional custom_id?: string
    • -
    • -
      Optional file?: string
    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/types/aft_ui_mobile_apps.UploadResponse.html b/docs/types/aft_ui_mobile_apps.UploadResponse.html deleted file mode 100644 index 5b100e57..00000000 --- a/docs/types/aft_ui_mobile_apps.UploadResponse.html +++ /dev/null @@ -1,99 +0,0 @@ -UploadResponse | automated-functional-testing
    -
    - -
    -
    -
    - -
    UploadResponse: { app_url: string; custom_id: string; shareable_id: string }
    -
    -

    Type declaration

    -
      -
    • -
      app_url: string
    • -
    • -
      custom_id: string
    • -
    • -
      shareable_id: string
    -
    -
    -

    Generated using TypeDoc

    -
    \ No newline at end of file diff --git a/docs/types/aft_ui.UiSessionGeneratorManagerOptions.html b/docs/types/aft_ui_selenium.SeleniumVerifierInternals.html similarity index 53% rename from docs/types/aft_ui.UiSessionGeneratorManagerOptions.html rename to docs/types/aft_ui_selenium.SeleniumVerifierInternals.html index 8bd8546a..79d7129e 100644 --- a/docs/types/aft_ui.UiSessionGeneratorManagerOptions.html +++ b/docs/types/aft_ui_selenium.SeleniumVerifierInternals.html @@ -1,4 +1,4 @@ -UiSessionGeneratorManagerOptions | automated-functional-testing
    +SeleniumVerifierInternals | automated-functional-testing
    +
    SeleniumVerifierInternals: Merge<VerifierInternals, { usingUiSessionGeneratorManager: ((mgr: UiSessionGeneratorManager) => Verifier) }>
    +
  • Defined in aft-ui-selenium/src/verification/selenium-verifier-internals.ts:4
  • +
  • GridSessionGeneratorPlugin
  • +
  • LocalSessionGeneratorPlugin
  • +
  • SeleniumComponent
  • +
  • SeleniumVerifier
  • +
  • SeleniumVerifierInternals
  • +
  • verifyWithSelenium
  • Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/types/aft_testrail.TestRailLoggingPluginOptions.html b/docs/types/aft_ui_webdriverio.WebdriverIoVerifierInternals.html similarity index 55% rename from docs/types/aft_testrail.TestRailLoggingPluginOptions.html rename to docs/types/aft_ui_webdriverio.WebdriverIoVerifierInternals.html index 7964f251..5ee10ce1 100644 --- a/docs/types/aft_testrail.TestRailLoggingPluginOptions.html +++ b/docs/types/aft_ui_webdriverio.WebdriverIoVerifierInternals.html @@ -1,4 +1,4 @@ -TestRailLoggingPluginOptions | automated-functional-testing
    +WebdriverIoVerifierInternals | automated-functional-testing
    +
    WebdriverIoVerifierInternals: Merge<VerifierInternals, { usingUiSessionGeneratorManager: ((mgr: UiSessionGeneratorManager) => Verifier) }>
    +
  • Defined in aft-ui-webdriverio/src/verification/webdriverio-verifier-internals.ts:4
  • +
  • WebdriverIoComponent
  • +
  • WebdriverIoRemoteSessionGeneratorPlugin
  • +
  • WebdriverIoVerifier
  • +
  • WebdriverIoVerifierInternals
  • +
  • verifyWithWebdriverIO
  • Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/functions/aft_core.LogManager.toConsole.html b/docs/types/aft_web_services.HttpHeaders.Accept.Acc.html similarity index 60% rename from docs/functions/aft_core.LogManager.toConsole.html rename to docs/types/aft_web_services.HttpHeaders.Accept.Acc.html index 68c35234..7fb836c8 100644 --- a/docs/functions/aft_core.LogManager.toConsole.html +++ b/docs/types/aft_web_services.HttpHeaders.Accept.Acc.html @@ -1,4 +1,4 @@ -toConsole | automated-functional-testing
    +Acc | automated-functional-testing
    +
    Acc: { Accept: string }
    +
    +

    Type declaration

    +
      +
    • +
      Accept: string
    +
  • Defined in aft-web-services/src/http/http-headers.ts:42
  • +
  • Acc
  • +
  • get
  • Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/types/aft_logging_awskinesis.KinesisLoggingPluginOptions.html b/docs/types/aft_web_services.HttpHeaders.Authorization.Auth.html similarity index 58% rename from docs/types/aft_logging_awskinesis.KinesisLoggingPluginOptions.html rename to docs/types/aft_web_services.HttpHeaders.Authorization.Auth.html index 640700a4..63d805ff 100644 --- a/docs/types/aft_logging_awskinesis.KinesisLoggingPluginOptions.html +++ b/docs/types/aft_web_services.HttpHeaders.Authorization.Auth.html @@ -1,4 +1,4 @@ -KinesisLoggingPluginOptions | automated-functional-testing
    +Auth | automated-functional-testing
    +
    Auth: { Authorization: string }
    +
    +

    Type declaration

    +
      +
    • +
      Authorization: string
    +
  • Defined in aft-web-services/src/http/http-headers.ts:52
  • +
  • Auth
  • +
  • DigestOptions
  • +
  • basic
  • +
  • digest
  • Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/types/aft_web_services.HttpHeaders.Authorization.DigestOptions.html b/docs/types/aft_web_services.HttpHeaders.Authorization.DigestOptions.html new file mode 100644 index 00000000..041ac7d5 --- /dev/null +++ b/docs/types/aft_web_services.HttpHeaders.Authorization.DigestOptions.html @@ -0,0 +1,99 @@ +DigestOptions | automated-functional-testing
    +
    + +
    +
    +
    + +
    DigestOptions: { algorithm: string; cnonce: string; nc: string; nonce: string; opaque: string; qop: string; realm: string; response: string; uri: string; username: string }
    +
    +

    Type declaration

    +
      +
    • +
      algorithm: string
    • +
    • +
      cnonce: string
    • +
    • +
      nc: string
    • +
    • +
      nonce: string
    • +
    • +
      opaque: string
    • +
    • +
      qop: string
    • +
    • +
      realm: string
    • +
    • +
      response: string
    • +
    • +
      uri: string
    • +
    • +
      username: string
    +
    +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/types/aft_logging_html.HtmlLoggingPluginOptions.html b/docs/types/aft_web_services.HttpHeaders.ContentType.CT.html similarity index 61% rename from docs/types/aft_logging_html.HtmlLoggingPluginOptions.html rename to docs/types/aft_web_services.HttpHeaders.ContentType.CT.html index 3ea94d55..135930da 100644 --- a/docs/types/aft_logging_html.HtmlLoggingPluginOptions.html +++ b/docs/types/aft_web_services.HttpHeaders.ContentType.CT.html @@ -1,4 +1,4 @@ -HtmlLoggingPluginOptions | automated-functional-testing
    +CT | automated-functional-testing
    +
    CT: { Content-Type: string }
    +
    +

    Type declaration

    +
      +
    • +
      Content-Type: string
    +
  • Defined in aft-web-services/src/http/http-headers.ts:32
  • +
  • CT
  • +
  • get
  • Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/functions/aft_core.LogManager.format.html b/docs/types/aft_web_services.HttpHeaders.Cookies.Cookie.html similarity index 59% rename from docs/functions/aft_core.LogManager.format.html rename to docs/types/aft_web_services.HttpHeaders.Cookies.Cookie.html index fe12cdcd..d508d10c 100644 --- a/docs/functions/aft_core.LogManager.format.html +++ b/docs/types/aft_web_services.HttpHeaders.Cookies.Cookie.html @@ -1,4 +1,4 @@ -format | automated-functional-testing
    +Cookie | automated-functional-testing
    +
    Cookie: { Cookie: string }
    +
    +

    Type declaration

    +
      +
    • +
      Cookie: string
    +
  • Defined in aft-web-services/src/http/http-headers.ts:90
  • +
  • Cookie
  • +
  • SetCookie
  • +
  • SetCookieOptions
  • +
  • cookie
  • +
  • setCookie
  • Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/types/aft_web_services.HttpHeaders.Cookies.SetCookie.html b/docs/types/aft_web_services.HttpHeaders.Cookies.SetCookie.html new file mode 100644 index 00000000..cd2f003f --- /dev/null +++ b/docs/types/aft_web_services.HttpHeaders.Cookies.SetCookie.html @@ -0,0 +1,82 @@ +SetCookie | automated-functional-testing
    +
    + +
    +
    +
    + +
    SetCookie: { Set-Cookie: string }
    +
    +

    Type declaration

    +
      +
    • +
      Set-Cookie: string
    +
    +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/types/aft_ui.UiSessionOptions.html b/docs/types/aft_web_services.HttpHeaders.Cookies.SetCookieOptions.html similarity index 52% rename from docs/types/aft_ui.UiSessionOptions.html rename to docs/types/aft_web_services.HttpHeaders.Cookies.SetCookieOptions.html index f66571ca..80d71fa9 100644 --- a/docs/types/aft_ui.UiSessionOptions.html +++ b/docs/types/aft_web_services.HttpHeaders.Cookies.SetCookieOptions.html @@ -1,4 +1,4 @@ -UiSessionOptions | automated-functional-testing
    +SetCookieOptions | automated-functional-testing
    +
    SetCookieOptions: { expires?: string; httpOnly?: boolean; key: string; secure?: boolean; val: string }

    Type declaration

    • -
      Optional driver?: unknown
    • +
      Optional expires?: string
    • -
      Optional logMgr?: LogManager
    • +
      Optional httpOnly?: boolean
    • -
      Optional uiplatform?: string
    +
  • Defined in aft-web-services/src/http/http-headers.ts:96
  • +
  • Cookie
  • +
  • SetCookie
  • +
  • SetCookieOptions
  • +
  • cookie
  • +
  • setCookie
  • Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/types/aft_web_services.HttpMethod.html b/docs/types/aft_web_services.HttpMethod.html index b4ee9279..f8a6b3e6 100644 --- a/docs/types/aft_web_services.HttpMethod.html +++ b/docs/types/aft_web_services.HttpMethod.html @@ -16,7 +16,7 @@

    Type alias HttpMethod

    HttpMethod: "GET" | "POST" | "PUT" | "UPDATE" | "DELETE"
    +
  • Defined in aft-web-services/src/http/http-custom-types.ts:4
  • +
  • httpService
  • Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/types/aft_web_services.HttpRequest.html b/docs/types/aft_web_services.HttpRequest.html index 8c6ec022..6e826c60 100644 --- a/docs/types/aft_web_services.HttpRequest.html +++ b/docs/types/aft_web_services.HttpRequest.html @@ -14,13 +14,13 @@
  • aft-web-services
  • HttpRequest
  • Type alias HttpRequest

    -
    HttpRequest: { allowAutoRedirect?: boolean; headers?: OutgoingHttpHeaders; logMgr?: LogManager; method?: HttpMethod; multipart?: boolean; postData?: any; url?: string }
    +
    HttpRequest: { allowAutoRedirect?: boolean; headers?: OutgoingHttpHeaders; method?: HttpMethod; multipart?: boolean; postData?: any; reporter?: Reporter; url?: string }

    to be used with the httpService.performRequest function like follows:

    -
    await httpService.performRequest({url: 'https://some.domain/path'});
    +
    await httpService.performRequest({url: 'https://some.domain/path'});
     

    or fully as:

    -
    await httpService.performRequest({
    url: 'https://some.domain/path',
    allowAutoRedirect: false,
    headers: {"Authorization": "basic AS0978FASLKLJA/=="},
    method: 'POST',
    postData: someObject,
    multipart: false
    }); +
    await httpService.performRequest({
    url: 'https://some.domain/path',
    allowAutoRedirect: false,
    headers: {"Authorization": "basic AS0978FASLKLJA/=="},
    method: 'POST',
    postData: someObject,
    multipart: false
    });
    @@ -31,17 +31,17 @@
    Optional allowAutoR
  • Optional headers?: OutgoingHttpHeaders
  • -
    Optional logMgr?: LogManager
  • -
  • Optional method?: HttpMethod
  • Optional multipart?: boolean
  • Optional postData?: any
  • +
    Optional reporter?: Reporter
  • +
  • Optional url?: string
  • +
  • Defined in aft-web-services/src/http/http-custom-types.ts:24
  • +
  • httpService
  • Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/types/aft_web_services.HttpResponse.html b/docs/types/aft_web_services.HttpResponse.html index 6e520e8a..b23032f7 100644 --- a/docs/types/aft_web_services.HttpResponse.html +++ b/docs/types/aft_web_services.HttpResponse.html @@ -29,7 +29,7 @@
    Optional headers
    Optional statusCode?: number
    +
  • Defined in aft-web-services/src/http/http-custom-types.ts:39
  • +
  • httpService
  • Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/variables/aft_core.SafeStringOption.defaults.html b/docs/variables/aft_core.SafeStringOption.defaults.html index 3182234c..21048107 100644 --- a/docs/variables/aft_core.SafeStringOption.defaults.html +++ b/docs/variables/aft_core.SafeStringOption.defaults.html @@ -22,7 +22,7 @@

    Variable defaultsConst

    string and the rest with underscore

    +
  • Defined in aft-core/src/helpers/convert.ts:30
  • +
    aftConfig: AftConfig = ...
    +
  • Defined in aft-core/src/configuration/aft-config.ts:259
  • +
    aftLogger: AftLogger = ...
    +

    a global instance of the AftLogger for use in AFT core components or systems +that should not log to any plugins

    +
    +
  • Defined in aft-core/src/logging/aft-logger.ts:128
  • convert: Convert = ...

    constant helper class for converting values to other values such as:

    -
    convert.toBase64Encoded('foo'); // returns 'Zm9v'
    convert.fromBase64Encoded('Zm9v'); // returns 'foo'
    convert.toSafeString('I am an Example!'); // returns 'I_am_an_Example'
    convert.toHoursMinutesSeconds(3666600); // returns '01:01:06.600' +
    convert.toBase64Encoded('foo'); // returns 'Zm9v'
    convert.fromBase64Encoded('Zm9v'); // returns 'foo'
    convert.toSafeString('I am an Example!'); // returns 'I_am_an_Example'
    convert.toHoursMinutesSeconds(3666600); // returns '01:01:06.600'
    +
  • Defined in aft-core/src/helpers/convert.ts:198
  • fileio: FileIO = ...
    +
  • Defined in aft-core/src/helpers/file-io.ts:96
  • machineInfo: MachineInfo = ...
    +
  • Defined in aft-core/src/helpers/machine-info.ts:49
  • +
    pluginLoader: PluginLoader = ...
    +

    attempts to load plugins by name and optional path.

    +
    // aftconfig.json
    {
    "pluginsSearchDir": "../",
    "pluginNames": [
    "testrail-reporting-plugin",
    "testrail-test-execution-policy-plugin"
    "html-reporting-plugin"
    ]
    }
    -

    NOTE: the above attempts to load a custom-plugin class. if loading -fails then it will search the filesystem, starting at the current -execution directory and searching all subdirectories, for a file -named custom-plugin.js which, if found, will be imported and a -new instance will be created and added to the internal cache and the -array to be returned

    +

    NOTE: the above will attempt to load a testrail-reporting-plugin, +testrail-test-execution-policy-plugin and html-reporting-plugin class. if loading +fails then it will search the filesystem, starting at the relative +pluginsSearchDir path (relative to current nodejs execution dir) +and searching all subdirectories, for a file named custom-plugin.js +which, if found, will be imported and a new instance will be created +and added to the internal cache and the array to be returned

    +
  • Defined in aft-core/src/plugins/plugin-loader.ts:203
  • helper class used for generating random test data and value

    +
  • Defined in aft-core/src/helpers/rand.ts:123
  • wait: Wait = ...
    +
  • Defined in aft-core/src/helpers/wait.ts:49
  • +
    textHtml: "text/html" = 'text/html'
    +
  • Defined in aft-web-services/src/http/http-headers.ts:25
  • +
  • applicationJson
  • +
  • applicationOctetstream
  • +
  • multipartFormData
  • +
  • textCss
  • +
  • textHtml
  • +
  • textJavascript
  • +
  • textPlain
  • +
  • textXml
  • Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/variables/aft_web_services.HttpHeaders.MimeType.textJavascript.html b/docs/variables/aft_web_services.HttpHeaders.MimeType.textJavascript.html new file mode 100644 index 00000000..e9b911d8 --- /dev/null +++ b/docs/variables/aft_web_services.HttpHeaders.MimeType.textJavascript.html @@ -0,0 +1,80 @@ +textJavascript | automated-functional-testing
    +
    + +
    + +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/variables/aft_web_services.HttpHeaders.MimeType.textPlain.html b/docs/variables/aft_web_services.HttpHeaders.MimeType.textPlain.html new file mode 100644 index 00000000..f4fa53db --- /dev/null +++ b/docs/variables/aft_web_services.HttpHeaders.MimeType.textPlain.html @@ -0,0 +1,80 @@ +textPlain | automated-functional-testing
    +
    + +
    + +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/variables/aft_web_services.HttpHeaders.MimeType.textXml.html b/docs/variables/aft_web_services.HttpHeaders.MimeType.textXml.html new file mode 100644 index 00000000..241bb904 --- /dev/null +++ b/docs/variables/aft_web_services.HttpHeaders.MimeType.textXml.html @@ -0,0 +1,80 @@ +textXml | automated-functional-testing
    +
    + +
    + +
    +

    Generated using TypeDoc

    +
    \ No newline at end of file diff --git a/docs/variables/aft_web_services.httpData.html b/docs/variables/aft_web_services.httpData.html index 11c41bff..1be74a64 100644 --- a/docs/variables/aft_web_services.httpData.html +++ b/docs/variables/aft_web_services.httpData.html @@ -16,7 +16,7 @@

    Variable httpDataConst

    httpData: HttpData = ...
    +
  • Defined in aft-web-services/src/http/http-data.ts:34
  • +
  • httpService
  • Generated using TypeDoc

    \ No newline at end of file diff --git a/docs/variables/aft_web_services.httpService.html b/docs/variables/aft_web_services.httpService-1.html similarity index 61% rename from docs/variables/aft_web_services.httpService.html rename to docs/variables/aft_web_services.httpService-1.html index 72fd98f6..86779109 100644 --- a/docs/variables/aft_web_services.httpService.html +++ b/docs/variables/aft_web_services.httpService-1.html @@ -12,25 +12,25 @@ +
  • httpService
  • Variable httpServiceConst

    -
    httpService: HttpService = ...
    +
    httpService: HttpService = ...

    supports performing requests over http / https returning the response as a HttpResponse object. Requests should include a URL at a minimum, but may also specify additional details such as headers, auto redirect, post data and the request method (GET|POST|PUT|DELETE|UPDATE) ex:

    -
    await httpService.performRequest({url: 'https://some.domain/path'});
    +
    await httpService.performRequest({url: 'https://some.domain/path'});
     

    or fully as:

    -
    await httpService.performRequest({
    url: 'https://some.domain/path',
    allowAutoRedirect: false,
    headers: {"Authorization": "basic AS0978FASLKLJA/=="},
    method: 'POST',
    postData: someObject,
    multipart: false
    }); +
    await httpService.performRequest({
    url: 'https://some.domain/path',
    allowAutoRedirect: false,
    headers: {...HttpHeaders.Authorization.basic('myUser', 'myPass')},
    method: 'POST',
    postData: someObject,
    multipart: false
    });

    or multipart post as:

    -
    let formData = new FormData();
    formData.append("Authorization": "basic AS0978FASLKLJA/==");
    await httpService.performRequest({
    url: 'https://some.domain/path',
    allowAutoRedirect: false,
    method: 'POST',
    postData: formData,
    multipart: true
    }); +
    let formData = new FormData();
    formData.append('file', fs.createReadStream('/path/to/file.ext'));
    await httpService.performRequest({
    url: 'https://some.domain/path',
    allowAutoRedirect: false,
    headers: {...HttpHeaders.Authorization.basic('myUser', 'myPass')}
    method: 'POST',
    postData: formData,
    multipart: true
    });
    +
  • Defined in aft-web-services/src/http/http-service.ts:242
  • +
  • httpService
  • Generated using TypeDoc

    \ No newline at end of file diff --git a/lerna.json b/lerna.json index 34a1403c..81092f36 100644 --- a/lerna.json +++ b/lerna.json @@ -2,5 +2,5 @@ "packages": [ "packages/*" ], - "version": "9.0.0" + "version": "10.0.0" } diff --git a/package-lock.json b/package-lock.json index 53e3e17f..1aea7f86 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2143,6 +2143,12 @@ "@types/node": "*" } }, + "node_modules/@types/lodash": { + "version": "4.14.194", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.194.tgz", + "integrity": "sha512-r22s9tAS7imvBt2lyHC9B8AGwWnXaYb1tY09oyLkXDs4vArpYJzw09nj8MLx5VfciBPGIb+ZwG0ssYnEPJxn/g==", + "dev": true + }, "node_modules/@types/minimatch": { "version": "3.0.5", "dev": true, @@ -2397,20 +2403,20 @@ "resolved": "packages/aft-jasmine-reporter", "link": true }, - "node_modules/aft-logging-awskinesis": { - "resolved": "packages/aft-logging-awskinesis", + "node_modules/aft-mocha-reporter": { + "resolved": "packages/aft-mocha-reporter", "link": true }, - "node_modules/aft-logging-filesystem": { - "resolved": "packages/aft-logging-filesystem", + "node_modules/aft-reporting-aws-kinesis-firehose": { + "resolved": "packages/aft-reporting-aws-kinesis-firehose", "link": true }, - "node_modules/aft-logging-html": { - "resolved": "packages/aft-logging-html", + "node_modules/aft-reporting-filesystem": { + "resolved": "packages/aft-reporting-filesystem", "link": true }, - "node_modules/aft-mocha-reporter": { - "resolved": "packages/aft-mocha-reporter", + "node_modules/aft-reporting-html": { + "resolved": "packages/aft-reporting-html", "link": true }, "node_modules/aft-testrail": { @@ -2421,12 +2427,12 @@ "resolved": "packages/aft-ui", "link": true }, - "node_modules/aft-ui-browsers": { - "resolved": "packages/aft-ui-browsers", + "node_modules/aft-ui-selenium": { + "resolved": "packages/aft-ui-selenium", "link": true }, - "node_modules/aft-ui-mobile-apps": { - "resolved": "packages/aft-ui-mobile-apps", + "node_modules/aft-ui-webdriverio": { + "resolved": "packages/aft-ui-webdriverio", "link": true }, "node_modules/aft-web-services": { @@ -2697,9 +2703,21 @@ "node": ">= 4.0.0" } }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/aws-sdk": { - "version": "2.1151.0", - "license": "Apache-2.0", + "version": "2.1373.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1373.0.tgz", + "integrity": "sha512-3/P79VU2VVeiof25bn8TSepEhWCRhwuQGYoEWX/2pApQRJAY+w/3JFVKHjbAe3NYEEBNeiAE6PQ9DqWz5Pp+Lw==", "dependencies": { "buffer": "4.9.2", "events": "1.1.1", @@ -2708,8 +2726,9 @@ "querystring": "0.2.0", "sax": "1.2.1", "url": "0.10.3", + "util": "^0.12.4", "uuid": "8.0.0", - "xml2js": "0.4.19" + "xml2js": "0.5.0" }, "engines": { "node": ">= 10.0.0" @@ -3059,6 +3078,18 @@ "node": ">=8" } }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -4355,6 +4386,14 @@ "flat": "cli.js" } }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dependencies": { + "is-callable": "^1.1.3" + } + }, "node_modules/foreground-child": { "version": "2.0.0", "dev": true, @@ -4459,8 +4498,7 @@ "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "node_modules/gauge": { "version": "4.0.4", @@ -4504,6 +4542,19 @@ "node": "*" } }, + "node_modules/get-intrinsic": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", + "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/get-package-type": { "version": "0.1.0", "dev": true, @@ -4745,6 +4796,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/got": { "version": "11.8.5", "resolved": "https://registry.npmjs.org/got/-/got-11.8.5.tgz", @@ -4811,7 +4873,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "dependencies": { "function-bind": "^1.1.1" }, @@ -4826,6 +4887,31 @@ "node": ">=8" } }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", @@ -4892,8 +4978,9 @@ "license": "MIT" }, "node_modules/http-cache-semantics": { - "version": "4.1.0", - "license": "BSD-2-Clause" + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" }, "node_modules/http-proxy-agent": { "version": "5.0.0", @@ -5032,7 +5119,8 @@ }, "node_modules/immediate": { "version": "3.0.6", - "license": "MIT" + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==" }, "node_modules/import-fresh": { "version": "3.3.0", @@ -5194,6 +5282,21 @@ "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", "dev": true }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -5211,6 +5314,17 @@ "node": ">=8" } }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-ci": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", @@ -5263,6 +5377,20 @@ "node": ">=8" } }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -5353,6 +5481,24 @@ "node": ">=0.10.0" } }, + "node_modules/is-typed-array": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", + "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-typedarray": { "version": "1.0.0", "dev": true, @@ -5546,6 +5692,64 @@ "dev": true, "license": "MIT" }, + "node_modules/jasmine-ts": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/jasmine-ts/-/jasmine-ts-0.4.0.tgz", + "integrity": "sha512-bIAWJKUwxfuZfGI1ctEbny7+dsyFzsN0eLzOokxh0qIUCofai2WUEKoe3MMllkGEBXJzbEVYr2IyhJBv4j7SBA==", + "dev": true, + "dependencies": { + "yargs": "^17.0.1" + }, + "bin": { + "jasmine-ts": "lib/index.js" + }, + "peerDependencies": { + "jasmine": ">=3.4", + "ts-node": ">=3.2.0 <=11", + "typescript": ">=3.5.2" + } + }, + "node_modules/jasmine-ts/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/jasmine-ts/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/jasmine-ts/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "node_modules/jmespath": { "version": "0.16.0", "license": "Apache-2.0", @@ -5621,9 +5825,10 @@ "dev": true }, "node_modules/json5": { - "version": "2.2.1", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, - "license": "MIT", "bin": { "json5": "lib/cli.js" }, @@ -5673,8 +5878,9 @@ } }, "node_modules/jszip": { - "version": "3.10.0", - "license": "(MIT OR GPL-3.0-or-later)", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", "dependencies": { "lie": "~3.3.0", "pako": "~1.0.2", @@ -5683,8 +5889,9 @@ } }, "node_modules/jszip/node_modules/readable-stream": { - "version": "2.3.7", - "license": "MIT", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -5697,11 +5904,13 @@ }, "node_modules/jszip/node_modules/safe-buffer": { "version": "5.1.2", - "license": "MIT" + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "node_modules/jszip/node_modules/string_decoder": { "version": "1.1.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dependencies": { "safe-buffer": "~5.1.0" } @@ -5920,7 +6129,8 @@ }, "node_modules/lie": { "version": "3.3.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", "dependencies": { "immediate": "~3.0.5" } @@ -7794,7 +8004,8 @@ }, "node_modules/pako": { "version": "1.0.11", - "license": "(MIT AND Zlib)" + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" }, "node_modules/parent-module": { "version": "1.0.1", @@ -8717,15 +8928,16 @@ "license": "ISC" }, "node_modules/selenium-webdriver": { - "version": "4.3.0", - "license": "Apache-2.0", + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-4.9.2.tgz", + "integrity": "sha512-0gDswAgVn6qbCYckZetQQvQK9tWW1r7LaumhiqY1/Wl/7JEWG0JANsTbZKnmGc3+cUU76zAi5/p0P8LUweXlig==", "dependencies": { - "jszip": "^3.10.0", + "jszip": "^3.10.1", "tmp": "^0.2.1", - "ws": ">=8.7.0" + "ws": ">=8.13.0" }, "engines": { - "node": ">= 10.15.0" + "node": ">= 14.20.0" } }, "node_modules/selenium-webdriver/node_modules/tmp": { @@ -8803,7 +9015,8 @@ }, "node_modules/setimmediate": { "version": "1.0.5", - "license": "MIT" + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" }, "node_modules/shallow-clone": { "version": "3.0.1", @@ -8960,8 +9173,9 @@ }, "node_modules/source-map-support": { "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, - "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -9381,9 +9595,10 @@ } }, "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.1", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, - "license": "MIT", "dependencies": { "minimist": "^1.2.0" }, @@ -9492,7 +9707,9 @@ } }, "node_modules/ua-parser-js": { - "version": "1.0.2", + "version": "1.0.35", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.35.tgz", + "integrity": "sha512-fKnGuqmTBnIE+/KXSzCn4db8RTigUzw1AN0DmdU6hJovUTbYJKyqj+8Mt1c4VfRDnOVJnENmfYkIPZ946UrSAA==", "funding": [ { "type": "opencollective", @@ -9503,7 +9720,6 @@ "url": "https://paypal.me/faisalman" } ], - "license": "MIT", "engines": { "node": "*" } @@ -9588,6 +9804,18 @@ "version": "1.3.2", "license": "MIT" }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "license": "MIT" @@ -9759,6 +9987,25 @@ "dev": true, "license": "ISC" }, + "node_modules/which-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", + "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/wide-align": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", @@ -9942,14 +10189,15 @@ } }, "node_modules/ws": { - "version": "8.8.0", - "license": "MIT", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", "engines": { "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { @@ -9961,20 +10209,21 @@ } }, "node_modules/xml2js": { - "version": "0.4.19", - "license": "MIT", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", + "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", "dependencies": { "sax": ">=0.6.0", - "xmlbuilder": "~9.0.1" + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" } }, - "node_modules/xml2js/node_modules/sax": { - "version": "1.2.4", - "license": "ISC" - }, "node_modules/xmlbuilder": { - "version": "9.0.7", - "license": "MIT", + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", "engines": { "node": ">=4.0" } @@ -10118,11 +10367,32 @@ "node": ">= 10" } }, - "packages/aft-core": { + "packages/aft-browserstack-automate": { "version": "9.0.0", + "extraneous": true, + "license": "MIT", + "dependencies": { + "aft-selenium": "^9.0.0", + "selenium-webdriver": "^4.3.0" + }, + "devDependencies": { + "@types/jasmine": "^3.6.10", + "@types/node": "^15.0.1", + "@types/selenium-webdriver": "^4.0.12", + "jasmine": "^3.7.0", + "jasmine-ts": "^0.4.0", + "nyc": "^15.1.0", + "rimraf": "^3.0.2", + "ts-node": "^10.7.0", + "typescript": "^4.3.2" + } + }, + "packages/aft-core": { + "version": "10.0.0", "license": "MIT", "dependencies": { "colors": "^1.4.0", + "dotenv": "^16.0.3", "fs-ext": "^2.0.0", "lodash": "^4.17.21", "uuid": "^8.3.2" @@ -10132,10 +10402,11 @@ "@types/jasmine": "^3.6.10", "@types/node": "^17.0.31", "@types/uuid": "^8.3.0", - "jasmine": "^3.7.0", + "jasmine": "^4.6.0", "jasmine-ts": "^0.4.0", "nyc": "^15.1.0", "rimraf": "^3.0.2", + "source-map-support": "^0.5.21", "ts-node": "^10.7.0", "typescript": "^4.6.4" } @@ -10151,22 +10422,33 @@ "node": ">=12" } }, - "packages/aft-core/node_modules/jasmine-ts": { - "version": "0.4.0", + "packages/aft-core/node_modules/dotenv": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", + "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", + "engines": { + "node": ">=12" + } + }, + "packages/aft-core/node_modules/jasmine": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-4.6.0.tgz", + "integrity": "sha512-iq7HQ5M8ydNUspjd9vbFW9Lu+6lQ1QLDIqjl0WysEllF5EJZy8XaUyNlhCJVwOx2YFzqTtARWbS56F/f0PzRFw==", "dev": true, - "license": "MIT", "dependencies": { - "yargs": "^17.0.1" + "glob": "^7.1.6", + "jasmine-core": "^4.6.0" }, "bin": { - "jasmine-ts": "lib/index.js" - }, - "peerDependencies": { - "jasmine": ">=3.4", - "ts-node": ">=3.2.0 <=11", - "typescript": ">=3.5.2" + "jasmine": "bin/jasmine.js" } }, + "packages/aft-core/node_modules/jasmine-core": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-4.6.0.tgz", + "integrity": "sha512-O236+gd0ZXS8YAjFx8xKaJ94/erqUliEkJTDedyE7iHvv4ZVqi+q+8acJxu05/WJDKm512EUNn809In37nWlAQ==", + "dev": true + }, "packages/aft-core/node_modules/ts-node": { "version": "10.7.0", "dev": true, @@ -10209,42 +10491,18 @@ } } }, - "packages/aft-core/node_modules/yargs": { - "version": "17.4.1", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "packages/aft-core/node_modules/yargs-parser": { - "version": "21.0.1", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, "packages/aft-examples": { - "version": "9.0.0", + "version": "10.0.0", "license": "MIT", "dependencies": { - "aft-logging-awskinesis": "^9.0.0", - "aft-logging-filesystem": "^9.0.0", - "aft-logging-html": "^9.0.0", - "aft-mocha-reporter": "^9.0.0", - "aft-testrail": "^9.0.0", - "aft-ui-browsers": "^9.0.0", - "aft-ui-mobile-apps": "^9.0.0" + "aft-mocha-reporter": "^10.0.0", + "aft-reporting-aws-kinesis-firehose": "^10.0.0", + "aft-reporting-filesystem": "^10.0.0", + "aft-reporting-html": "^10.0.0", + "aft-testrail": "^10.0.0", + "aft-ui-selenium": "^10.0.0", + "aft-ui-webdriverio": "^10.0.0", + "aft-web-services": "^10.0.0" }, "devDependencies": { "@types/chai": "^4.2.17", @@ -10265,17 +10523,17 @@ "license": "MIT" }, "packages/aft-jasmine-reporter": { - "version": "9.0.0", + "version": "10.0.0", "license": "MIT", "dependencies": { - "aft-core": "^9.0.0", + "aft-core": "^10.0.0", "jasmine": "^4.2.1" }, "devDependencies": { "@types/jasmine": "^4.0.3", "@types/node": "^18.0.1", - "aft-logging-filesystem": "^9.0.0", - "aft-logging-html": "^9.0.0", + "aft-reporting-filesystem": "^10.0.0", + "aft-reporting-html": "^10.0.0", "nyc": "^15.1.0", "rimraf": "^3.0.2", "ts-node": "^10.8.2", @@ -10349,63 +10607,43 @@ } } }, - "packages/aft-logging-awskinesis": { - "version": "9.0.0", + "packages/aft-mocha-reporter": { + "version": "10.0.0", "license": "MIT", "dependencies": { - "aft-core": "^9.0.0", - "aws-sdk": "^2.1151.0" + "aft-core": "^10.0.0", + "mocha": "^10.0.0" }, "devDependencies": { - "@aws-sdk/types": "^3.78.0", - "@types/jasmine": "^3.6.10", - "@types/node": "^15.0.1", - "jasmine": "^3.7.0", - "jasmine-ts": "^0.4.0", + "@types/mocha": "^9.1.1", + "@types/node": "^18.0.0", + "@types/sinon": "^10.0.12", + "aft-reporting-filesystem": "^10.0.0", + "aft-reporting-html": "^10.0.0", + "chai": "^4.3.6", "nyc": "^15.1.0", "rimraf": "^3.0.2", - "ts-node": "^10.7.0", - "typescript": "^4.3.2" - } - }, - "packages/aft-logging-awskinesis/node_modules/@cspotcode/source-map-support": { - "version": "0.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@cspotcode/source-map-consumer": "0.8.0" - }, - "engines": { - "node": ">=12" + "sinon": "^14.0.0", + "ts-node": "^10.8.1", + "typescript": "^4.7.4" } }, - "packages/aft-logging-awskinesis/node_modules/@types/node": { - "version": "15.14.9", + "packages/aft-mocha-reporter/node_modules/@types/mocha": { + "version": "9.1.1", "dev": true, "license": "MIT" }, - "packages/aft-logging-awskinesis/node_modules/jasmine-ts": { - "version": "0.4.0", + "packages/aft-mocha-reporter/node_modules/@types/node": { + "version": "18.0.0", "dev": true, - "license": "MIT", - "dependencies": { - "yargs": "^17.0.1" - }, - "bin": { - "jasmine-ts": "lib/index.js" - }, - "peerDependencies": { - "jasmine": ">=3.4", - "ts-node": ">=3.2.0 <=11", - "typescript": ">=3.5.2" - } + "license": "MIT" }, - "packages/aft-logging-awskinesis/node_modules/ts-node": { - "version": "10.7.0", + "packages/aft-mocha-reporter/node_modules/ts-node": { + "version": "10.8.1", "dev": true, "license": "MIT", "dependencies": { - "@cspotcode/source-map-support": "0.7.0", + "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", "@tsconfig/node12": "^1.0.7", "@tsconfig/node14": "^1.0.0", @@ -10416,7 +10654,7 @@ "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.0", + "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" }, "bin": { @@ -10442,79 +10680,36 @@ } } }, - "packages/aft-logging-awskinesis/node_modules/yargs": { - "version": "17.4.1", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "packages/aft-logging-awskinesis/node_modules/yargs-parser": { - "version": "21.0.1", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "packages/aft-logging-filesystem": { - "version": "9.0.0", + "packages/aft-reporting-aws-kinesis-firehose": { + "version": "10.0.0", "license": "MIT", "dependencies": { - "aft-core": "^9.0.0", - "date-and-time": "^2.4.0" + "aft-core": "^10.0.0", + "aws-sdk": "^2.1151.0" }, "devDependencies": { - "@types/jasmine": "^4.0.3", - "@types/node": "^18.0.0", + "@aws-sdk/types": "^3.78.0", + "@types/jasmine": "^3.6.10", + "@types/node": "^15.0.1", "jasmine": "^3.7.0", "jasmine-ts": "^0.4.0", "nyc": "^15.1.0", "rimraf": "^3.0.2", - "ts-node": "^10.8.1", - "typescript": "^4.7.4" + "ts-node": "^10.7.0", + "typescript": "^4.3.2" } }, - "packages/aft-logging-filesystem/node_modules/@types/jasmine": { - "version": "4.0.3", - "dev": true, - "license": "MIT" - }, - "packages/aft-logging-filesystem/node_modules/@types/node": { - "version": "18.0.0", - "dev": true, - "license": "MIT" - }, - "packages/aft-logging-filesystem/node_modules/jasmine-ts": { - "version": "0.4.0", - "dev": true, - "license": "MIT", - "dependencies": { - "yargs": "^17.0.1" - }, - "bin": { - "jasmine-ts": "lib/index.js" - }, - "peerDependencies": { - "jasmine": ">=3.4", - "ts-node": ">=3.2.0 <=11", - "typescript": ">=3.5.2" - } + "packages/aft-reporting-aws-kinesis-firehose/node_modules/@types/node": { + "version": "15.14.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.14.9.tgz", + "integrity": "sha512-qjd88DrCxupx/kJD5yQgZdcYKZKSIGBVDIBE1/LTGcNm3d2Np/jxojkdePDdfnBHJc5W7vSMpbJ1aB7p/Py69A==", + "dev": true }, - "packages/aft-logging-filesystem/node_modules/ts-node": { - "version": "10.8.1", + "packages/aft-reporting-aws-kinesis-firehose/node_modules/ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", "dev": true, - "license": "MIT", "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -10553,38 +10748,16 @@ } } }, - "packages/aft-logging-filesystem/node_modules/yargs": { - "version": "17.4.1", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "packages/aft-logging-filesystem/node_modules/yargs-parser": { - "version": "21.0.1", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "packages/aft-logging-html": { + "packages/aft-reporting-awskinesis": { "version": "9.0.0", + "extraneous": true, "license": "MIT", "dependencies": { - "aft-core": "^9.0.0" + "aft-core": "^9.0.0", + "aws-sdk": "^2.1151.0" }, "devDependencies": { + "@aws-sdk/types": "^3.78.0", "@types/jasmine": "^3.6.10", "@types/node": "^15.0.1", "jasmine": "^3.7.0", @@ -10595,44 +10768,40 @@ "typescript": "^4.3.2" } }, - "packages/aft-logging-html/node_modules/@cspotcode/source-map-support": { - "version": "0.7.0", - "dev": true, + "packages/aft-reporting-filesystem": { + "version": "10.0.0", "license": "MIT", "dependencies": { - "@cspotcode/source-map-consumer": "0.8.0" + "aft-core": "^10.0.0", + "date-and-time": "^2.4.0" }, - "engines": { - "node": ">=12" + "devDependencies": { + "@types/jasmine": "^4.0.3", + "@types/node": "^18.0.0", + "jasmine": "^3.7.0", + "jasmine-ts": "^0.4.0", + "nyc": "^15.1.0", + "rimraf": "^3.0.2", + "ts-node": "^10.8.1", + "typescript": "^4.7.4" } }, - "packages/aft-logging-html/node_modules/@types/node": { - "version": "15.14.9", + "packages/aft-reporting-filesystem/node_modules/@types/jasmine": { + "version": "4.0.3", "dev": true, "license": "MIT" }, - "packages/aft-logging-html/node_modules/jasmine-ts": { - "version": "0.4.0", + "packages/aft-reporting-filesystem/node_modules/@types/node": { + "version": "18.0.0", "dev": true, - "license": "MIT", - "dependencies": { - "yargs": "^17.0.1" - }, - "bin": { - "jasmine-ts": "lib/index.js" - }, - "peerDependencies": { - "jasmine": ">=3.4", - "ts-node": ">=3.2.0 <=11", - "typescript": ">=3.5.2" - } + "license": "MIT" }, - "packages/aft-logging-html/node_modules/ts-node": { - "version": "10.7.0", + "packages/aft-reporting-filesystem/node_modules/ts-node": { + "version": "10.8.1", "dev": true, "license": "MIT", "dependencies": { - "@cspotcode/source-map-support": "0.7.0", + "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", "@tsconfig/node12": "^1.0.7", "@tsconfig/node14": "^1.0.0", @@ -10643,7 +10812,7 @@ "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.0", + "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" }, "bin": { @@ -10669,68 +10838,45 @@ } } }, - "packages/aft-logging-html/node_modules/yargs": { - "version": "17.4.1", - "dev": true, + "packages/aft-reporting-html": { + "version": "10.0.0", "license": "MIT", "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" + "aft-core": "^10.0.0" }, - "engines": { - "node": ">=12" + "devDependencies": { + "@types/jasmine": "^3.6.10", + "@types/node": "^15.0.1", + "jasmine": "^3.7.0", + "jasmine-ts": "^0.4.0", + "nyc": "^15.1.0", + "rimraf": "^3.0.2", + "ts-node": "^10.7.0", + "typescript": "^4.3.2" } }, - "packages/aft-logging-html/node_modules/yargs-parser": { - "version": "21.0.1", + "packages/aft-reporting-html/node_modules/@cspotcode/source-map-support": { + "version": "0.7.0", "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "packages/aft-mocha-reporter": { - "version": "9.0.0", "license": "MIT", "dependencies": { - "aft-core": "^9.0.0", - "mocha": "^10.0.0" + "@cspotcode/source-map-consumer": "0.8.0" }, - "devDependencies": { - "@types/mocha": "^9.1.1", - "@types/node": "^18.0.0", - "@types/sinon": "^10.0.12", - "aft-logging-filesystem": "^9.0.0", - "aft-logging-html": "^9.0.0", - "chai": "^4.3.6", - "nyc": "^15.1.0", - "rimraf": "^3.0.2", - "sinon": "^14.0.0", - "ts-node": "^10.8.1", - "typescript": "^4.7.4" + "engines": { + "node": ">=12" } }, - "packages/aft-mocha-reporter/node_modules/@types/mocha": { - "version": "9.1.1", - "dev": true, - "license": "MIT" - }, - "packages/aft-mocha-reporter/node_modules/@types/node": { - "version": "18.0.0", + "packages/aft-reporting-html/node_modules/@types/node": { + "version": "15.14.9", "dev": true, "license": "MIT" }, - "packages/aft-mocha-reporter/node_modules/ts-node": { - "version": "10.8.1", + "packages/aft-reporting-html/node_modules/ts-node": { + "version": "10.7.0", "dev": true, "license": "MIT", "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", + "@cspotcode/source-map-support": "0.7.0", "@tsconfig/node10": "^1.0.7", "@tsconfig/node12": "^1.0.7", "@tsconfig/node14": "^1.0.0", @@ -10741,7 +10887,7 @@ "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", + "v8-compile-cache-lib": "^3.0.0", "yn": "3.1.1" }, "bin": { @@ -10767,11 +10913,30 @@ } } }, - "packages/aft-testrail": { + "packages/aft-selenium": { "version": "9.0.0", + "extraneous": true, "license": "MIT", "dependencies": { - "aft-web-services": "^9.0.0" + "aft-core": "^9.0.0", + "selenium-webdriver": "^4.9.2" + }, + "devDependencies": { + "@types/jasmine": "^3.6.10", + "@types/node": "^15.0.1", + "jasmine": "^3.7.0", + "jasmine-ts": "^0.4.0", + "nyc": "^15.1.0", + "rimraf": "^3.0.2", + "ts-node": "^10.7.0", + "typescript": "^4.3.2" + } + }, + "packages/aft-testrail": { + "version": "10.0.0", + "license": "MIT", + "dependencies": { + "aft-web-services": "^10.0.0" }, "devDependencies": { "@types/jasmine": "^3.6.10", @@ -10800,22 +10965,6 @@ "dev": true, "license": "MIT" }, - "packages/aft-testrail/node_modules/jasmine-ts": { - "version": "0.4.0", - "dev": true, - "license": "MIT", - "dependencies": { - "yargs": "^17.0.1" - }, - "bin": { - "jasmine-ts": "lib/index.js" - }, - "peerDependencies": { - "jasmine": ">=3.4", - "ts-node": ">=3.2.0 <=11", - "typescript": ">=3.5.2" - } - }, "packages/aft-testrail/node_modules/ts-node": { "version": "10.7.0", "dev": true, @@ -10858,36 +11007,11 @@ } } }, - "packages/aft-testrail/node_modules/yargs": { - "version": "17.4.1", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "packages/aft-testrail/node_modules/yargs-parser": { - "version": "21.0.1", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, "packages/aft-ui": { - "version": "9.0.0", + "version": "10.0.0", "license": "MIT", "dependencies": { - "aft-core": "^9.0.0" + "aft-core": "^10.0.0" }, "devDependencies": { "@types/jasmine": "^3.6.10", @@ -10902,6 +11026,7 @@ }, "packages/aft-ui-browsers": { "version": "9.0.0", + "extraneous": true, "license": "MIT", "dependencies": { "aft-ui": "^9.0.0", @@ -10919,44 +11044,59 @@ "typescript": "^4.3.2" } }, - "packages/aft-ui-browsers/node_modules/@cspotcode/source-map-support": { - "version": "0.7.0", - "dev": true, + "packages/aft-ui-mobile-apps": { + "version": "9.0.0", + "extraneous": true, "license": "MIT", "dependencies": { - "@cspotcode/source-map-consumer": "0.8.0" + "aft-ui": "^9.0.0", + "aft-web-services": "^9.0.0", + "webdriverio": "^7.5.7" }, - "engines": { - "node": ">=12" + "devDependencies": { + "@types/jasmine": "^3.6.10", + "@types/node": "^15.0.1", + "jasmine": "^3.7.0", + "jasmine-ts": "^0.4.0", + "nyc": "^15.1.0", + "rimraf": "^3.0.2", + "ts-node": "^10.7.0", + "typescript": "^4.3.2" } }, - "packages/aft-ui-browsers/node_modules/@types/node": { - "version": "15.14.9", - "dev": true, - "license": "MIT" - }, - "packages/aft-ui-browsers/node_modules/jasmine-ts": { - "version": "0.4.0", - "dev": true, + "packages/aft-ui-selenium": { + "version": "10.0.0", "license": "MIT", "dependencies": { - "yargs": "^17.0.1" - }, - "bin": { - "jasmine-ts": "lib/index.js" + "aft-ui": "^10.0.0", + "selenium-webdriver": "^4.3.0" }, - "peerDependencies": { - "jasmine": ">=3.4", - "ts-node": ">=3.2.0 <=11", - "typescript": ">=3.5.2" + "devDependencies": { + "@types/jasmine": "^3.6.10", + "@types/lodash": "^4.14.194", + "@types/node": "^15.0.1", + "@types/selenium-webdriver": "^4.0.12", + "jasmine": "^3.7.0", + "jasmine-ts": "^0.4.0", + "nyc": "^15.1.0", + "rimraf": "^3.0.2", + "ts-node": "^10.7.0", + "typescript": "^4.3.2" } }, - "packages/aft-ui-browsers/node_modules/ts-node": { - "version": "10.7.0", + "packages/aft-ui-selenium/node_modules/@types/node": { + "version": "15.14.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.14.9.tgz", + "integrity": "sha512-qjd88DrCxupx/kJD5yQgZdcYKZKSIGBVDIBE1/LTGcNm3d2Np/jxojkdePDdfnBHJc5W7vSMpbJ1aB7p/Py69A==", + "dev": true + }, + "packages/aft-ui-selenium/node_modules/ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", "dev": true, - "license": "MIT", "dependencies": { - "@cspotcode/source-map-support": "0.7.0", + "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", "@tsconfig/node12": "^1.0.7", "@tsconfig/node14": "^1.0.0", @@ -10967,7 +11107,7 @@ "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.0", + "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" }, "bin": { @@ -10993,37 +11133,11 @@ } } }, - "packages/aft-ui-browsers/node_modules/yargs": { - "version": "17.4.1", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "packages/aft-ui-browsers/node_modules/yargs-parser": { - "version": "21.0.1", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "packages/aft-ui-mobile-apps": { - "version": "9.0.0", + "packages/aft-ui-webdriverio": { + "version": "10.0.0", "license": "MIT", "dependencies": { - "aft-ui": "^9.0.0", - "aft-web-services": "^9.0.0", + "aft-ui": "^10.0.0", "webdriverio": "^7.5.7" }, "devDependencies": { @@ -11037,44 +11151,19 @@ "typescript": "^4.3.2" } }, - "packages/aft-ui-mobile-apps/node_modules/@cspotcode/source-map-support": { - "version": "0.7.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@cspotcode/source-map-consumer": "0.8.0" - }, - "engines": { - "node": ">=12" - } - }, - "packages/aft-ui-mobile-apps/node_modules/@types/node": { + "packages/aft-ui-webdriverio/node_modules/@types/node": { "version": "15.14.9", - "dev": true, - "license": "MIT" - }, - "packages/aft-ui-mobile-apps/node_modules/jasmine-ts": { - "version": "0.4.0", - "dev": true, - "license": "MIT", - "dependencies": { - "yargs": "^17.0.1" - }, - "bin": { - "jasmine-ts": "lib/index.js" - }, - "peerDependencies": { - "jasmine": ">=3.4", - "ts-node": ">=3.2.0 <=11", - "typescript": ">=3.5.2" - } + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.14.9.tgz", + "integrity": "sha512-qjd88DrCxupx/kJD5yQgZdcYKZKSIGBVDIBE1/LTGcNm3d2Np/jxojkdePDdfnBHJc5W7vSMpbJ1aB7p/Py69A==", + "dev": true }, - "packages/aft-ui-mobile-apps/node_modules/ts-node": { - "version": "10.7.0", + "packages/aft-ui-webdriverio/node_modules/ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", "dev": true, - "license": "MIT", "dependencies": { - "@cspotcode/source-map-support": "0.7.0", + "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", "@tsconfig/node12": "^1.0.7", "@tsconfig/node14": "^1.0.0", @@ -11085,7 +11174,7 @@ "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.0", + "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" }, "bin": { @@ -11101,39 +11190,14 @@ "@swc/wasm": ">=1.2.50", "@types/node": "*", "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, - "packages/aft-ui-mobile-apps/node_modules/yargs": { - "version": "17.4.1", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "packages/aft-ui-mobile-apps/node_modules/yargs-parser": { - "version": "21.0.1", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } } }, "packages/aft-ui/node_modules/@cspotcode/source-map-support": { @@ -11152,22 +11216,6 @@ "dev": true, "license": "MIT" }, - "packages/aft-ui/node_modules/jasmine-ts": { - "version": "0.4.0", - "dev": true, - "license": "MIT", - "dependencies": { - "yargs": "^17.0.1" - }, - "bin": { - "jasmine-ts": "lib/index.js" - }, - "peerDependencies": { - "jasmine": ">=3.4", - "ts-node": ">=3.2.0 <=11", - "typescript": ">=3.5.2" - } - }, "packages/aft-ui/node_modules/ts-node": { "version": "10.7.0", "dev": true, @@ -11210,36 +11258,11 @@ } } }, - "packages/aft-ui/node_modules/yargs": { - "version": "17.4.1", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "packages/aft-ui/node_modules/yargs-parser": { - "version": "21.0.1", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, "packages/aft-web-services": { - "version": "9.0.0", + "version": "10.0.0", "license": "MIT", "dependencies": { - "aft-core": "^9.0.0", + "aft-core": "^10.0.0", "form-data": "^4.0.0", "xmldom": "^0.6.0" }, @@ -11271,22 +11294,6 @@ "dev": true, "license": "MIT" }, - "packages/aft-web-services/node_modules/jasmine-ts": { - "version": "0.4.0", - "dev": true, - "license": "MIT", - "dependencies": { - "yargs": "^17.0.1" - }, - "bin": { - "jasmine-ts": "lib/index.js" - }, - "peerDependencies": { - "jasmine": ">=3.4", - "ts-node": ">=3.2.0 <=11", - "typescript": ">=3.5.2" - } - }, "packages/aft-web-services/node_modules/ts-node": { "version": "10.7.0", "dev": true, @@ -11328,31 +11335,6 @@ "optional": true } } - }, - "packages/aft-web-services/node_modules/yargs": { - "version": "17.4.1", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "packages/aft-web-services/node_modules/yargs-parser": { - "version": "21.0.1", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } } }, "dependencies": { @@ -13014,6 +12996,12 @@ "@types/node": "*" } }, + "@types/lodash": { + "version": "4.14.194", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.194.tgz", + "integrity": "sha512-r22s9tAS7imvBt2lyHC9B8AGwWnXaYb1tY09oyLkXDs4vArpYJzw09nj8MLx5VfciBPGIb+ZwG0ssYnEPJxn/g==", + "dev": true + }, "@types/minimatch": { "version": "3.0.5", "dev": true @@ -13204,12 +13192,14 @@ "@types/node": "^17.0.31", "@types/uuid": "^8.3.0", "colors": "^1.4.0", + "dotenv": "^16.0.3", "fs-ext": "^2.0.0", - "jasmine": "^3.7.0", + "jasmine": "^4.6.0", "jasmine-ts": "^0.4.0", "lodash": "^4.17.21", "nyc": "^15.1.0", "rimraf": "^3.0.2", + "source-map-support": "^0.5.21", "ts-node": "^10.7.0", "typescript": "^4.6.4", "uuid": "^8.3.2" @@ -13222,13 +13212,27 @@ "@cspotcode/source-map-consumer": "0.8.0" } }, - "jasmine-ts": { - "version": "0.4.0", + "dotenv": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", + "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==" + }, + "jasmine": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-4.6.0.tgz", + "integrity": "sha512-iq7HQ5M8ydNUspjd9vbFW9Lu+6lQ1QLDIqjl0WysEllF5EJZy8XaUyNlhCJVwOx2YFzqTtARWbS56F/f0PzRFw==", "dev": true, "requires": { - "yargs": "^17.0.1" + "glob": "^7.1.6", + "jasmine-core": "^4.6.0" } }, + "jasmine-core": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-4.6.0.tgz", + "integrity": "sha512-O236+gd0ZXS8YAjFx8xKaJ94/erqUliEkJTDedyE7iHvv4ZVqi+q+8acJxu05/WJDKm512EUNn809In37nWlAQ==", + "dev": true + }, "ts-node": { "version": "10.7.0", "dev": true, @@ -13247,23 +13251,6 @@ "v8-compile-cache-lib": "^3.0.0", "yn": "3.1.1" } - }, - "yargs": { - "version": "17.4.1", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" - } - }, - "yargs-parser": { - "version": "21.0.1", - "dev": true } } }, @@ -13274,13 +13261,14 @@ "@types/mocha": "^8.2.2", "@types/node": "^15.0.1", "@types/selenium-webdriver": "^4.0.12", - "aft-logging-awskinesis": "^9.0.0", - "aft-logging-filesystem": "^9.0.0", - "aft-logging-html": "^9.0.0", - "aft-mocha-reporter": "^9.0.0", - "aft-testrail": "^9.0.0", - "aft-ui-browsers": "^9.0.0", - "aft-ui-mobile-apps": "^9.0.0", + "aft-mocha-reporter": "^10.0.0", + "aft-reporting-aws-kinesis-firehose": "^10.0.0", + "aft-reporting-filesystem": "^10.0.0", + "aft-reporting-html": "^10.0.0", + "aft-testrail": "^10.0.0", + "aft-ui-selenium": "^10.0.0", + "aft-ui-webdriverio": "^10.0.0", + "aft-web-services": "^10.0.0", "chai": "^4.3.4", "mocha": "^10.0.0", "nyc": "^15.1.0", @@ -13300,9 +13288,9 @@ "requires": { "@types/jasmine": "^4.0.3", "@types/node": "^18.0.1", - "aft-core": "^9.0.0", - "aft-logging-filesystem": "^9.0.0", - "aft-logging-html": "^9.0.0", + "aft-core": "^10.0.0", + "aft-reporting-filesystem": "^10.0.0", + "aft-reporting-html": "^10.0.0", "jasmine": "^4.2.1", "nyc": "^15.1.0", "rimraf": "^3.0.2", @@ -13349,108 +13337,32 @@ } } }, - "aft-logging-awskinesis": { - "version": "file:packages/aft-logging-awskinesis", - "requires": { - "@aws-sdk/types": "^3.78.0", - "@types/jasmine": "^3.6.10", - "@types/node": "^15.0.1", - "aft-core": "^9.0.0", - "aws-sdk": "^2.1151.0", - "jasmine": "^3.7.0", - "jasmine-ts": "^0.4.0", - "nyc": "^15.1.0", - "rimraf": "^3.0.2", - "ts-node": "^10.7.0", - "typescript": "^4.3.2" - }, - "dependencies": { - "@cspotcode/source-map-support": { - "version": "0.7.0", - "dev": true, - "requires": { - "@cspotcode/source-map-consumer": "0.8.0" - } - }, - "@types/node": { - "version": "15.14.9", - "dev": true - }, - "jasmine-ts": { - "version": "0.4.0", - "dev": true, - "requires": { - "yargs": "^17.0.1" - } - }, - "ts-node": { - "version": "10.7.0", - "dev": true, - "requires": { - "@cspotcode/source-map-support": "0.7.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.0", - "yn": "3.1.1" - } - }, - "yargs": { - "version": "17.4.1", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" - } - }, - "yargs-parser": { - "version": "21.0.1", - "dev": true - } - } - }, - "aft-logging-filesystem": { - "version": "file:packages/aft-logging-filesystem", + "aft-mocha-reporter": { + "version": "file:packages/aft-mocha-reporter", "requires": { - "@types/jasmine": "^4.0.3", + "@types/mocha": "^9.1.1", "@types/node": "^18.0.0", - "aft-core": "^9.0.0", - "date-and-time": "^2.4.0", - "jasmine": "^3.7.0", - "jasmine-ts": "^0.4.0", + "@types/sinon": "^10.0.12", + "aft-core": "^10.0.0", + "aft-reporting-filesystem": "^10.0.0", + "aft-reporting-html": "^10.0.0", + "chai": "^4.3.6", + "mocha": "^10.0.0", "nyc": "^15.1.0", "rimraf": "^3.0.2", + "sinon": "^14.0.0", "ts-node": "^10.8.1", "typescript": "^4.7.4" }, "dependencies": { - "@types/jasmine": { - "version": "4.0.3", + "@types/mocha": { + "version": "9.1.1", "dev": true }, "@types/node": { "version": "18.0.0", "dev": true }, - "jasmine-ts": { - "version": "0.4.0", - "dev": true, - "requires": { - "yargs": "^17.0.1" - } - }, "ts-node": { "version": "10.8.1", "dev": true, @@ -13469,32 +13381,17 @@ "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" } - }, - "yargs": { - "version": "17.4.1", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" - } - }, - "yargs-parser": { - "version": "21.0.1", - "dev": true } } }, - "aft-logging-html": { - "version": "file:packages/aft-logging-html", + "aft-reporting-aws-kinesis-firehose": { + "version": "file:packages/aft-reporting-aws-kinesis-firehose", "requires": { + "@aws-sdk/types": "^3.78.0", "@types/jasmine": "^3.6.10", "@types/node": "^15.0.1", - "aft-core": "^9.0.0", + "aft-core": "^10.0.0", + "aws-sdk": "^2.1151.0", "jasmine": "^3.7.0", "jasmine-ts": "^0.4.0", "nyc": "^15.1.0", @@ -13503,29 +13400,19 @@ "typescript": "^4.3.2" }, "dependencies": { - "@cspotcode/source-map-support": { - "version": "0.7.0", - "dev": true, - "requires": { - "@cspotcode/source-map-consumer": "0.8.0" - } - }, "@types/node": { "version": "15.14.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.14.9.tgz", + "integrity": "sha512-qjd88DrCxupx/kJD5yQgZdcYKZKSIGBVDIBE1/LTGcNm3d2Np/jxojkdePDdfnBHJc5W7vSMpbJ1aB7p/Py69A==", "dev": true }, - "jasmine-ts": { - "version": "0.4.0", - "dev": true, - "requires": { - "yargs": "^17.0.1" - } - }, "ts-node": { - "version": "10.7.0", + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", "dev": true, "requires": { - "@cspotcode/source-map-support": "0.7.0", + "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", "@tsconfig/node12": "^1.0.7", "@tsconfig/node14": "^1.0.0", @@ -13536,49 +13423,29 @@ "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.0", + "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" } - }, - "yargs": { - "version": "17.4.1", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" - } - }, - "yargs-parser": { - "version": "21.0.1", - "dev": true } } }, - "aft-mocha-reporter": { - "version": "file:packages/aft-mocha-reporter", + "aft-reporting-filesystem": { + "version": "file:packages/aft-reporting-filesystem", "requires": { - "@types/mocha": "^9.1.1", - "@types/node": "^18.0.0", - "@types/sinon": "^10.0.12", - "aft-core": "^9.0.0", - "aft-logging-filesystem": "^9.0.0", - "aft-logging-html": "^9.0.0", - "chai": "^4.3.6", - "mocha": "^10.0.0", + "@types/jasmine": "^4.0.3", + "@types/node": "^18.0.0", + "aft-core": "^10.0.0", + "date-and-time": "^2.4.0", + "jasmine": "^3.7.0", + "jasmine-ts": "^0.4.0", "nyc": "^15.1.0", "rimraf": "^3.0.2", - "sinon": "^14.0.0", "ts-node": "^10.8.1", "typescript": "^4.7.4" }, "dependencies": { - "@types/mocha": { - "version": "9.1.1", + "@types/jasmine": { + "version": "4.0.3", "dev": true }, "@types/node": { @@ -13606,12 +13473,12 @@ } } }, - "aft-testrail": { - "version": "file:packages/aft-testrail", + "aft-reporting-html": { + "version": "file:packages/aft-reporting-html", "requires": { "@types/jasmine": "^3.6.10", "@types/node": "^15.0.1", - "aft-web-services": "^9.0.0", + "aft-core": "^10.0.0", "jasmine": "^3.7.0", "jasmine-ts": "^0.4.0", "nyc": "^15.1.0", @@ -13631,13 +13498,6 @@ "version": "15.14.9", "dev": true }, - "jasmine-ts": { - "version": "0.4.0", - "dev": true, - "requires": { - "yargs": "^17.0.1" - } - }, "ts-node": { "version": "10.7.0", "dev": true, @@ -13656,32 +13516,15 @@ "v8-compile-cache-lib": "^3.0.0", "yn": "3.1.1" } - }, - "yargs": { - "version": "17.4.1", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" - } - }, - "yargs-parser": { - "version": "21.0.1", - "dev": true } } }, - "aft-ui": { - "version": "file:packages/aft-ui", + "aft-testrail": { + "version": "file:packages/aft-testrail", "requires": { "@types/jasmine": "^3.6.10", "@types/node": "^15.0.1", - "aft-core": "^9.0.0", + "aft-web-services": "^10.0.0", "jasmine": "^3.7.0", "jasmine-ts": "^0.4.0", "nyc": "^15.1.0", @@ -13701,13 +13544,6 @@ "version": "15.14.9", "dev": true }, - "jasmine-ts": { - "version": "0.4.0", - "dev": true, - "requires": { - "yargs": "^17.0.1" - } - }, "ts-node": { "version": "10.7.0", "dev": true, @@ -13726,38 +13562,19 @@ "v8-compile-cache-lib": "^3.0.0", "yn": "3.1.1" } - }, - "yargs": { - "version": "17.4.1", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" - } - }, - "yargs-parser": { - "version": "21.0.1", - "dev": true } } }, - "aft-ui-browsers": { - "version": "file:packages/aft-ui-browsers", + "aft-ui": { + "version": "file:packages/aft-ui", "requires": { "@types/jasmine": "^3.6.10", "@types/node": "^15.0.1", - "@types/selenium-webdriver": "^4.0.12", - "aft-ui": "^9.0.0", + "aft-core": "^10.0.0", "jasmine": "^3.7.0", "jasmine-ts": "^0.4.0", "nyc": "^15.1.0", "rimraf": "^3.0.2", - "selenium-webdriver": "^4.3.0", "ts-node": "^10.7.0", "typescript": "^4.3.2" }, @@ -13773,13 +13590,6 @@ "version": "15.14.9", "dev": true }, - "jasmine-ts": { - "version": "0.4.0", - "dev": true, - "requires": { - "yargs": "^17.0.1" - } - }, "ts-node": { "version": "10.7.0", "dev": true, @@ -13798,33 +13608,61 @@ "v8-compile-cache-lib": "^3.0.0", "yn": "3.1.1" } + } + } + }, + "aft-ui-selenium": { + "version": "file:packages/aft-ui-selenium", + "requires": { + "@types/jasmine": "^3.6.10", + "@types/lodash": "^4.14.194", + "@types/node": "^15.0.1", + "@types/selenium-webdriver": "^4.0.12", + "aft-ui": "^10.0.0", + "jasmine": "^3.7.0", + "jasmine-ts": "^0.4.0", + "nyc": "^15.1.0", + "rimraf": "^3.0.2", + "selenium-webdriver": "^4.3.0", + "ts-node": "^10.7.0", + "typescript": "^4.3.2" + }, + "dependencies": { + "@types/node": { + "version": "15.14.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.14.9.tgz", + "integrity": "sha512-qjd88DrCxupx/kJD5yQgZdcYKZKSIGBVDIBE1/LTGcNm3d2Np/jxojkdePDdfnBHJc5W7vSMpbJ1aB7p/Py69A==", + "dev": true }, - "yargs": { - "version": "17.4.1", + "ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", "dev": true, "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" } - }, - "yargs-parser": { - "version": "21.0.1", - "dev": true } } }, - "aft-ui-mobile-apps": { - "version": "file:packages/aft-ui-mobile-apps", + "aft-ui-webdriverio": { + "version": "file:packages/aft-ui-webdriverio", "requires": { "@types/jasmine": "^3.6.10", "@types/node": "^15.0.1", - "aft-ui": "^9.0.0", - "aft-web-services": "^9.0.0", + "aft-ui": "^10.0.0", "jasmine": "^3.7.0", "jasmine-ts": "^0.4.0", "nyc": "^15.1.0", @@ -13834,29 +13672,19 @@ "webdriverio": "^7.5.7" }, "dependencies": { - "@cspotcode/source-map-support": { - "version": "0.7.0", - "dev": true, - "requires": { - "@cspotcode/source-map-consumer": "0.8.0" - } - }, "@types/node": { "version": "15.14.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.14.9.tgz", + "integrity": "sha512-qjd88DrCxupx/kJD5yQgZdcYKZKSIGBVDIBE1/LTGcNm3d2Np/jxojkdePDdfnBHJc5W7vSMpbJ1aB7p/Py69A==", "dev": true }, - "jasmine-ts": { - "version": "0.4.0", - "dev": true, - "requires": { - "yargs": "^17.0.1" - } - }, "ts-node": { - "version": "10.7.0", + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", "dev": true, "requires": { - "@cspotcode/source-map-support": "0.7.0", + "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", "@tsconfig/node12": "^1.0.7", "@tsconfig/node14": "^1.0.0", @@ -13867,26 +13695,9 @@ "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.0", + "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" } - }, - "yargs": { - "version": "17.4.1", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" - } - }, - "yargs-parser": { - "version": "21.0.1", - "dev": true } } }, @@ -13896,7 +13707,7 @@ "@types/jasmine": "^3.6.10", "@types/node": "^15.0.1", "@types/xmldom": "^0.1.30", - "aft-core": "^9.0.0", + "aft-core": "^10.0.0", "form-data": "^4.0.0", "jasmine": "^3.7.0", "jasmine-ts": "^0.4.0", @@ -13918,13 +13729,6 @@ "version": "15.14.9", "dev": true }, - "jasmine-ts": { - "version": "0.4.0", - "dev": true, - "requires": { - "yargs": "^17.0.1" - } - }, "ts-node": { "version": "10.7.0", "dev": true, @@ -13943,23 +13747,6 @@ "v8-compile-cache-lib": "^3.0.0", "yn": "3.1.1" } - }, - "yargs": { - "version": "17.4.1", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" - } - }, - "yargs-parser": { - "version": "21.0.1", - "dev": true } } }, @@ -14151,8 +13938,15 @@ "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", "dev": true }, + "available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==" + }, "aws-sdk": { - "version": "2.1151.0", + "version": "2.1373.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1373.0.tgz", + "integrity": "sha512-3/P79VU2VVeiof25bn8TSepEhWCRhwuQGYoEWX/2pApQRJAY+w/3JFVKHjbAe3NYEEBNeiAE6PQ9DqWz5Pp+Lw==", "requires": { "buffer": "4.9.2", "events": "1.1.1", @@ -14161,8 +13955,9 @@ "querystring": "0.2.0", "sax": "1.2.1", "url": "0.10.3", + "util": "^0.12.4", "uuid": "8.0.0", - "xml2js": "0.4.19" + "xml2js": "0.5.0" }, "dependencies": { "buffer": { @@ -14393,6 +14188,15 @@ "write-file-atomic": "^3.0.0" } }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -15307,6 +15111,14 @@ "flat": { "version": "5.0.2" }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "requires": { + "is-callable": "^1.1.3" + } + }, "foreground-child": { "version": "2.0.0", "dev": true, @@ -15369,8 +15181,7 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "gauge": { "version": "4.0.4", @@ -15399,6 +15210,16 @@ "version": "2.0.0", "dev": true }, + "get-intrinsic": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", + "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + } + }, "get-package-type": { "version": "0.1.0", "dev": true @@ -15583,6 +15404,14 @@ "slash": "^3.0.0" } }, + "gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "requires": { + "get-intrinsic": "^1.1.3" + } + }, "got": { "version": "11.8.5", "resolved": "https://registry.npmjs.org/got/-/got-11.8.5.tgz", @@ -15630,7 +15459,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -15638,6 +15466,19 @@ "has-flag": { "version": "4.0.0" }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "requires": { + "has-symbols": "^1.0.2" + } + }, "has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", @@ -15686,7 +15527,9 @@ "dev": true }, "http-cache-semantics": { - "version": "4.1.0" + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" }, "http-proxy-agent": { "version": "5.0.0", @@ -15779,7 +15622,9 @@ } }, "immediate": { - "version": "3.0.6" + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==" }, "import-fresh": { "version": "3.3.0", @@ -15904,6 +15749,15 @@ "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", "dev": true }, + "is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -15918,6 +15772,11 @@ "binary-extensions": "^2.0.0" } }, + "is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==" + }, "is-ci": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", @@ -15947,6 +15806,14 @@ "is-fullwidth-code-point": { "version": "3.0.0" }, + "is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, "is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -16007,6 +15874,18 @@ "text-extensions": "^1.0.0" } }, + "is-typed-array": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", + "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + } + }, "is-typedarray": { "version": "1.0.0", "dev": true @@ -16136,6 +16015,49 @@ "version": "3.99.1", "dev": true }, + "jasmine-ts": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/jasmine-ts/-/jasmine-ts-0.4.0.tgz", + "integrity": "sha512-bIAWJKUwxfuZfGI1ctEbny7+dsyFzsN0eLzOokxh0qIUCofai2WUEKoe3MMllkGEBXJzbEVYr2IyhJBv4j7SBA==", + "dev": true, + "requires": { + "yargs": "^17.0.1" + }, + "dependencies": { + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, + "yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true + } + } + }, "jmespath": { "version": "0.16.0" }, @@ -16192,7 +16114,9 @@ "dev": true }, "json5": { - "version": "2.2.1", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true }, "jsonc-parser": { @@ -16225,7 +16149,9 @@ } }, "jszip": { - "version": "3.10.0", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", "requires": { "lie": "~3.3.0", "pako": "~1.0.2", @@ -16234,7 +16160,9 @@ }, "dependencies": { "readable-stream": { - "version": "2.3.7", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -16246,10 +16174,14 @@ } }, "safe-buffer": { - "version": "5.1.2" + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "string_decoder": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { "safe-buffer": "~5.1.0" } @@ -16430,6 +16362,8 @@ }, "lie": { "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", "requires": { "immediate": "~3.0.5" } @@ -17794,7 +17728,9 @@ } }, "pako": { - "version": "1.0.11" + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" }, "parent-module": { "version": "1.0.1", @@ -18447,11 +18383,13 @@ "version": "1.2.1" }, "selenium-webdriver": { - "version": "4.3.0", + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-4.9.2.tgz", + "integrity": "sha512-0gDswAgVn6qbCYckZetQQvQK9tWW1r7LaumhiqY1/Wl/7JEWG0JANsTbZKnmGc3+cUU76zAi5/p0P8LUweXlig==", "requires": { - "jszip": "^3.10.0", + "jszip": "^3.10.1", "tmp": "^0.2.1", - "ws": ">=8.7.0" + "ws": ">=8.13.0" }, "dependencies": { "tmp": { @@ -18506,7 +18444,9 @@ "dev": true }, "setimmediate": { - "version": "1.0.5" + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" }, "shallow-clone": { "version": "3.0.1", @@ -18616,6 +18556,8 @@ }, "source-map-support": { "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, "requires": { "buffer-from": "^1.0.0", @@ -18916,7 +18858,9 @@ }, "dependencies": { "json5": { - "version": "1.0.1", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, "requires": { "minimist": "^1.2.0" @@ -18991,7 +18935,9 @@ "version": "4.7.4" }, "ua-parser-js": { - "version": "1.0.2" + "version": "1.0.35", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.35.tgz", + "integrity": "sha512-fKnGuqmTBnIE+/KXSzCn4db8RTigUzw1AN0DmdU6hJovUTbYJKyqj+8Mt1c4VfRDnOVJnENmfYkIPZ946UrSAA==" }, "uglify-js": { "version": "3.17.1", @@ -19052,6 +18998,18 @@ } } }, + "util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "requires": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, "util-deprecate": { "version": "1.0.2" }, @@ -19190,6 +19148,19 @@ "version": "2.0.0", "dev": true }, + "which-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", + "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.10" + } + }, "wide-align": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", @@ -19333,23 +19304,24 @@ } }, "ws": { - "version": "8.8.0", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", "requires": {} }, "xml2js": { - "version": "0.4.19", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", + "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", "requires": { "sax": ">=0.6.0", - "xmlbuilder": "~9.0.1" - }, - "dependencies": { - "sax": { - "version": "1.2.4" - } + "xmlbuilder": "~11.0.0" } }, "xmlbuilder": { - "version": "9.0.7" + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" }, "xmldom": { "version": "0.6.0" diff --git a/package.json b/package.json index 5b28893c..5433688d 100644 --- a/package.json +++ b/package.json @@ -5,21 +5,23 @@ ], "scripts": { "clean": "npm run clean --workspaces", - "build": "npm run clean && npm run build --workspaces --if-present && npm run build-e2e -w aft-examples", + "build": "npm run clean && npm run build --workspaces --if-present", "test": "npm run test --workspaces --if-present", "coverage": "npm run coverage --workspaces --if-present", - "test-core": "npm run test --workspace=aft-core", - "test-awskinesis": "npm run test --workspace=aft-logging-awskinesis", - "test-testrail": "npm run test --workspace=aft-testrail", - "test-ui": "npm run test --workspace=aft-ui", - "test-browsers": "npm run test --workspace=aft-ui-browsers", - "test-mobile-apps": "npm run test --workspace=aft-ui-mobile-apps", - "test-web-services": "npm run test --workspace=aft-web-services", - "test-html": "npm run test --workspace=aft-logging-html", - "test-examples": "npm run test-e2e --workspace=aft-examples", - "test-filesystem": "npm run test --workspace=aft-logging-filesystem", - "test-mocha": "npm run test --workspace=aft-mocha-reporter", - "test-jasmine": "npm run test --workspace=aft-jasmine-reporter" + "test:core": "npm run test --workspace=aft-core", + "test:kinesis": "npm run test --workspace=aft-reporting-aws-kinesis-firehose", + "test:testrail": "npm run test --workspace=aft-testrail", + "test:ui": "npm run test --workspace=aft-ui", + "test:selenium": "npm run test --workspace=aft-ui-selenium", + "test:webdriverio": "npm run test --workspace=aft-ui-webdriverio", + "test:web-services": "npm run test --workspace=aft-web-services", + "test:html": "npm run test --workspace=aft-reporting-html", + "test:examples": "npm run test:e2e --workspace=aft-examples", + "test-examples": "npm run test:examples", + "test:filesystem": "npm run test --workspace=aft-reporting-filesystem", + "test:mocha": "npm run test --workspace=aft-mocha-reporter", + "test:jasmine": "npm run test --workspace=aft-jasmine-reporter", + "docs": "npm run build && npx typedoc --entryPointStrategy packages ./packages/* --out ./docs" }, "devDependencies": { "dpdm": "^3.9.0", diff --git a/packages/aft-core/README.md b/packages/aft-core/README.md index 39e14e11..7d20c31d 100644 --- a/packages/aft-core/README.md +++ b/packages/aft-core/README.md @@ -5,40 +5,52 @@ the base Automated Functional Testing (AFT) library providing support for Plugin `> npm i aft-core` ## Configuration -the `aft-core` package contains the `cfgmgr` constant class for reading in configuration from multiple different sources all chained in the following order by default, but updatable using `cfgmgr.set((configKey: string, options: object) => new ChainedProvider([new ProviderOne(), new ProviderTwo(), ...]))`: -- **OptionsProvider** - reads from the passed in `options` object passed to `cfgmgr.get(configKey, options)` -- **EnvVarProvider** - reads from the `process.env` prepending all environment variable keys with the supplied `configKey` -- **AftConfigProvider** - reads from the `aftconfig.json` file starting from a property named with the supplied `configKey` +the `aft-core` package contains the `aftConfig` constant class (instance of `new AftConfig()`) for reading in configuration an `aftconfig.json` file at the project root. this configuration can be read as a top-level field using `aftConfig.get('field_name')` or `aftConfig.get('field_name', defaultVal)` and can also be set without actually modifying the values in your `aftconfig.json` using `aftConfig.set('field_name', val)`. additionally, configuration classes can be read using `AftConfig` with the `aftConfig.getSection(ConfigClass)` which will read from your `aftconfig.json` file for a field named `ConfigClass` Ex: with an `aftconfig.json` containing: ```json { - "ConfigSectionName": { - "config_field3": "%your_env_var%", - "config_field4": "some-value", - "config_field5": "['foo', true, 10]" + "SomeCustomClassConfig": { + "configField1": "%your_env_var%", + "configField2": "some-value", + "configField3": ["foo", true, 10] } } ``` and with the following environment variables set: > export your_env_var="an important value" -can be accessed using the `cfgmgr` as follows: +and a config class of: ```typescript -const config = cfgmgr.get('ConfigSectionName', { - config_field1: 12345, - config_field2: true, - config_field4: 'a value here' -}); -await config.get('config_field1', -1); // returns 12345 -await config.get('config_field2', true); // returns false -await config.get('config_field3'); // returns "an important value" -await config.get('config_field4', 'no value'); // returns "a value here" (passed in options override aftconfig.json values) -await config.get('config_field5'); // returns ["foo", true, 10] as an array +export class SomeCustomClassConfig { + configField1: string = 'default_value_here'; + configField2: string = 'another_default_value'; + configField3: Array = ['default_val']; + configField4: string = 'last_default_value'; +} ``` -for classes that rely on dependency injected options, there is also the `optmgr` constant class that will extract environment variables and JSON objects from a object passed to the `optmgr.process()` function. this is useful when combined with the `IHasOptions` interface resulting in easier scoping of lookups on the passed in `options` object. -> NOTE: the `optmgr.process` function is used in the `OptionsProvider` and `AftConfigProvider` classes before returning the values for a given key +can be accessed using an `AftConfig` instance as follows: +```typescript +const config = aftConfig.getSection(SomeCustomClassConfig); // or new AftConfig().getSection(SomeCustomClassConfig); +config.configField1; // returns "an important value" +config.configField2; // returns "some-value" +config.configField3; // returns ["foo", true, 10] as an array +config.configField4; // returns "last_default_value" +``` + +and if you wish to entirely disregard the configuration specified in your `aftconfig.json` file you can use the following (still based on the above example): +```typescript +const config = new AftConfig({ + SomeCustomClassConfig: { + configField1: 'custom_value_here' + } +}); +config.configField1; // returns "custom_value_here" +config.configField2; // returns "another_default_value" +config.configField3; // returns ["default_val"] as an array +config.configField4; // returns "last_default_value" +``` ## Helpers the `aft-core` package contains several helper and utility classes, interfaces and functions to make functional testing and test development easier. These include: @@ -46,15 +58,13 @@ the `aft-core` package contains several helper and utility classes, interfaces a - **convert** - string manipulation like Base64 encode / decode and replacement - **ellide** - string elliding supporting beginning, middle and end ellipsis - **Err** - a `module` that can run functions in a `try-catch` with optional logging as well as provide formatted string outputs from `Error` objects -- **wait** - continually retry some action until success or a maximum time elapses -- **using** - automatically call the `dispose` function of a class that implements the `IDisposable` interface when done -- **verify** - a function accepting an `assertion` function that simplifies usage of a `Verifier` within your _Jasmine_ or _Mocha_ tests +- **using** - automatically call the `dispose` function of a class that implements the `Disposable` interface when done - **MachineInfo** - get details of the host machine and user running the tests - **CacheMap** - a `Map` implementation that stores values with expirations where expired items will not be returned and are pruned from the `Map` automatically. The `CacheMap` can also optionally store its data on the filesystem allowing for other running node processes to read from the same cache data (e.g. sharded parallel testing) - **FileSystemMap** - a `Map` implementation that stores its values in a file on the filesystem allowing multiple node processes to share the map data or to persist the data over multiple iterations -- **fileio** - a constant class providing file system `write`, `readAs` and `getExpiringFileLock` functions to simplify file operations +- **fileio** - a constant class providing file system `write` and `readAs` functions to simplify file operations - **wait** - constant class providing `wait.forResult(...): Promise`, `wait.forDuration(number)`, and `wait.until(number | Date): Promise` functions to allow for non-thread-locking waits -- **retry** - constant class providing `retry(retryable): Promise` async function +- **retry** - constant class providing `retry(retryable): Promise` async function that will retry a given `retryable` function until it succeeds or some condition such as number of attempts or elapsed time is exceeded - **verifier** - see: [Testing with the Verifier](#testing-with-the-verifier) section below ## Custom Types @@ -70,106 +80,95 @@ the `aft-core` package contains several helper and utility classes, interfaces a ## Plugins -### Example Logging Plugin -to create your own simple logging plugin that stores all logs until the `dispose` function is called you would implement the code below. +### Example Reporting Plugin +to create your own simple reporting plugin that stores all logs until the `finalise` function is called you would implement the code below. -> NOTE: configuration for the below can be added in a object in the `aftconfig.json` named `ondisposeconsolelogger` based on the `key` passed to the `LoggingPlugin` constructor +> NOTE: configuration for the below can be added in a object in the `aftconfig.json` named `OnDisposeConsoleReportingPluginConfig` and optionally containing values for the supported properties of the `OnDisposeConsoleReportingPluginConfig` class ```typescript -export type OnDisposeConsoleLoggerOptions = Merge; -export class OnDisposeConsoleLogger extends LoggingPlugin { - private _logs: Array; - private _maxLines: number; - constructor(options?: OnDisposeConsoleLoggerOptions) { - super(options); - this._logs = new Array(); +export class OnDisposeConsoleReportingPluginConfig { + maxLogLines: number = Infinity; + logLevel: LogLevel = 'warn'; +}; +export class OnDisposeConsoleReportingPlugin extends ReportingPlugin { + public override get logLevel(): LogLevel { return this._lvl; } + private readonly _lvl: LogLevel; + private readonly _logs: Map>; + private readonly _maxLines: number; + constructor(aftCfg?: AftConfig) { + super(aftCfg); + const cfg = this.aftCfg.getSection(OnDisposeConsoleReportingPluginConfig); + this._lvl = cfg.logLevel ?? 'warn'; + if (this.enabled) { + this._logs = new Map>(); + } } - get maxLogLines(): number { - if (!this._maxLines) { - this._maxLines = this.option('maxLogLines', 100); + override initialise = async (name: string): Promise => { + if (!this._logs.has(name)) { + this._logs.set(name, new Array()); } - return this._maxLines; } - async log(data: LogMessageData): Promise { - let l: LoggingLevel = this.level; - if (LogLevel.toValue(data.level) >= LogLevel.toValue(l) && level != 'none') { - this._logs.push(data); - while (this._logs.length > this.maxLogLines) { - this._logs.shift(); + override log = async (name: string, level: LogLevel, message: string, ...data: Array): Promise => { + if (this.enabled) { + if (LogLevel.toValue(level) >= LogLevel.toValue(this.logLevel) && level != 'none') { + const namedLogs: Array = this._logs.get(name); + namedLogs.push({name, level, message, args: data}); + while (namedLogs.length > this.maxLogLines) { + namedLogs.shift(); + } } } } - async logResult(name: string, result: ITestResult): Promise { - if (result.status == 'Passed') { - this.log(LoggingLevel.pass, JSON.stringify(result)); - } else { - this.log(LogginLevel.fail, JSON.stringify(result)); - } + override submitResult = async (name: string, result: TestResult): Promise => { + /* ignore */ } - async dispose(name: string, error?: Error): Promise { - this._logs.forEach((message) => { - LogManager.toConsole(message); - }); - if (error) { - LogManager.toConsole({name: this.logName, level: 'error', message: Err.full(error.message)}); + override finalise = async (name: string): Promise => { + if (this.enabled) { + const namedLogs = this._logs.get(name); + while (namedLogs?.length > 0) { + let data = namedLogs.shift(); + aftLogger.log({name: data.name, level: data.level, message: data.message, args: data.args}); + }); + aftLogger.log({name: this.constructor.name, level: 'debug', message: `finalised '${name}'`}); } - LogManager.toConsole({name: this.logName, level: 'info', message: 'OnDisposeConsoleLogger is now disposed!'}); } } ``` -### Example Test Case Plugin (TestRail) +### Example TestExecutionPolicyPlugin (TestRail) ```typescript -export type TestRailTestCasePluginOptions = Merge; -export class TestRailTestCasePlugin extends TestCasePlugin { - private _client: TestRailClient; - get client(): TestRailClient { - if (!this._client) { - this._client = this.option('client') || new TestRailClient(); - } - return this._client; - } - async getTestCase(testId: string): Promise { - return await this.client.getTestCase(testId); - } - async findTestCases(searchTerm: string): Promise { - return await this.client.findTestCases(searchTerm); - } - async shouldRun(testId: string): Promise { - return await this.client.shouldRun(testId); - } - async dispose(error?: Error) { /* perform some action if needed */ } +export class TestRailConfig { + username: string; + password: string; + url: string = 'https://you.testrail.io'; + projectId: number; + suiteIds: Array = new Array(); + planId: number; + enabled: boolean = false; } -``` -### Example Defect Plugin (Bugzilla) -```typescript -export type BugzillaDefectPluginOptions = Merge; - -export class BugzillaDefectPlugin extends DefectPlugin { - private _client: BugzillaClient; - get client(): TestRailClient { - if (!this._client) { - this._client = this.option('client') || new BugzillaClient(); +export class TestRailTestExecutionPolicyPlugin extends TestExecutionPolicyPlugin { + public override get enabled(): boolean { return this._enabled; } + private readonly _client: TestRailClient; + private readonly _enabled: boolean; + constructor(aftCfg?: AftConfig) { + super(aftCfg); + const cfg = this.aftCfg.getSection(TestRailConfig); + this._enabled = cfg.enabled ?? false; + if (this.enabled) { + this._client = new TestRailClient(this.aftCfg); } - return this._client; - } - async getDefect(defectId: string): Promise { - return await this.client.getDefect(defectId); } - async findDefects(searchTerm: string): Promise { - return await this.client.findDefects(searchTerm); + override shouldRun = async (testId: string): Promise => { + const result = await this._client.getLastTestResult(testId); + if (result.status === 'Passed') { + return false; // test alraedy has passing result so don't run + } + return true; } - async dispose(error?: Error) { /* perform some action if needed */ } } ``` ## Testing with the Verifier -the `Verifier` class and `verify` functions of `aft-core` enable testing with pre-execution filtering based on integration with external test case and defect managers via plugin packages supporting each (see examples above). +the `Verifier` class and `verify` functions of `aft-core` enable testing with pre-execution filtering based on integration with external test execution policy managers via plugin packages extending the `TestExecutionPolicyPlugin` class (see examples above). ```typescript describe('Sample Test', () => { @@ -177,23 +176,22 @@ describe('Sample Test', () => { let feature: FeatureObj = new FeatureObj(); /** * the `verify(assertion).returns(expectation)` function - * checks any specified `TestCasePlugin` - * and `DefectPlugin` implementations + * checks any specified `TestExecutionPolicyPlugin` implementations * to ensure the test should be run. It will then - * report to any `LoggingPlugin` implementations + * report to any `ReportingPlugin` implementations * with an `TestResult` indicating the success, * failure or skipped status */ await verify(async () => await feature.performAction()) .withTestId('C1234') - .and.withKnownDefectId('DEFECT-123') .and.withDescription("expect that performAction will return 'result of action'") .returns('result of action'); }); }); ``` -in the above example, the `await feature.performAction()` call will only be run if a `TestCasePlugin` is loaded and returns `true` from it's `shouldRun(testId: string)` function (or no `TestCasePlugin` is loaded) and if a `DefectPlugin` is loaded and returns either no defect or a `closed` defect from it's `getDefect(defectId: string)` function (or no `DefectPlugin` is loaded). additionally, any logs associated with the above `verify` call will use a `logName` of `"expect_that_performAction_will_return_result_of_action"` resulting in log lines like the following: +> NOTE: if using the `aft-jasmine-reporter` or `aft-mocha-reporter` it is even easier to set the test IDs. see examples at [jasmine](../aft-jasmine-reporter/README.md#afttest) and [mocha](../aft-mocha-reporter/README.md#afttest) + +in the above example, the `await feature.performAction()` call will only be run if a `TestExecutionPolicyPlugin` is loaded and returns `true` from it's `shouldRun(testId: string)` function (or no `TestExecutionPolicyPlugin` is loaded). additionally, any logs associated with the above `verify` call will use a `logName` of `"expect_that_performAction_will_return_result_of_action"` resulting in log lines like the following: ``` -09:14:01 - [expect that performAction will return 'result of action'] - TRACE - no TestCasePlugin in use so run all tests -09:14:02 - [expect that performAction will return 'result of action'] - TRACE - no DefectPlugin in use so run all tests +09:14:01 - [expect that performAction will return 'result of action'] - TRACE - no TestExecutionPolicyPlugin in use so run all tests ``` \ No newline at end of file diff --git a/packages/aft-core/aftconfig.json b/packages/aft-core/aftconfig.json index dc7e2c99..2634dc8e 100644 --- a/packages/aft-core/aftconfig.json +++ b/packages/aft-core/aftconfig.json @@ -1,5 +1,5 @@ { - "LogManager": { + "Reporter": { "level": "none", "pluginNames": [] } diff --git a/packages/aft-core/jasmine.json b/packages/aft-core/jasmine.json new file mode 100644 index 00000000..ebd6e2fa --- /dev/null +++ b/packages/aft-core/jasmine.json @@ -0,0 +1,12 @@ +{ + "spec_dir": "test", + "spec_files": [ + "**/*-spec.ts" + ], + "env": { + "failSpecWithNoExpectations": false, + "stopSpecOnExpectationFailure": false, + "stopOnSpecFailure": false, + "random": true + } +} \ No newline at end of file diff --git a/packages/aft-core/package.json b/packages/aft-core/package.json index 32b7aa99..374034e0 100644 --- a/packages/aft-core/package.json +++ b/packages/aft-core/package.json @@ -1,6 +1,6 @@ { "name": "aft-core", - "version": "9.0.0", + "version": "10.0.0", "description": "Automation Framework for Testing (AFT) package supporting JavaScript unit, integration and functional testing", "repository": { "type": "git", @@ -11,8 +11,8 @@ "scripts": { "clean": "rimraf ./dist && rimraf ./.nyc_output && rimraf ./coverage", "build": "npm run clean && tsc --build", - "test": "jasmine-ts ./test/**/*-spec.ts", - "coverage": "nyc npm run test" + "test": "npm run build && npx jasmine-ts --config=./jasmine.json", + "coverage": "npm run build && nyc npx jasmine-ts --config=./jasmine.json" }, "keywords": [ "aft", @@ -30,6 +30,7 @@ "homepage": "https://github.com/bicarbon8/automated-functional-testing#readme", "dependencies": { "colors": "^1.4.0", + "dotenv": "^16.0.3", "fs-ext": "^2.0.0", "lodash": "^4.17.21", "uuid": "^8.3.2" @@ -39,10 +40,11 @@ "@types/jasmine": "^3.6.10", "@types/node": "^17.0.31", "@types/uuid": "^8.3.0", - "jasmine": "^3.7.0", + "jasmine": "^4.6.0", "jasmine-ts": "^0.4.0", "nyc": "^15.1.0", "rimraf": "^3.0.2", + "source-map-support": "^0.5.21", "ts-node": "^10.7.0", "typescript": "^4.6.4" } diff --git a/packages/aft-core/src/configuration/aft-config.ts b/packages/aft-core/src/configuration/aft-config.ts new file mode 100644 index 00000000..613df9cb --- /dev/null +++ b/packages/aft-core/src/configuration/aft-config.ts @@ -0,0 +1,259 @@ +import * as dotenv from "dotenv"; +import { Class, JsonObject, JsonValue, RetryBackOffType } from "../helpers/custom-types"; +import { fileio } from "../helpers/file-io"; +import { LogLevel } from "../logging/log-level"; + +export class AftConfig { + private readonly _cfg: JsonObject; + private readonly _valueCache: Map; + private readonly _sectionCache: Map; + + constructor(config?: JsonObject) { + this._cfg = config; + if (!this._cfg) { + try { + this._cfg = fileio.readAs('aftconfig.json'); + } catch { + this._cfg = {}; + } + } + this._valueCache = new Map(); + this._sectionCache = new Map(); + dotenv.config(); + } + + /** + * the relative path from `process.cwd()` to begin searching for plugins + * @default process.cwd() + */ + get pluginsSearchDir(): string { + return this.get('pluginsSearchDir', process.cwd()); + } + /** + * an array of plugin filenames (these must also match the lowercase plugin class name minus + * any `-`, `_` and `.` characters) to load via the `pluginLoader` + * + * ex: + * ```json + * // aftconfig.json + * { + * "pluginNames": ["my-plugin"] + * } + * ``` + * would match with the following plugin class + * ```javascript + * // my-plugin.js + * export class MyPlugin extends Plugin { + * doStuff = () => 'stuff'; + * } + * ``` + * @default [] + */ + get pluginNames(): Array { + return this.get('pluginNames', new Array()); + } + /** + * used by `Reporter` + * @default 'warn' + */ + get logLevel(): LogLevel { + return this.get('logLevel', 'warn'); + } + /** + * used by `ExpiringFileLock` to set the number of milliseconds to wait for a lock to become available + * @default 10000 + */ + get fileLockMaxWait(): number { + return this.get('fileLockMaxWait', 10000); + } + /** + * used by `ExpiringFileLock` to set the number of milliseconds to hold a lock + * @default 10000 + */ + get fileLockMaxHold(): number { + return this.get('fileLockMaxHold', 10000); + } + /** + * used by `FileSystemMap` to set the directory where the data is written to the file system + * @default 'FileSystemMap' + */ + get fsMapDirectory(): string { + return this.get('fsMapDirectory', 'FileSystemMap'); + } + /** + * used by `retry` to set the maximum number of attempts + * @default Infinity + */ + get retryMaxAttempts(): number { + return this.get('retryMaxAttempts', Infinity); + } + /** + * used by `retry` to set the retry delay back off type + * @default 'constant' + */ + get retryBackOffType(): RetryBackOffType { + return this.get('retryBackOffType', 'constant'); + } + /** + * used by `retry` to set the starting millisecond delay between each retry attempt + * @default 1 + */ + get retryDelayMs(): number { + return this.get('retryDelayMs', 1); + } + /** + * used by `retry` to set the maximum duration in milliseconds to attempt retries + * @default Infinity + */ + get retryMaxDurationMs(): number { + return this.get('retryMaxDurationMs', Infinity); + } + /** + * used by `retry` to indicate if a failure to get success should result in a `Promise.reject` + * on completion or simply returning `null` + * @default true + */ + get retryRejectOnFail(): boolean { + return this.get('retryRejectOnFail', true); + } + + /** + * looks for a value in the `aftconfig.json` file at the top level and if found attempts + * to extract any environment variable set if the value matches a format of `%some_var_name%` + * before returning the value or the specified `defaultVal` if nothing was found + * @param key the configuration key + * @param defaultVal a default value to return if no value is set for the specified `key` + * @returns the value set in the `aftconfig.json` file for the specified `key` or `undefined` + */ + get(key: string, defaultVal?: T): T { + if (this._valueCache.has(key)) { + return this._valueCache.get(key) as T; + } + let val: T = this._cfg[key] as T; + if (val === null || val === undefined) { + val = defaultVal as T; + } + if (typeof val === "string") { + val = this.processEnvVars(val) as T; + } else if (typeof val === "object") { + val = this.processProperties(val); + } + if (val != null) { + this.set(key, val); + } + return val; + } + + set(key: string, val: T): void { + if (val != null) { + this._valueCache.set(key, val); + } else { + this._valueCache.delete(key); + } + } + + /** + * looks for a top-level section in your `aftconfig.json` file with a name matching the passed in + * `className` and returns it or a new instance of the `className` type + * @param className a class of type `T` where the name of the class and the section name must match + * @returns the section from `aftconfig.json` matching the name of the passed in `className` or a + * new instance of the `className` type + */ + getSection(className: Class | string): T { + let val: T; + let key: string; + if (typeof className === "function") { + key = `${className.name}`; + } else { + key = className; + } + val = this._sectionCache.get(key) as T; + if (!val) { + val = this.get(key); + if (!val) { + if (typeof className === "function") { + val = new className(); + } else { + val = {} as T; + } + } + if (val && typeof className === "function") { + // copy props to class + const config = new className(); + for (var prop of Object.getOwnPropertyNames(val)) { + if (val[prop] != null) { + config[prop] = val[prop]; + } + } + val = config as T; + } + this.setSection(key, val); + } + return val; + } + + /** + * adds the passed in `section` to the `ConfigManager` cache of `aftconfig.json` + * sections so it will be used instead of the value from the actual JSON file + * @param key adds the passed in `section` to the cache so it will be used + * instead of reading from `aftconfig.json` + * @param section an object containing properties + */ + setSection(key: string, section: T): void { + if (section) { + this._sectionCache.set(key, section); + } else { + this._sectionCache.delete(key); + } + } + + /** + * iterates over all properties for the passed in `input` object and + * if a property is a `string` it calls `processEnvVars` on the property + * @param input an object that contains properties + * @returns the input object with any string property values updated + * based on the result of calling `processEnvVars` + */ + processProperties(input: T): T { + if (input) { + for (var prop of Object.keys(input)) { + let val = input[prop]; + if (val != null) { + if (typeof val === "string") { + val = this.processEnvVars(val); + } else if (typeof val === "object") { + val = this.processProperties(val); + } + input[prop] = val; + } + } + } + return input; + } + + /** + * attempts to get an environment variable value for a given key if the passed + * in `input` is in the format of `%some_env_var_key%` + * @param input a string that might reference an environment var between two `%` + * characters like `%some_env_var%` + * @returns the value of the environment variable + */ + processEnvVars(input: string): string { + if (input && typeof input === 'string') { + let regx = /^%(.*)%$/; + if ((input?.match(regx)?.length ?? 0) > 0) { + var envVarKey = input.match(regx)?.[1]; + if (envVarKey) { + let result = process.env[envVarKey]; + if (result) + { + input = result; + } + } + } + } + return input; + } +} + +export const aftConfig: AftConfig = new AftConfig(); \ No newline at end of file diff --git a/packages/aft-core/src/configuration/aftconfig-provider.ts b/packages/aft-core/src/configuration/aftconfig-provider.ts deleted file mode 100644 index e3a5c233..00000000 --- a/packages/aft-core/src/configuration/aftconfig-provider.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { JsonObject } from "../helpers/custom-types"; -import { fileio } from "../helpers/file-io"; -import { IConfigProvider } from "./i-config-provider"; -import { OptionsProvider } from "./options-provider"; - -export class AftConfigProvider implements IConfigProvider { - private _aftConfig: JsonObject; - private _optsProvider: OptionsProvider; - - public readonly configKey: string; - - constructor(configKey: string) { - this.configKey = configKey; - } - - /** - * parses a 'aftconfig.json' file from the local execution directory - * and returns it as a JavaScript object - */ - get aftConfig(): JsonObject { - if (!this._aftConfig) { - try { - this._aftConfig = fileio.readAs('aftconfig.json'); - } catch (e) { - this._aftConfig = {}; - } - } - return this._aftConfig; - } - - get options(): OptionsProvider { - if (!this._optsProvider) { - const conf = this.aftConfig[this.configKey] || {}; - this._optsProvider = new OptionsProvider(conf); - } - return this._optsProvider; - } - - async get(key: K, defaultVal?: V): Promise { - return this.options.get(key, defaultVal); - } -} \ No newline at end of file diff --git a/packages/aft-core/src/configuration/chained-provider.ts b/packages/aft-core/src/configuration/chained-provider.ts deleted file mode 100644 index 79bdbc45..00000000 --- a/packages/aft-core/src/configuration/chained-provider.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { IConfigProvider } from "./i-config-provider"; - -export class ChainedProvider implements IConfigProvider { - private _providers: IConfigProvider[]; - - constructor(configProviders: IConfigProvider[]) { - this._providers = configProviders || []; - } - - async get(key: K, defaultVal?: V): Promise { - let result: V; - for (var i=0; i(key).catch((err) => undefined); - if (result !== undefined) { - break; - } - } - return (result === undefined) ? defaultVal : result; - } -} \ No newline at end of file diff --git a/packages/aft-core/src/configuration/config-manager.ts b/packages/aft-core/src/configuration/config-manager.ts deleted file mode 100644 index 186e2623..00000000 --- a/packages/aft-core/src/configuration/config-manager.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { AftConfigProvider } from "./aftconfig-provider"; -import { IConfigProvider } from "./i-config-provider"; -import { ChainedProvider } from "./chained-provider"; -import { EnvVarProvider } from "./envvar-provider"; -import { OptionsProvider } from "./options-provider"; - -type ConfigKeyOptions = (configKey: string, options: T) => IConfigProvider; - -class ConfigManager { - private readonly _default: ConfigKeyOptions = (configKey: string, options: T) => new ChainedProvider([ - new OptionsProvider(options), - new EnvVarProvider(configKey), - new AftConfigProvider(configKey) - ]); - private _override: ConfigKeyOptions; - /** - * returns a new `ConfigProvider` either using the `default` of a - * `ChainedProvider` that reads from an `OptionsProvider` followed - * by and `EnvVarProvider` followed by `AftConfigProvider` or using - * the value specified using the `set` function. - * @param configKey a configuration key to use in `ConfigProvider` instances that - * require one - * @param options an `object` containing options that override any environment - * variables or `aftconfig.json` values - * @returns either the default `ConfigProvider` or the one set using the `set` - * function - */ - get(configKey: string, options: T): IConfigProvider { - return (this._override) ? this._override(configKey, options) : this._default(configKey, options); - } - /** - * this function allows for overriding the default `IConfigProvider` lookup chain - * so that any future `IConfigProvider` implementations may be added in or replace - * the existing `ChainedProvider` - * ```typescript - * ConfigManager.set((configKey: string, options: T) => CustomConfigProvider(configKey, options)); - * ``` - * @param func a `Function` accepting two arguments, a `configKey: string` and an - * `options: object` and returning a `IConfigProvider` instance - */ - set(func: ConfigKeyOptions): void { - this._override = func; - } - /** - * resets the `cfgmgr` to use the default provider chain - */ - reset(): void { - this.set(this._default); - } -} - -/** - * calling `cfgmgr.get('someCustomKey', {'my_field_1': ObjectInstance, 'my_field_2': true ...})` - * will (by default) return a `ChainedProvider` that uses the passed in `object` instance - * followed by environment variables and then aftconfig.json to lookup a value when using the - * returned `ChainedProvider.get(key, defaultVal)` function. - * - * calling `cfgmgr.set((configKey: string, options: object) => new CustomProvider(configKey))` - * overrides the default returned `ChainedProvider` with a new `CustomProvider` instance that will - * be returned from future `cfgmgr.get(...)` calls - */ -export const cfgmgr = new ConfigManager(); \ No newline at end of file diff --git a/packages/aft-core/src/configuration/envvar-provider.ts b/packages/aft-core/src/configuration/envvar-provider.ts deleted file mode 100644 index 85d17094..00000000 --- a/packages/aft-core/src/configuration/envvar-provider.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { IConfigProvider } from "./i-config-provider"; - -export class EnvVarProvider implements IConfigProvider { - public readonly varPrefix: string; - - constructor(variableNamePrefix: string) { - this.varPrefix = variableNamePrefix; - } - - async get(key: K, defaultVal?: V): Promise { - let result: V; - const genKey: string = `${this.varPrefix}_${String(key)}`; - const val: string = process.env[genKey]; - if (val !== undefined) { - let res: unknown; - try { - res = JSON.parse(val) as V; - } catch (e) { - res = val; - } - result = res as V; - } - return (result === undefined) ? defaultVal : result; - } -} \ No newline at end of file diff --git a/packages/aft-core/src/configuration/i-config-provider.ts b/packages/aft-core/src/configuration/i-config-provider.ts deleted file mode 100644 index b8f06b5f..00000000 --- a/packages/aft-core/src/configuration/i-config-provider.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface IConfigProvider { - get(key: K, defaultVal?: V): Promise; -} \ No newline at end of file diff --git a/packages/aft-core/src/configuration/i-has-config.ts b/packages/aft-core/src/configuration/i-has-config.ts deleted file mode 100644 index 9ab8f859..00000000 --- a/packages/aft-core/src/configuration/i-has-config.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface IHasConfig { - config(key: K, defaultVal?: V): Promise; -} \ No newline at end of file diff --git a/packages/aft-core/src/configuration/i-has-options.ts b/packages/aft-core/src/configuration/i-has-options.ts deleted file mode 100644 index 7993f441..00000000 --- a/packages/aft-core/src/configuration/i-has-options.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface IHasOptions { - option(key: K, defaultVal?: V): V; -} \ No newline at end of file diff --git a/packages/aft-core/src/configuration/options-manager.ts b/packages/aft-core/src/configuration/options-manager.ts deleted file mode 100644 index a364144d..00000000 --- a/packages/aft-core/src/configuration/options-manager.ts +++ /dev/null @@ -1,102 +0,0 @@ -class OptionsManager { - /** - * iterates through the values of any properties on the passed - * in `object` and if they are a string, attempts to extract - * environment variables from them and / or convert them into - * an object. For example: - * ```typescript - * const options = { - * "foo": "%some_env_var_key%", - * "bar": "[10, true, 'baz']" - * } - * const updated = optmgr.process(options); - * ``` - * with an environment variable of `some_env_var_key` set to `"24"`. - * - * would result in the following object being returned: - * ```typescript - * { - * "foo": 24, - * "bar": [10, true, "baz"] - * } - * ``` - * @param options an object to be processed - * @returns the processed object - */ - process(options: T): T { - let result: T; - if (options) { - const keys = Object.keys(options); - for (var i=0; i 0) { - let envValStr: string = process.env[matchResults[1]]; - result = envValStr || str; - } - return result; - } - - /** - * attempts to call `JSON.parse` on the passed in `str` and returns - * the resulting value or the original `str` if an error occurs - * @param str input string that may be parsable by `JSON.parse` - * @returns the result of calling `JSON.parse` or the original `str` - */ - private _processJson(str: string): string | object { - let result: string | object; - try { - result = JSON.parse(str); - } catch (e) { - result = str; - } - return result; - } -} - -/** - * iterates through the values of any properties on the passed - * in `object` and if they are a string, attempts to extract - * environment variables from them and / or convert them into - * an object. For example: - * ```typescript - * const options = { - * "foo": "%some_env_var_key%", - * "bar": "[10, true, 'baz']" - * } - * const updated = optmgr.process(options); - * ``` - * with an environment variable of `some_env_var_key` set to `"24"`. - * - * would result in the following object being returned: - * ```typescript - * { - * "foo": 24, - * "bar": [10, true, "baz"] - * } - * ``` - */ -export const optmgr = new OptionsManager(); \ No newline at end of file diff --git a/packages/aft-core/src/configuration/options-provider.ts b/packages/aft-core/src/configuration/options-provider.ts deleted file mode 100644 index 62c04ebf..00000000 --- a/packages/aft-core/src/configuration/options-provider.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { IConfigProvider } from "./i-config-provider"; -import { optmgr } from "./options-manager"; - -export class OptionsProvider implements IConfigProvider { - private readonly _options: T; - - constructor(options: T) { - options = options || {} as T; - this._options = optmgr.process(options); - } - - async get(key: K, defaultVal?: V): Promise { - let result: V = this._options[key] as V; - return (result === undefined) ? defaultVal : result; - } -} \ No newline at end of file diff --git a/packages/aft-core/src/helpers/cache-map.ts b/packages/aft-core/src/helpers/cache-map.ts index 555ae37c..8db1b4db 100644 --- a/packages/aft-core/src/helpers/cache-map.ts +++ b/packages/aft-core/src/helpers/cache-map.ts @@ -20,7 +20,7 @@ export class CacheMap implements Map(filename) : new Map(); } diff --git a/packages/aft-core/src/helpers/custom-types.ts b/packages/aft-core/src/helpers/custom-types.ts index b55a2bda..f17a6bb3 100644 --- a/packages/aft-core/src/helpers/custom-types.ts +++ b/packages/aft-core/src/helpers/custom-types.ts @@ -65,13 +65,24 @@ export type JsonValue = JsonKey | boolean | JsonObject | null | undefined; export type JsonObject = { [key: JsonKey]: JsonValue; } | Array; /** - * this type allows for more complex return values - * to be expressed from functions that would normally - * return a simple boolean + * this type allows for a descriptive message to be + * included in a result from functions that would normally + * be limited to returning only a single value + * + * ex: + * ```typescript + * function shouldDoWork(input: Worker): ProcessingResult { + * try { + * const result = input.functionThatMightThrow(); + * return { result: result }; + * } catch (e) { + * return { result: false, message: Err.short(e) }; + * } + * } + * ``` */ -export type ProcessingResult = { - obj?: any; - success?: boolean; +export type ProcessingResult = { + result: T; message?: string; }; diff --git a/packages/aft-core/src/helpers/disposable.ts b/packages/aft-core/src/helpers/disposable.ts deleted file mode 100644 index b5c4336f..00000000 --- a/packages/aft-core/src/helpers/disposable.ts +++ /dev/null @@ -1,18 +0,0 @@ -/** - * interface should be implemented by classes that require - * some disposal after their use. automatic disposal is - * handled by using the `Disposable` within the `using` - * object like follows: - * ``` - * async using(new ImplementsDisposable(), async (disp) => { - * await disp.doSomethingAsync(); - * disp.doSomethingSync(); - * }); - * ``` - * where the `dispose` function would be called - * automatically upon completion or in the case of an - * Error - */ -export interface Disposable { - dispose(error?: any): void; -} \ No newline at end of file diff --git a/packages/aft-core/src/helpers/err.ts b/packages/aft-core/src/helpers/err.ts index 9e77e418..f2ab8768 100644 --- a/packages/aft-core/src/helpers/err.ts +++ b/packages/aft-core/src/helpers/err.ts @@ -1,5 +1,6 @@ -import { LogLevel } from '../plugins/logging/log-level'; -import { LogManager } from '../plugins/logging/log-manager'; +import { LogLevel } from '../logging/log-level'; +import { Reporter } from '../plugins/reporting/reporter'; +import { AftLogger, aftLogger } from '../logging/aft-logger'; import { convert } from './convert'; import { Func } from './custom-types'; import { ellide } from './ellide'; @@ -8,51 +9,53 @@ export type ErrVerbosity = 'full' | 'short'; export type ErrOptions = { /** - * an optional `LogManager` instance to use in logging the error message + * an optional `Reporter` instance to use in logging the error message * and stack */ - logMgr?: LogManager; + logger: Reporter; /** * the `LogLevel` to use when logging any caught `Error`. defaults to * `warn` */ - errLevel?: LogLevel; + errLevel: LogLevel; /** * the amount of detail to include in the output message. defaults to * `full` */ - verbosity?: ErrVerbosity; + verbosity: ErrVerbosity; } /** * provides a standardised way of generating log-friendly exception details * in either short or full formatting. Usage would look like: * ```typescript - * const logMgr = new LogManager({logName: 'foo'}); - * const result = await Err.handle(functionThatThrowsTypeError, { - * logMgr: logMgr, - * errLevel: 'debug', - * verbosity: 'short' - * }); + * const result1 = Err.handle(() => functionThatThrowsTypeError()); + * const result2 = await Err.handleAsync(async () => asyncFunctionThatThrowsArgumentError()); * ``` * which would output: * ```text - * YYYYMMDD - [foo] - DEBUG - TypeError: [max 100 characters of message...] --- [max 300 characters of the ... first line of stack trace] + * YYYYMMDD - [AFT] - WARN - TypeError: [max 100 characters of message...] --- [max 300 characters...of the stack trace] + * YYYYMMDD - [AFT] - WARN - ArgumentError: [max 100 characters of message...] --- [max 300 characters...of the stack trace] * ``` + * + * > NOTE: an optional `Partial` object can be passed to the `handle` and `handleAsync` functions allowing + * you to control the `LogLevel` used _(defaults to `'warn'`)_, the verbosity _(defaults to `'short'`)_, and the + * `Reporter` instance used _(defaults to `aftLog` global instance)_ + * * and: * ```typescript - * const logMgr = new LogManager({logName: 'AFT'}); + * const logger = new Reporter('AFT'); * try { * functionThatThrowsTypeError(); * } catch (e) { - * await logMgr.warn(Err.short(e)); - * await logMgr.debug(Err.full(e)); + * await logger.warn(Err.short(e)); + * await logger.debug(Err.full(e)); * } * ``` * which outputs: * ```text - * YYYYMMDD - [AFT] - WARN - TypeError: [max 100 characters of message...] --- [max 300 characters of the ... first line of stack trace] - * YYYYMMDD - [AFT] - DEBUG - TypeError: [full type error description message] + * YYYYMMDD - [AFT] - WARN - TypeError: [max 100 characters of message...] --- [max 300 characters...of the stack trace] + * YYYYMMDD - [AFT] - DEBUG - TypeError: [full type error message and stack trace] * [full stack trace of as much as the Error contained] * ``` */ @@ -70,26 +73,26 @@ export class Err { get verbosity(): ErrVerbosity { if (!this._verbosity) { - this._verbosity = 'full'; + this._verbosity = 'short'; } return this._verbosity; } setVerbosity(v: ErrVerbosity): this { - this._verbosity = (['full', 'short'].includes(v)) ? v : 'full'; + this._verbosity = (['full', 'short'].includes(v)) ? v : 'short'; return this; } get type(): string { - return this.err?.name || 'Error'; + return this.err?.name ?? 'Error'; } get message(): string { - return this.err?.message || 'unknown'; + return this.err?.message ?? 'unknown'; } get stack(): string { - return this.err?.stack || 'unknown'; + return this.err?.stack ?? 'unknown'; } toString(): string { @@ -178,35 +181,56 @@ export module Err { } /** - * calls the passed in `Func>` and handles any errors + * calls the passed in `Func` and handles any errors * @param func a function to be run inside a try-catch - * @param optsOrLogMgr an `ErrOptions` object containing options for this handler or a - * `LogManager` used to log any captured `Error` _(defaults to `undefined`)_ - * > **WARNING** passing a `LogManager` is deprecated and you should instead add the - * `LogManager` using the `logMgr` field in the `ErrOptions` instance) + * @param opts an `ErrOptions` object containing options for this call to `handle` * @returns the result of the passed in `func` or `null` if an error is thrown */ - export async function handle(func: Func>, optsOrLogMgr?: LogManager | ErrOptions): Promise { - let opts: ErrOptions; - if (_isLogManager(optsOrLogMgr)) { // TODO: remove this in next major release - opts = {logMgr: optsOrLogMgr} as ErrOptions; - await opts.logMgr?.warn(`passing a 'LogManager' is DEPRECATED! pass a 'ErrOptions' object containing your 'LogManager' instead`); - } else { - opts = optsOrLogMgr as ErrOptions || {}; + export function handle(func: Func, opts?: Partial): T { + try { + return func(); + } catch (e) { + opts ??= {}; + opts.verbosity ??= 'short'; + opts.errLevel ??= 'warn'; + const err = new Err(e).setVerbosity(opts.verbosity); + if (opts.logger) { + opts.logger[opts?.errLevel](e.toString()); + } else { + aftLogger.log({ + name: this.constructor.name, + level: opts.errLevel, + message: e.toString() + }); + } + return null as T; } + } + + /** + * calls the passed in `Func>` and handles any errors + * @param func a function to be run inside a try-catch + * @param opts an `ErrOptions` object containing options for this call to `handle` + * @returns the result of the passed in `func` or `null` if an error is thrown + */ + export async function handleAsync(func: Func>, opts?: Partial): Promise { return await Promise.resolve() .then(func) .catch(async (err) => { + opts ??= {}; + opts.verbosity ??= 'short'; + opts.errLevel ??= 'warn'; const e = new Err(err).setVerbosity(opts?.verbosity); - await opts?.logMgr?.[opts?.errLevel || 'warn'](e.toString()); - return null; + if (opts.logger) { + await opts.logger[opts?.errLevel ?? 'warn'](e.toString()); + } else { + aftLogger.log({ + name: this.constructor.name, + level: opts.errLevel, + message: e.toString() + }); + } + return null as T; }); } - - function _isLogManager(obj: any): boolean { - if (obj?.logName && obj?.trace && obj?.debug && obj?.info) { - return true; - } - return false; - } } \ No newline at end of file diff --git a/packages/aft-core/src/helpers/expiring-file-lock.ts b/packages/aft-core/src/helpers/expiring-file-lock.ts index d3570e38..51419bf5 100644 --- a/packages/aft-core/src/helpers/expiring-file-lock.ts +++ b/packages/aft-core/src/helpers/expiring-file-lock.ts @@ -3,7 +3,8 @@ import * as path from "path"; import * as os from "os"; import { flockSync } from "fs-ext"; import { convert } from "./convert"; -import { ellide, EllipsisLocation } from "./ellide"; +import { ellide } from "./ellide"; +import { AftConfig, aftConfig } from "../configuration/aft-config"; /** * class will create a new (or use existing) lockfile locking @@ -14,12 +15,17 @@ import { ellide, EllipsisLocation } from "./ellide"; * throwing an exception * * Ex: + * ```json + * // aftconfig.json + * { + * fileLockMaxWait: 10000, + * fileLockMaxHold: 5000 + * } * ``` - * const maxWait = 10000; // 10 seconds - * const maxHold = 5000; // 5 seconds + * ```typescript * // wait a maximum of 10 seconds to aquire lock and then hold * // lock for maximum of 5 seconds or until `unlock` is called - * const lock = new ExpiringFileLock('unique_name', maxWait, maxHold); + * const lock = new ExpiringFileLock('unique_name'); * try { * // perform action on shared resource... * } finally { @@ -28,6 +34,7 @@ import { ellide, EllipsisLocation } from "./ellide"; * ``` */ export class ExpiringFileLock { + public readonly aftCfg: AftConfig; public readonly lockName: string; public readonly lockDuration: number; public readonly waitDuration: number; @@ -35,12 +42,13 @@ export class ExpiringFileLock { private readonly _lockFileDescriptor: number; private readonly _timeout: NodeJS.Timeout; - constructor(lockFileName: string, maxWaitDurationMs: number, maxHoldDurationMs: number) { + constructor(lockFileName: string, aftCfg?: AftConfig) { if (!lockFileName) { throw `[${this.constructor.name}] - lockFileName must be set`; } - this.lockDuration = maxHoldDurationMs || 1; // defaults to 1 ms - this.waitDuration = maxWaitDurationMs || 1; // defaults to 1 ms + this.aftCfg = aftCfg ?? aftConfig; + this.lockDuration = Math.abs(this.aftCfg.fileLockMaxHold ?? 10000); // ensure positive value; defaults to 10 s + this.waitDuration = Math.abs(this.aftCfg.fileLockMaxWait ?? 10000); // ensure positive value; defaults to 10 s this.lockName = path.join(os.tmpdir(), ellide(convert.toSafeString(lockFileName), 255, 'beginning', '')); this._lockFileDescriptor = this._waitForLock(); this._timeout = setTimeout(() => flockSync(this._lockFileDescriptor, 'un'), this.lockDuration); @@ -81,4 +89,21 @@ export class ExpiringFileLock { } return lockFileDescriptor; } +} + +export module ExpiringFileLock { + /** + * creates a new {ExpiringFileLock} that can be used to ensure separate processes cannot cause + * a race condition when accessing a shared resource + * @param name the name of the lock file + * @param wait the number of milliseconds to wait for a lock to be acquired + * @param hold the number of milliseconds that a lock can be held before it automatically releases + * @returns an {ExpiringFileLock} instance + */ + export function get(name: string, wait?: number, hold?: number): ExpiringFileLock { + const aftCfg = new AftConfig(); + aftCfg.set('fileLockMaxHold', hold ?? aftCfg.fileLockMaxHold); + aftCfg.set('fileLockMaxWait', wait ?? aftCfg.fileLockMaxWait); + return new ExpiringFileLock(name, aftCfg); + } } \ No newline at end of file diff --git a/packages/aft-core/src/helpers/file-io.ts b/packages/aft-core/src/helpers/file-io.ts index 91e5f4db..d9e06756 100644 --- a/packages/aft-core/src/helpers/file-io.ts +++ b/packages/aft-core/src/helpers/file-io.ts @@ -1,7 +1,6 @@ import * as fs from "fs"; import * as path from "path"; import { Func } from "./custom-types"; -import { ExpiringFileLock } from "./expiring-file-lock"; class FileIO { /** @@ -92,20 +91,6 @@ class FileIO { } return obj; } - - /** - * class will create a new (or use existing) lockfile locking - * it using an exclusive `flock` that automatically will release - * after the specified `maxDurataionMs` or when the `unlock` - * function is called - * @param lockFileName the name of the temporary lockfile to use - * @param maxWaitDurationMs the maximum amount fo time to wait to acquire the lock - * @param maxHoldDurationMs the maximum amount of time the lock can be held - * @returns an `ExpriringFileLock` instance that can be used to release the lock - */ - getExpiringFileLock(lockFileName: string, maxWaitDurationMs?: number, maxHoldDurationMs?: number): ExpiringFileLock { - return new ExpiringFileLock(lockFileName, maxWaitDurationMs, maxHoldDurationMs); - } } export const fileio = new FileIO(); \ No newline at end of file diff --git a/packages/aft-core/src/helpers/file-system-map.ts b/packages/aft-core/src/helpers/file-system-map.ts index 6f4d110b..7cded5ff 100644 --- a/packages/aft-core/src/helpers/file-system-map.ts +++ b/packages/aft-core/src/helpers/file-system-map.ts @@ -3,6 +3,7 @@ import { convert } from "./convert"; import { JsonKey, JsonValue } from "./custom-types"; import { ExpiringFileLock } from "./expiring-file-lock"; import { fileio } from "./file-io"; +import { AftConfig, aftConfig } from "../configuration/aft-config"; /** * an implementation of `Map` that stores all its data on the filesystem allowing @@ -13,19 +14,24 @@ import { fileio } from "./file-io"; * the extension .json appended to it * @param entries an optional array of arrays containing two elements used to seed * the instantiated map object + * @param aftCfg an optional `AftConfig` instance that allows you to override any + * `FileSystemMapConfig` loaded from `appsettings.json` */ export class FileSystemMap implements Map { public readonly filename: string; private readonly _memoryMap: Map; + private readonly _aftCfg: AftConfig; - constructor(filename: string, entries?: readonly (readonly [Tkey, Tval])[] | null) { + constructor(filename: string, entries?: readonly (readonly [Tkey, Tval])[] | null, aftCfg?: AftConfig) { if (!filename) { - throw 'filename argument must be defined'; + throw `[${this.constructor.name}] filename argument must be defined'`; } + this._aftCfg = aftCfg ?? aftConfig; this._memoryMap = new Map(); - this.filename = path.join(process.cwd(), this.constructor.name, `${convert.toSafeString(filename)}.json`); + const dir = this._aftCfg.fsMapDirectory; + this.filename = path.join(process.cwd(), dir, `${convert.toSafeString(filename)}.json`); this._updateMemoryMap(); if (entries?.length > 0) { for (var i=0; i impleme } private _writeToFile(): void { - const lock: ExpiringFileLock = fileio.getExpiringFileLock(this.filename, 10000, 5000); + const lock: ExpiringFileLock = new ExpiringFileLock(this.filename, this._aftCfg); try { fileio.write(this.filename, convert.mapToString(this._memoryMap)); } finally { @@ -101,7 +107,7 @@ export class FileSystemMap impleme private _updateMemoryMap(): void { let fileMapData: Map; - const lock: ExpiringFileLock = fileio.getExpiringFileLock(this.filename, 10000, 5000); + const lock: ExpiringFileLock = new ExpiringFileLock(this.filename, this._aftCfg); try { fileMapData = fileio.readAs>(this.filename, convert.stringToMap); } catch (e) { diff --git a/packages/aft-core/src/helpers/retry.ts b/packages/aft-core/src/helpers/retry.ts index e0c10f6c..b08ca02c 100644 --- a/packages/aft-core/src/helpers/retry.ts +++ b/packages/aft-core/src/helpers/retry.ts @@ -1,3 +1,4 @@ +import { AftConfig, aftConfig } from "../configuration/aft-config"; import { convert } from "./convert"; import { Func, RetryBackOffType } from "./custom-types"; import { wait } from "./wait"; @@ -7,186 +8,113 @@ import { wait } from "./wait"; * in `delay` interval (using the specified `backOffType` back-off) until the `condition` succeeds (returns `true`) */ export class Retry implements PromiseLike { - #retryable: Func>; - #result: T; - #delay: number; - #currentDelay: number; - #backOffType: RetryBackOffType; - #condition: Func>; - #maxAttempts: number; - #totalAttempts: number; - #failAction: Func; - #err: any; - #maxDuration: number; - #totalDuration: number; - #success: boolean; - #reject: boolean; - - constructor(retryable: Func>) { - this.#retryable = retryable; - this.#delay = 1; - this.#currentDelay = this.#delay; - this.#backOffType = 'constant'; - this.#maxAttempts = Infinity; - this.#totalAttempts = 0; - this.#condition = (result: T) => result != null; - this.#maxDuration = Infinity; - this.#reject = true; - } - - /** - * the `Func>` to call until it's return - * value passes the `condition` - */ - get retryable(): Func> { - return this.#retryable; - } - - /** - * the last result returned by the `retryable` or `undefined` + private readonly _aftCfg: AftConfig; + private readonly _retryable: Func>; + + private _condition: Func>; + private _delay: number; + private _backOffType: RetryBackOffType; + private _maxAttempts: number; + private _maxDuration: number; + private _reject: boolean; + private _currentDelay: number; + private _result: T; + private _success: boolean; + private _totalAttempts: number; + private _totalDuration: number; + private _failAction: Func; + private _err: any; + + constructor(retryable: Func>, aftCfg?: AftConfig) { + this._retryable = retryable; + this._aftCfg = aftCfg ?? aftConfig; + this._delay = this._aftCfg.retryDelayMs; + this._currentDelay = this._delay; + this._backOffType = this._aftCfg.retryBackOffType; + this._maxAttempts = this._aftCfg.retryMaxAttempts; + this._totalAttempts = 0; + this._condition = (result: T) => result != null; + this._maxDuration = this._aftCfg.retryMaxDurationMs; + this._reject = this._aftCfg.retryRejectOnFail; + } + + /** + * the last result returned by the `retryable` or `undefined`. this can be used + * if `RetryConfig.rejectOnFail` is set to `false` */ get result(): T { - return this.#result; - } - - /** - * the starting amount to delay between retries (defaults to 1ms). - * call `withStartDelayBetweenAttempts(number)` to specify a value - */ - get startDelay(): number { - return this.#delay; - } - - /** - * the millisecond delay amount most recently used (or to be used) between - * retry attempts - */ - get currentDelay(): number { - return this.#currentDelay; - } - - /** - * the `RetryBackOffType` used to determine how the delay between - * attempts changes on each subsequent attempt - */ - get backOffType(): RetryBackOffType { - return this.#backOffType; - } - - /** - * a `Func` (function accepting an argument of type `T` - * and returning a boolean result) that is used to determine if the `retryable` is successful - */ - get condition(): Func> { - return this.#condition; - } - - /** - * the maximum number of retries to attempt before giving up (defaults to `Infinity`). - * call `withMaxAttempts(number)` to specify a value - */ - get maxAttempts(): number { - return this.#maxAttempts; + return this._result; } /** - * the total number of attempts actually executed at the time this is called + * the total number of attempts actually executed at the time this is called. this + * can be used if `RetryConfig.rejectOnFail` is set to `false` */ get totalAttempts(): number { - return this.#totalAttempts; + return this._totalAttempts; } /** - * a `Func` to call each time the `retryable` does not succeed - * (defaults to undefined). call `withFailAction(func)` to specify a value - */ - get failAction(): Func { - return this.#failAction; - } - - /** - * the last error returned by the `retryable` (if any) + * the last error returned by the `retryable` (if any). this can be used if + * `RetryConfig.rejectOnFail` is set to `false` */ get lastError(): any { - return this.#err; - } - - /** - * a maximum amount of time to call the `retryable` if it is not successful - * (defaults to `Infinity`). call `withMaxDuration(number)` to specify a value - */ - get maxDuration(): number { - return this.#maxDuration; + return this._err; } /** * the total amount of time spent calling the `retryable` until it succeeded - * or reached the maximum duration or number of attempts + * or reached the maximum duration or number of attempts. this can be used if + * `RetryConfig.rejectOnFail` is set to `false` */ get totalDuration(): number { - return this.#totalDuration; + return this._totalDuration; } /** * a `boolean` indicating if the result of the `retryable` eventually passed the * `condition` successfully. a value of `false` indicates that either a maximum - * duration or number of attempts was reached before success + * duration or number of attempts was reached before success. this can be used if + * `RetryConfig.rejectOnFail` is set to `false` */ get isSuccessful(): boolean { - return this.#success; + return this._success; } /** - * a `boolean` indicating if a rejected promise should be returned if the `retryable` - * does not successfully pass the `condition` within either the maximum number of - * attempts or duration specified (default is `true`). call `rejectIfUnsuccessful(false)` - * to change the default behaviour to resolve the promise with `undefined` instead + * allows for specifying a custom `condition` to determine the success of calling + * the `retryable` (default is if the `retryable` returns a non-null and non-undefined result) + * @param condition a function that accepts an argument of type `T` and returns + * a `boolean` result based on a comparison of the argument with an expectation + * @returns the current `Retry` instance */ - get reject(): boolean { - return this.#reject; + until(condition: Func>): this { + this._condition = condition; + return this; } - /** - * allows for specifying a starting number of milliseconds to delay between retry - * attempts (defaults to 1ms) - * @param delayMs the starting number of milliseconds to delay between attempts - * @returns the current `Retry` instance - */ - withStartDelayBetweenAttempts(delayMs: number): this { - this.#delay = delayMs; + withDelay(milliseconds: number): this { + this._delay = milliseconds; return this; } - /** - * allows for specifying a `RetryBackOffType` used to calculate the delay between attempts - * (default is `constant` which will continually use the value specified for `startDelay`) - * @param backOffType a `RetryBackOffType` used to calculate the delay between attempts - * @returns the current `Retry` instance - */ withBackOff(backOffType: RetryBackOffType): this { - this.#backOffType = backOffType; + this._backOffType = backOffType; return this; } - /** - * allows for specifying a custom `condition` to determine the success of calling - * the `retryable` (default is if the `retryable` returns a non-null and non-undefined result) - * @param condition a function that accepts an argument of type `T` and returns - * a `boolean` result based on a comparison of the argument with an expectation - * @returns the current `Retry` instance - */ - until(condition: Func>): this { - this.#condition = condition; + withMaxDuration(milliseconds: number): this { + this._maxDuration = milliseconds; return this; } - /** - * allows for specifying a limit to the number of retry attempts - * @param maxAttempts the maximum number of times to call the `retryable` - * @returns the current `Retry` instance - */ - withMaxAttempts(maxAttempts: number): this { - this.#maxAttempts = maxAttempts; + withMaxAttempts(attempts: number): this { + this._maxAttempts = attempts; + return this; + } + + withRejectOnFail(reject: boolean): this { + this._reject = reject; return this; } @@ -197,34 +125,7 @@ export class Retry implements PromiseLike { * @returns the current `Retry` instance */ withFailAction(func: Func): this { - this.#failAction = func; - return this; - } - - /** - * allows for specifying the maximum number of milliseconds to wait for - * the `retryable` to return a value that passes the `condition` (defaults - * to `Infinity`) - * @param durationMs the maximum number of milliseconds to wait for the - * `retryable` to succeed - * @returns the current `Retry` instance - */ - withMaxDuration(durationMs: number): this { - this.#maxDuration = durationMs; - return this; - } - - /** - * allows for specifying `false` if the last result should be returned if the `retryable` - * cannot successfully pass the `condition` instead of returning a rejected promise - * @param enable a `boolean` indicating if a rejected promise should be returned - * if the `retryable` is unable to successfully pass the `condition` within either - * the maximum number of attempts or duration specified (default is `true`) - * @returns `true` if a rejected promise is returned on failure or `false` if a - * resolved promise of the last result should be returned instead - */ - rejectIfUnsuccessful(enable: boolean): this { - this.#reject = enable; + this._failAction = func; return this; } @@ -235,15 +136,15 @@ export class Retry implements PromiseLike { * @returns `true` if the `result` successfully passes the `condition` * otherwise `false` */ - async isConditionMet(result: T): Promise { + private async _isConditionMet(result: T): Promise { return Promise.resolve(result) - .then(this.condition) + .then(this._condition) .catch(() => false); } async then(onfulfilled?: (value: T) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike): Promise { - if (this.maxDuration < Infinity) { - return wait.forResult(() => this._getInnerPromise(), this.maxDuration) + if (this._maxDuration < Infinity) { + return wait.forResult(() => this._getInnerPromise(), this._maxDuration) .then(onfulfilled, onrejected); } else { return this._getInnerPromise() @@ -253,36 +154,37 @@ export class Retry implements PromiseLike { private async _getInnerPromise(): Promise { const startTime = Date.now(); - this.#currentDelay = this.startDelay; - this.#success = false; - this.#totalDuration = 0; - while (!this.isSuccessful && this.totalAttempts < this.maxAttempts && this.totalDuration < this.maxDuration) { - this.#result = await Promise.resolve() - .then(this.retryable) + this._currentDelay = this._delay; + this._success = false; + this._totalDuration = 0; + while (!this._success && this._totalAttempts < this._maxAttempts && this._totalDuration < this._maxDuration) { + this._result = await Promise.resolve() + .then(this._retryable) .catch((e) => { - this.#err = e; + this._err = e; return undefined; }); - this.#success = await this.isConditionMet(this.result); - if (!this.isSuccessful) { - if (this.failAction) { + this._success = await this._isConditionMet(this._result); + if (!this._success) { + if (this._failAction) { await Promise.resolve() - .then(this.failAction) + .then(this._failAction) .catch(() => { /* ignore */ }); } - await wait.forDuration(this.currentDelay); + await wait.forDuration(this._currentDelay); } - this.#totalAttempts++; - this.#currentDelay = Retry.calculateBackOffDelay(this.startDelay, this.currentDelay, this.backOffType); - this.#totalDuration = convert.toElapsedMs(startTime); + this._totalAttempts++; + this._currentDelay = Retry.calculateBackOffDelay(this._delay, this._currentDelay, this._backOffType); + this._totalDuration = convert.toElapsedMs(startTime); } - if (!this.isSuccessful && this.reject) { - return Promise.reject(`unable to get a successful result after ${convert.toHoursMinutesSeconds(this.totalDuration)} over ${this.totalAttempts} attempts`); + if (!this._success && this._reject) { + return Promise.reject(`[${this.constructor.name}] unable to get a successful result after` + + ` ${convert.toHoursMinutesSeconds(this._totalDuration)} over ${this._totalAttempts} attempts`); } - return this.result; + return this._result; } /** @@ -317,21 +219,36 @@ export class Retry implements PromiseLike { * generates a new `Retry` instance that runs a given `retryable` until it * successfully passes a `condition` * - * Ex: + * Ex: using `aftconfig.json` to control conditions + * ```json + * // aftconfig.json + * { + * "retryDelayMs": 1000, + * "retryBackOffType": "exponential", + * "retryMaxAttempts": 10, + * "retryMaxDurationMs": 30000 + * } + * ``` + * ```typescript + * // in your code + * const result = await retry(() => someAction()).until((res: number) => res === 5); * ``` - * const result = await retry(() => returnsNullableObj()); // will call until returns non-nullish value * - * const result = await retry(() => someAction()) - * .withStartDelayBetweenAttempts(1000) // wait 1 second before retrying - * .withBackOff('exponential') // increase the delay between retries exponentially - * .withMaxAttempts(10) // stop after 10 retries if not successful - * .withMaxDuration(30000) // stop after 30 seconds if not successful - * .until((res: number) => res === 5); // expect result to equal 5 + * Ex: overriding `aftconfig.json` to control conditions + * ```typescript + * // in your code + * const result = await retry(() => someAction(), new AftConfig({ + * retryDelayMs: 1000, + * retryBackOffType: 'exponential', + * retryMaxAttempts: 10, + * retryMaxDurationMs: 30000 + * })).unti((res: number) => res === 5); * ``` * @param retryable the function to be retried until it passes a default * condition of return value != null or a custom `condition` + * @param aftCfg an optional `AftConfig` instance allowing you to override the default settings in `aftconfig.json` * @returns a new `Retry` instance */ -export const retry = (retryable: Func>): Retry => { - return new Retry(retryable); +export const retry = (retryable: Func>, aftCfg?: AftConfig): Retry => { + return new Retry(retryable, aftCfg); }; \ No newline at end of file diff --git a/packages/aft-core/src/helpers/using.ts b/packages/aft-core/src/helpers/using.ts index df7b440e..8faaf712 100644 --- a/packages/aft-core/src/helpers/using.ts +++ b/packages/aft-core/src/helpers/using.ts @@ -1,5 +1,23 @@ import { Func } from "./custom-types"; -import { Disposable } from "./disposable"; + +/** + * interface should be implemented by classes that require + * some disposal after their use. automatic disposal is + * handled by using the `Disposable` within the `using` + * object like follows: + * ``` + * async using(new ImplementsDisposable(), async (disp) => { + * await disp.doSomethingAsync(); + * disp.doSomethingSync(); + * }); + * ``` + * where the `dispose` function would be called + * automatically upon completion or in the case of an + * Error + */ +export interface Disposable { + dispose(error?: any): void; +} /** * function will execute a passed in function passing in the supplied `Disposable` diff --git a/packages/aft-core/src/helpers/verifier.ts b/packages/aft-core/src/helpers/verifier.ts deleted file mode 100644 index 5b2e1b80..00000000 --- a/packages/aft-core/src/helpers/verifier.ts +++ /dev/null @@ -1,417 +0,0 @@ -import { buildinfo, BuildInfoManager } from "../plugins/build-info/build-info-manager"; -import { DefectManager, defects } from "../plugins/defects/defect-manager"; -import { Defect } from "../plugins/defects/defect"; -import { LogManager } from "../plugins/logging/log-manager"; -import { TestResult } from "../plugins/test-cases/test-result"; -import { TestCaseManager, testcases } from "../plugins/test-cases/test-case-manager"; -import { TestStatus } from "../plugins/test-cases/test-status"; -import { convert } from "./convert"; -import { Func, ProcessingResult } from "./custom-types"; -import { rand } from "./rand"; -import { equaling, VerifierMatcher } from "./verifier-matcher"; - -/** - * class to be used for executing some Functional Test Assertion after checking with any - * `TestCasePlugin` and `DefectPlugin` instances that have been loaded to confirm that the - * assertion should be executed based on referenced Test ID(s) or Defect ID(s) - * - * Ex: - * ``` - * await verify(async (v: Verifier) => { - * await v.logMgr.info('doing some testing...'); - * let feature = new FeatureObj(); - * return await feature.returnExpectedValue(); - * }).withDescription('example usage for Verifier') - * .and.withTestIds('C1234') // if TestCasePlugin.shouldRun('C1234') returns `false` the assertion is not run - * .and.withKnownDefectIds('AUTO-123') // if DefectPlugin.getDefect('AUTO-123').status === 'open' the assertion is not run - * .returns('expected value'); - * ``` - * @param assertion the `Func` function to be executed by this `Verifier` - * @returns a new `Verifier` instance - */ -export class Verifier implements PromiseLike { - protected _assertion: Func; - protected _matcher: VerifierMatcher; - protected _description: string; - protected _startTime: number; - protected _innerPromise: Promise; - protected _tests: Set; - protected _defects: Set; - protected _logMgr: LogManager; - protected _testMgr: TestCaseManager; - protected _defectMgr: DefectManager; - protected _buildMgr: BuildInfoManager; - - constructor() { - this._startTime = new Date().getTime(); - this._tests = new Set(); - this._defects = new Set(); - } - - /** - * a `LogManager` that uses either the Description - * or a list of Test Ids or a `uuid` as the `logName` depending - * on which is available (NOTE: description is preferred most and - * will be used if other values are also present) - */ - get logMgr(): LogManager { - let logName: string; - if (this._description) { - logName = this._description; - } else if (this._tests.size > 0) { - logName = Array.from(this._tests).join('_'); - } else { - logName = this.constructor.name; - } - if (!this._logMgr) { - this._logMgr = new LogManager({logName: logName}); - } - return this._logMgr; - } - - get testMgr(): TestCaseManager { - if (!this._testMgr) { - this._testMgr = testcases; - } - return this._testMgr; - } - - get defectMgr(): DefectManager { - if (!this._defectMgr) { - this._defectMgr = defects; - } - return this._defectMgr; - } - - get buildMgr(): BuildInfoManager { - if (!this._buildMgr) { - this._buildMgr = buildinfo; - } - return this._buildMgr; - } - - async then(onfulfilled?: (value: void) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike): Promise { - return this._getInnerPromise() - .then(onfulfilled, onrejected); - } - - protected async _getInnerPromise(): Promise { - if (!this._innerPromise) { - this._innerPromise = new Promise(async (resolve, reject) => { - try { - const shouldRun: Array = await Promise.all([ - this._shouldRun_tests(...Array.from(this._tests)), - this._shouldRun_defects(...Array.from(this._defects)) - ]); - if (shouldRun.map(pr => pr.success).reduce((prev, cur) => prev && cur)) { - await this._resolveAssertion(); - await this._logResult('Passed'); - } else { - await this._logResult('Skipped', shouldRun.filter(pr => !pr.success).map(pr => pr.message).join('; ')); - } - resolve(); - } catch(e) { - await this._logResult('Failed', e); - reject(e); - } - }); - } - return this._innerPromise; - } - - protected async _resolveAssertion(): Promise { - let result: any = await Promise.resolve(this._assertion(this)); - if (this._matcher !== undefined) { - if (!this._matcher.setActual(result).compare()) { - return Promise.reject(`${this._matcher.failureString()}`); - } - } - } - - /** - * a syntactic way of connecting fluent functions for the Verifier - */ - get and(): this { - return this; - } - - /** - * the starting point for setting up a `Verifier` execution. Generally it is preferred - * to use the `verify(...)` `const` instead of creating individual `Verifier` instances. - * ex: - * ``` - * await verify(async (v: Verifier) => { - * await v.logMgr.info('doing some testing...'); - * let feature = new FeatureObj(); - * return await feature.returnExpectedValue(); - * }).withDescription('example usage for Verifier') - * .and.withTestId('C1234') - * .returns('expected value'); - * ``` - * @param assertion the `Func` function to be executed by this `Verifier` - * @returns this `Verifier` instance - */ - verify(assertion: Func): this { - this._assertion = assertion; - return this; - } - - /** - * allows for setting the `description` to be used as the `logName` in any - * logging output from this `Verifier` - * @param description the description of this `Verifier` - * @returns this `Verifier` instance - */ - withDescription(description: string): this { - this._description = description; - return this; - } - - /** - * allows for setting a `testId` to be checked before executing the `assertion` - * and to be reported to from any connected logging plugins that connect to - * your test case management system. if all the referenced `testId` values should not be - * run (as returned by your `AbstractTestCasePlugin.shouldRun(testId)`) then - * the `assertion` will not be run. - * NOTE: multiple `testId` values can be chained together - * @param testIds a test identifier for your connected `AbstractTestCasePlugin` - * @returns this `Verifier` instance - */ - withTestIds(...testIds: string[]): this { - if (testIds?.length) { - for (var i=0; i { - const shouldRunTests = new Array(); - const shouldNotRunTests = new Array(); - if (tests?.length) { - for (var i=0; i = await this.defectMgr.findDefects(testId) || new Array(); - if (defects.some((d: Defect) => d?.status == 'open')) { - let openDefects: string = defects - .filter((d: Defect) => d.status == 'open') - .map((d: Defect) => d.id) - .join(', '); - shouldNotRunTests.push(testId); - return { - success: false, - message: `the testId ${testId} has one or more open defects so test should not be run: [${openDefects}]` - }; - } else { - shouldRunTests.push(testId); - } - } else { - shouldNotRunTests.push(testId); - } - } - let shouldRun: boolean = shouldRunTests.length > 0; - if (!shouldRun) { - return {success: false, message: `none of the supplied tests should be run: [${tests.join(', ')}]`}; - } - } - return {success: true, message: 'returning the test IDs, as an array, that should be run', obj: shouldRunTests}; - } - - protected async _shouldRun_defects(...defects: string[]): Promise { - // first search for any specified Defects by ID - if (defects?.length) { - for (var i=0; i { - try { - status = status || 'Untested'; - if (this._tests.size) { - this._tests.forEach(async (testId: string) => { - if (message) { - await this._logMessage(status, `${testId} - ${message}`); - } else { - await this._logMessage(status, testId); - } - }); - } else { - await this._logMessage(status, message); - } - - let results: TestResult[] = await this._generateTestResults(status, message, ...Array.from(this._tests.values())); - for (var i=0; i { - message = message || this.logMgr.logName; - switch (status) { - case 'Blocked': - case 'Retest': - case 'Skipped': - case 'Untested': - await this.logMgr.warn(message); - break; - case 'Failed': - await this.logMgr.fail(message); - break; - case 'Passed': - default: - await this.logMgr.pass(message); - break; - } - } - - protected async _generateTestResults(status: TestStatus, logMessage: string, ...testIds: string[]): Promise { - let results: TestResult[] = []; - if (testIds.length > 0) { - for (var i=0; i { - let result: TestResult = { - testId: testId, - created: Date.now(), - resultId: rand.guid, - resultMessage: logMessage, - status: status, - metadata: { - durationMs: convert.toElapsedMs(this._startTime), - buildName: await this.buildMgr.buildName() || 'unknown', - buildNumber: await this.buildMgr.buildNumber() || 'unknown' - } - }; - return result; - } -} - -/** - * creates a new `Verifier` instace to be used for executing some Functional - * Test Assertion. - * - * Ex: - * ``` - * await verify(async (v: Verifier) => { - * await v.logMgr.info('doing some testing...'); - * let feature = new FeatureObj(); - * return await feature.returnExpectedValue(); - * }).withDescription('example usage for Verifier') - * .and.withTestIds('C1234') // if TestCasePlugin.shouldRun('C1234') returns `false` the assertion is not run - * .and.withKnownDefectIds('AUTO-123') // if DefectPlugin.getDefect('AUTO-123').status === 'open' the assertion is not run - * .returns('expected value'); - * ``` - * @param assertion the `Func` function to be executed by this `Verifier` - * @returns a new `Verifier` instance - */ -export const verify = (assertion: Func): Verifier => { - return new Verifier().verify(assertion); -}; \ No newline at end of file diff --git a/packages/aft-core/src/index.ts b/packages/aft-core/src/index.ts index 98597f9f..775552bb 100644 --- a/packages/aft-core/src/index.ts +++ b/packages/aft-core/src/index.ts @@ -1,51 +1,38 @@ /** configuration */ -export * from './configuration/aftconfig-provider'; -export * from './configuration/chained-provider'; -export * from './configuration/config-manager'; -export * from './configuration/envvar-provider'; -export * from './configuration/i-config-provider'; -export * from './configuration/i-has-config'; -export * from './configuration/i-has-options'; -export * from './configuration/options-manager'; -export * from './configuration/options-provider'; +export * from './configuration/aft-config'; /** helpers */ export * from './helpers/cache-map'; -export * from './helpers/custom-types'; export * from './helpers/convert'; +export * from './helpers/custom-types'; export * from './helpers/ellide'; export * from './helpers/err'; export * from './helpers/expiring-file-lock'; export * from './helpers/file-io'; export * from './helpers/file-system-map'; -export * from './helpers/disposable'; export * from './helpers/machine-info'; export * from './helpers/rand'; export * from './helpers/retry'; export * from './helpers/using'; -export * from './helpers/verifier'; -export * from './helpers/verifier-matcher'; export * from './helpers/wait'; +/** logging */ +export * from './logging/aft-logger'; +export * from './logging/log-level'; +export * from './logging/log-message-data'; /** plugins */ export * from './plugins/plugin'; export * from './plugins/plugin-loader'; -export * from './plugins/plugin-manager'; -export * from './plugins/plugin-manager-with-logging'; /** plugins/build-info */ -export * from './plugins/build-info/build-info-plugin'; export * from './plugins/build-info/build-info-manager'; -/** plugins/defects */ -export * from './plugins/defects/defect-status'; -export * from './plugins/defects/defect'; -export * from './plugins/defects/defect-plugin'; -export * from './plugins/defects/defect-manager'; -/** plugins/logging */ -export * from './plugins/logging/log-message-data'; -export * from './plugins/logging/log-manager'; -export * from './plugins/logging/log-level'; -export * from './plugins/logging/logging-plugin'; -/** plugins/test-cases */ -export * from './plugins/test-cases/test-case-plugin'; -export * from './plugins/test-cases/test-case-manager'; -export * from './plugins/test-cases/test-case'; -export * from './plugins/test-cases/test-result'; -export * from './plugins/test-cases/test-status'; \ No newline at end of file +export * from './plugins/build-info/build-info-plugin'; +/** plugins/reporting */ +export * from './plugins/reporting/reporting-plugin'; +export * from './plugins/reporting/reporter'; +export * from './plugins/reporting/test-result'; +export * from './plugins/reporting/test-status'; +/** plugins/test-execution-policy */ +export * from './plugins/test-execution-policy/test-execution-policy-plugin'; +export * from './plugins/test-execution-policy/test-execution-policy-manager'; +/** verification */ +export * from './verification/verifier'; +export * from './verification/verifier-internals'; +export * from './verification/verifier-matcher'; \ No newline at end of file diff --git a/packages/aft-core/src/logging/aft-logger.ts b/packages/aft-core/src/logging/aft-logger.ts new file mode 100644 index 00000000..6b7c8bcb --- /dev/null +++ b/packages/aft-core/src/logging/aft-logger.ts @@ -0,0 +1,128 @@ +import * as colors from "colors"; +import { AftConfig, aftConfig } from "../configuration/aft-config"; +import { LogLevel } from "./log-level"; +import { ellide } from "../helpers/ellide"; +import { LogMessageData } from "./log-message-data"; + +/** + * a logging class that uses configuration to determine what + * should be logged to the console and formats the logging output + * to indicate the source of the logging data. + * Configuration for this class can be passed in directly or + * specified in `aftconfig.json` like: + * ``` + * // aftconfig.json + * { + * ... + * "logLevel": "info" + * ... + * } + * ``` + * + * **NOTE**: this should only be used in cases where using `Reporter` would + * not be reasonable such as inside core components of AFT; otherwise you + * should use a `Reporter` instance instead + */ +export class AftLogger { + public readonly aftCfg: AftConfig; + + /** + * allows for filtering out of erroneous information from logs by assigning + * values to different types of logging. the purpose of each log level is + * as follows: + * - `trace` - used when logging low-level debug events that occur within a loop + * - `debug` - used for debug logging that does not run within a loop or at a high frequency + * - `info` - used for informational events providing current state of a system + * - `step` - used within a test to denote where within the test steps we are + * - `warn` - used for unexpected errors that are recoverable + * - `pass` - used to indicate the success of a test expectation or assertion + * - `fail` - used to indicate the failure of a test expectation or assertion + * - `error` - used for unexpected errors that are **not** recoverable + * - `none` - used when no logging is desired (disables logging) + */ + get logLevel(): LogLevel { + return this.aftCfg.logLevel ?? 'warn'; + } + + constructor(aftCfg?: AftConfig) { + this.aftCfg = aftCfg ?? aftConfig; + } + + /** + * function will check that the `level` is greater or equal to the current configured `logLevel` + * and if it is, will send the `name`, `level` and `message` to the console. if any `data` + * is included it will be converted to a string using `JSON.stringify(...)` and appended + * to the `message` + * @param name the name of the system performing the log call + * @param level the `LogLevel` of this message + * @param message the string to be logged + * @param data an array of additional data to be included in the logs + */ + log(data: LogMessageData): void { + if (data?.level != 'none' && LogLevel.toValue(data?.level) >= LogLevel.toValue(this.logLevel)) { + if (data?.message) { + const out: string = this.format(data); + this.toConsole(data.level, out); + } + } + } + + /** + * formats the passed in `LogMessage.message` based on the passed in options + * @param data a `LogMessage` object containing the `level`, `name` and `message` to + * be formatted into a console-friendly log string + * @returns the formatted log string + */ + format(data: LogMessageData) { + data ??= {} as LogMessageData; + data.name ??= 'AFT'; + data.message ??= ''; + data.level ??= 'none'; + let d: string = new Date().toLocaleTimeString(); + let out: string = `${d} - [${data.name}] - ${ellide(data.level.toUpperCase(), 5, 'end', '')} - ${data.message}`; + return out; + } + + /** + * applies a colour based on the supplied `level` and outputs the `message` + * to the console using `console.log` in that colour + * > NOTE: calling this function directly will bypass checking the `level` + * to see if the `message` should actually be logged and simply outputs to + * the console + * @param level a valid {LogLevel} like 'warn' or 'trace' + * @param message the message string to log to console + */ + toConsole(level: LogLevel, message: string): void { + switch (level) { + case 'error': + case 'fail': + console.log(colors.red(message)); + break; + case 'warn': + console.log(colors.yellow(message)); + break; + case 'info': + console.log(colors.white(message)); + break; + case 'pass': + console.log(colors.green(message)); + break; + case 'step': + console.log(colors.magenta(message)); + break; + case 'trace': + case 'debug': + console.log(colors.blue(message)); + break; + default: + console.log(colors.gray(message)); + break; + } + } +} + +/** + * a global instance of the `AftLogger` for use in AFT core components or systems + * that should not log to any plugins + */ +export const aftLogger = new AftLogger(); \ No newline at end of file diff --git a/packages/aft-core/src/plugins/logging/log-level.ts b/packages/aft-core/src/logging/log-level.ts similarity index 100% rename from packages/aft-core/src/plugins/logging/log-level.ts rename to packages/aft-core/src/logging/log-level.ts diff --git a/packages/aft-core/src/logging/log-message-data.ts b/packages/aft-core/src/logging/log-message-data.ts new file mode 100644 index 00000000..2e7123ce --- /dev/null +++ b/packages/aft-core/src/logging/log-message-data.ts @@ -0,0 +1,8 @@ +import { LogLevel } from "./log-level"; + +export type LogMessageData = { + name: string; + level: LogLevel; + message: string; + args?: Array; +}; \ No newline at end of file diff --git a/packages/aft-core/src/plugins/build-info/build-info-manager.ts b/packages/aft-core/src/plugins/build-info/build-info-manager.ts index 3a9b1877..7a4400b5 100644 --- a/packages/aft-core/src/plugins/build-info/build-info-manager.ts +++ b/packages/aft-core/src/plugins/build-info/build-info-manager.ts @@ -1,73 +1,22 @@ -import { LogManager } from "../logging/log-manager"; -import { BuildInfoPlugin, BuildInfoPluginOptions } from "./build-info-plugin"; -import { machineInfo, MachineInfoData } from "../../helpers/machine-info"; -import { convert, SafeStringOption } from "../../helpers/convert"; -import { PluginManagerWithLogging, PluginManagerWithLoggingOptions } from "../plugin-manager-with-logging"; -import { Merge } from "../../helpers/custom-types"; -import { IConfigProvider } from "../../configuration/i-config-provider"; +import { AftConfig, aftConfig } from "../../configuration/aft-config"; +import { AftLogger, aftLogger } from "../../logging/aft-logger"; +import { SafeStringOption, convert } from "../../helpers/convert"; +import { Err } from "../../helpers/err"; +import { MachineInfoData, machineInfo } from "../../helpers/machine-info"; +import { pluginLoader } from "../plugin-loader"; +import { BuildInfoPlugin } from "./build-info-plugin"; -export type BuildInfoManagerOptions = Merge; +export class BuildInfoManager { + public readonly aftCfg: AftConfig; + public readonly plugins: Array -/** - * loads and provides an interface between any `BuildInfoPlugin` - * that provides CICD build details such as TeamCity, Jenkins, - * Bamboo or Octopus. - * - * to specify a plugin use the following `aftconfig.json` key: - * ``` - * { - * ... - * "buildinfomanager": { - * "pluginNames": ["plugin-name"] - * } - * ... - * } - * ``` - */ -export class BuildInfoManager extends PluginManagerWithLogging, BuildInfoManagerOptions> { - private readonly safeStrOpt: SafeStringOption[] = [{exclude: /[\()\;\\\/\|\<\>""'*&^%$#@!,.\-\+_=\?]/gi, replaceWith: ''}]; + private readonly _safeStrOpt: SafeStringOption[] = [{exclude: /[\()\;\\\/\|\<\>""'*&^%$#@!,.\-\+_=\?]/gi, replaceWith: ''}]; + private readonly _aftLogger: AftLogger; - /** - * returns a build name as provided by the first enabled plugin - * @returns the build name returned by the first enabled plugin - * or null if none exist - */ - async buildName(): Promise { - let buildName: string = await this.first() - .then((p: BuildInfoPlugin) => p?.buildName() - .catch(async (err) => { - await this.logMgr() - .then((l: LogManager) => l.warn(`error calling ${p?.constructor.name || 'unknown'}.buildName() due to: ${err}`)); - return null; - })) - .catch(async (err) => { - await this.logMgr() - .then((l: LogManager) => l.warn(err)); - return null; - }); - return buildName; - } - - /** - * returns a build number as a string as provided by the first enabled - * plugin - * @returns the build number returned by the first enabled plugin - * or null if none exist - */ - async buildNumber(): Promise { - let buildNumber: string = await this.first() - .then((p: BuildInfoPlugin) => p?.buildNumber() - .catch(async (err) => { - await this.logMgr() - .then((l: LogManager) => l.warn(`error calling ${p?.constructor.name || 'unknown'}.buildNumber() due to: ${err}`)); - return `${Date.now()}`; - })) - .catch(async (err) => { - await this.logMgr() - .then((l: LogManager) => l.warn(err)); - return `${Date.now()}`; - }); - return buildNumber; + constructor(aftCfg?: AftConfig) { + this.aftCfg = aftCfg ?? aftConfig; + this._aftLogger = (aftCfg) ? new AftLogger(aftCfg) : aftLogger; + this.plugins = pluginLoader.getPluginsByType(BuildInfoPlugin, this.aftCfg); } /** @@ -75,34 +24,70 @@ export class BuildInfoManager extends PluginManagerWithLogging { - let job: string = await this.buildName(); - if (job) { - job = convert.toSafeString(job, this.safeStrOpt); - let build: string = await this.buildNumber(); - build = convert.toSafeString(build); - return `${job}_${build}`; - } else { - let mi: MachineInfoData = machineInfo.data; - let username: string = convert.toSafeString(mi.user, this.safeStrOpt); - let machine: string = convert.toSafeString(mi.hostname, this.safeStrOpt); - let d = new Date(); - let month: number = d.getUTCMonth() + 1; - let monthStr: string = month.toString(); - if (month < 10) { - monthStr = '0' + month; - } - let day: number = d.getUTCDate(); - let dayStr: string = day.toString(); - if (day < 10) { - dayStr = '0' + day; + const bName = await this.buildName(); + const bNum = await this.buildNumber(); + return `${bName}_${bNum}`; + } + + /** + * gets the first enabled `IBuildInfoPlugin` and returns the value from it's `buidlName` + * function or a name consisting of `USERNAME_MACHINENAME` if no enabled plugins found + * @returns the build name generated by the first enabled `IBuildInfoPlugin.buildName` or + * a name consisting of `USERNAME_MACHINENAME` if no enabled plugins found + */ + async buildName(): Promise { + const plugin = this.plugins.find(p => p?.enabled); + if (plugin) { + try { + return plugin.buildName(); + } catch (e) { + this._aftLogger.log({ + name: this.constructor.name, + level: 'warn', + message: `error calling '${plugin.constructor.name}.buildName': ${Err.short(e)}` + }); } - let now: string = convert.toSafeString(`${d.getUTCFullYear()}${monthStr}${dayStr}`, this.safeStrOpt); - return `${username}_${machine}_${now}`; } + let mi: MachineInfoData = machineInfo.data; + let username: string = convert.toSafeString(mi.user, this._safeStrOpt); + let machine: string = convert.toSafeString(mi.hostname, this._safeStrOpt); + return `${username.toLocaleUpperCase()}_${machine.toLocaleUpperCase()}`; } -} -export const buildinfo = new BuildInfoManager(); \ No newline at end of file + /** + * gets the first enabled `IBuildInfoPlugin` and returns the value from it's `buildNumber` + * function or a name consisting of the current date like: `YYYYMMDD` if no enabled plugins found + * @returns the build name generated by the first enabled `IBuildInfoPlugin.buildNumber` or + * a name consisting of the current date like: `YYYYMMDD` if no enabled plugins found + */ + async buildNumber(): Promise { + const plugin = this.plugins.find(p => p?.enabled); + if (plugin) { + try { + return plugin.buildNumber(); + } catch (e) { + this._aftLogger.log({ + name: this.constructor.name, + level: 'warn', + message: `error calling '${plugin.constructor.name}.buildNumber': ${Err.short(e)}` + }); + } + } + let d = new Date(); + let month: number = d.getUTCMonth() + 1; + let monthStr: string = month.toString(); + if (month < 10) { + monthStr = '0' + month; + } + let day: number = d.getUTCDate(); + let dayStr: string = day.toString(); + if (day < 10) { + dayStr = '0' + day; + } + let now: string = convert.toSafeString(`${d.getUTCFullYear()}${monthStr}${dayStr}`, this._safeStrOpt); + return now; + } +} \ No newline at end of file diff --git a/packages/aft-core/src/plugins/build-info/build-info-plugin.ts b/packages/aft-core/src/plugins/build-info/build-info-plugin.ts index 70a106e0..e5dc0c19 100644 --- a/packages/aft-core/src/plugins/build-info/build-info-plugin.ts +++ b/packages/aft-core/src/plugins/build-info/build-info-plugin.ts @@ -1,8 +1,6 @@ -import { Plugin, PluginOptions } from "../plugin"; +import { Plugin } from "../plugin"; -export type BuildInfoPluginOptions = PluginOptions; - -export abstract class BuildInfoPlugin extends Plugin { - abstract buildName(): Promise; - abstract buildNumber(): Promise; +export class BuildInfoPlugin extends Plugin { + buildName = (): Promise => null; + buildNumber = (): Promise => null; } \ No newline at end of file diff --git a/packages/aft-core/src/plugins/defects/defect-manager.ts b/packages/aft-core/src/plugins/defects/defect-manager.ts deleted file mode 100644 index 7a6541c7..00000000 --- a/packages/aft-core/src/plugins/defects/defect-manager.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { LogManager } from "../logging/log-manager"; -import { Defect } from "./defect"; -import { DefectPlugin } from "./defect-plugin"; -import { PluginManagerWithLogging, PluginManagerWithLoggingOptions } from "../plugin-manager-with-logging"; - -/** - * loads and provides an interface between any `DefectPlugin` - * to lookup defects in connected systems such as Jira, Bugzilla - * or any other system that is used to store product defects so - * they can be used for test execution control (i.e. a test with - * and associated open defect will not be executed) - * to specify a plugin use the following `aftconfig.json` key: - * ``` - * { - * ... - * "defectmanager": { - * "pluginNames": ["plugin-name"] - * } - * ... - * } - * ``` - */ -export class DefectManager extends PluginManagerWithLogging, PluginManagerWithLoggingOptions> { - async getDefect(defectId: string): Promise { - let defect: Defect; - defect = await this.first() - .then((p: DefectPlugin) => p?.getDefect(defectId) - .catch(async (err) => { - await this.logMgr() - .then((l: LogManager) => l.warn(`error calling ${p?.constructor.name || 'unknown'}.getDefect(${defectId}) due to: ${err}`)); - return null; - })) - .catch(async (err) => { - await this.logMgr() - .then((l: LogManager) => l.warn(err)); - return null; - }); - return defect; - } - - async findDefects(searchTerm: string): Promise { - let defects: Defect[]; - defects = await this.first() - .then((p: DefectPlugin) => p?.findDefects(searchTerm) - .catch(async (err) => { - await this.logMgr() - .then((l: LogManager) => l.warn(`error calling ${p?.constructor.name || 'unknown'}.findDefects(${searchTerm}) due to: ${err}`)); - return []; - })) - .catch(async (err) => { - await this.logMgr() - .then((l: LogManager) => l.warn(err)); - return []; - }); - return defects || []; - } -} - -export const defects = new DefectManager(); \ No newline at end of file diff --git a/packages/aft-core/src/plugins/defects/defect-plugin.ts b/packages/aft-core/src/plugins/defects/defect-plugin.ts deleted file mode 100644 index be3023e2..00000000 --- a/packages/aft-core/src/plugins/defects/defect-plugin.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Plugin, PluginOptions } from "../plugin"; -import { Defect } from "./defect"; - -export type DefectPluginOptions = PluginOptions; - -export abstract class DefectPlugin extends Plugin { - abstract getDefect(defectId: string): Promise; - abstract findDefects(searchTerm: string): Promise; -} \ No newline at end of file diff --git a/packages/aft-core/src/plugins/defects/defect-status.ts b/packages/aft-core/src/plugins/defects/defect-status.ts deleted file mode 100644 index 46cc8b40..00000000 --- a/packages/aft-core/src/plugins/defects/defect-status.ts +++ /dev/null @@ -1,5 +0,0 @@ -/** - * type representing if a Defect is still open or if it has - * been resolved (closed) - */ -export type DefectStatus = 'open' | 'closed'; \ No newline at end of file diff --git a/packages/aft-core/src/plugins/defects/defect.ts b/packages/aft-core/src/plugins/defects/defect.ts deleted file mode 100644 index 092cd171..00000000 --- a/packages/aft-core/src/plugins/defects/defect.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { DefectStatus } from "./defect-status"; - -export type Defect = { - id: string; - title?: string; - description?: string; - status: DefectStatus; -}; \ No newline at end of file diff --git a/packages/aft-core/src/plugins/logging/log-manager.ts b/packages/aft-core/src/plugins/logging/log-manager.ts deleted file mode 100644 index a998eff5..00000000 --- a/packages/aft-core/src/plugins/logging/log-manager.ts +++ /dev/null @@ -1,281 +0,0 @@ -import { cloneDeep } from "lodash"; -import * as colors from "colors"; -import { LoggingPlugin, LoggingPluginOptions } from "./logging-plugin"; -import { LogLevel } from "./log-level"; -import { LogMessageData } from "./log-message-data"; -import { PluginManager, PluginManagerOptions } from "../plugin-manager"; -import { TestResult } from "../test-cases/test-result"; -import { ellide } from "../../helpers/ellide"; -import { Disposable } from "../../helpers/disposable"; -import { Merge } from "../../helpers/custom-types"; -import { PluginConfig } from "../plugin-loader"; - -export type LogManagerOptions = Merge; - -/** - * a logging class that uses configuration to determine what - * should be logged to the console and formats the logging output - * to indicate the source of the logging data. Additionally this - * class manages logging plugins and serves as the interface for - * sending `TestResult` data to `LoggingPlugin` instances. - * Configuration for this class can be passed in directly or - * specified in `aftconfig.json` like: - * ``` - * { - * ... - * "logmanager": { - * "level": "info", - * "plugins": [ - * {"name": "logging-plugin1", "enabled": true, "searchDirectory": "./dist/", "options": {"foo": "bar"}}, - * {"name": "logging-plugin2", "enabled": false, "options": {"foo": "bar"}} - * ] - * } - * ... - * } - * ``` - * NOTE: multiple instances of this class are expected to be created as each instance should have a unique - * `logName` associated with it. Ex: - * ```typescript - * let logMgr1: LogManager = new LogManager({logName: 'logger for test 1'}); - * let logMgr2: LogManager = new LogManager({logName: 'logger for test 2'}); - * ``` - */ -export class LogManager extends PluginManager, LogManagerOptions> implements Disposable { - private _stepCount: number = 0; - - constructor(options: LogManagerOptions) { - super(options); - } - - get logName(): string { - return this.option('logName', 'AFT'); - } - - /** - * allows for filtering out of erroneous information from logs by assigning - * values to different types of logging. the purpose of each log level is - * as follows: - * - `trace` - used when logging low-level debug events that occur within a loop - * - `debug` - used for debug logging that does not run within a loop or at a high frequency - * - `info` - used for informational events providing current state of a system - * - `step` - used within a test to denote where within the test steps we are - * - `warn` - used for unexpected errors that are recoverable - * - `pass` - used to indicate the success of a test expectation or assertion - * - `fail` - used to indicate the failure of a test expectation or assertion - * - `error` - used for unexpected errors that are **not** recoverable - * - `none` - used when no logging is desired (disables logging) - */ - async level(): Promise { - let lvl: string = await this.config('level', 'info'); - return (LogLevel.isType(lvl)) ? lvl as LogLevel : 'info'; - } - - /** - * calls the `log` function with a `LogLevel` of `trace` - * @param message the message to be logged - */ - async trace(message: string): Promise { - await this.log('trace', message); - } - - /** - * calls the `log` function with a `LogLevel` of `debug` - * @param message the message to be logged - */ - async debug(message: string): Promise { - await this.log('debug', message); - } - - /** - * calls the `log` function with a `LogLevel` of `info` - * @param message the message to be logged - */ - async info(message: string): Promise { - await this.log('info', message); - } - - /** - * calls the `log` function with a `LogLevel` of `step` - * @param message the message to be logged - */ - async step(message: string): Promise { - await this.log('step', ++this._stepCount + ': ' + message); - } - - /** - * calls the `log` function with a `LogLevel` of `warn` - * @param message the message to be logged - */ - async warn(message: string): Promise { - await this.log('warn', message); - } - - /** - * calls the `log` function with a `LogLevel` of `pass` - * @param message the message to be logged - */ - async pass(message: string): Promise { - await this.log('pass', message); - } - - /** - * calls the `log` function with a `LogLevel` of `fail` - * @param message the message to be logged - */ - async fail(message: string): Promise { - await this.log('fail', message); - } - - /** - * calls the `log` function with a `LogLevel` of `error` - * @param message the message to be logged - */ - async error(message: string): Promise { - await this.log('error', message); - } - - /** - * function will send the `LogLevel` and `message` on to any - * loaded `LoggingPlugin` objects - * @param level the `LogLevel` of this message - * @param message the string to be logged - */ - async log(level: LogLevel, message: string): Promise { - const lvl: LogLevel = await this.level(); - const name = this.logName; - const logdata: LogMessageData = {name: name, level: level, message: message}; - if (LogLevel.toValue(level) >= LogLevel.toValue(lvl) && level != 'none') { - LogManager.toConsole(logdata); - } - return await this.enabled() - .then((plugins: LoggingPlugin[]) => plugins.forEach((p: LoggingPlugin) => p?.log({...logdata}) - .catch((err) => LogManager.toConsole({ - level: 'warn', - message: `unable to send log message to '${p?.constructor.name || 'unknown'}' due to: ${err}`, - name: name - })))) - .catch((err) => LogManager.toConsole({ - level: 'warn', - message: `unable to send log message to LoggingPlugin due to: ${err}`, - name: name - })); - } - - /** - * function will send the passed in `TestResult` to any loaded `LoggingPlugin` objects - * allowing them to process the result - * @param result a `TestResult` object to be sent - */ - async logResult(result: TestResult): Promise { - const name = this.logName; - return await this.enabled() - .then((plugins: LoggingPlugin[]) => plugins.forEach((p: LoggingPlugin) => p?.logResult(name, cloneDeep(result)) - .catch((err) => LogManager.toConsole({ - level: 'warn', - message: `unable to send result to '${p?.constructor.name || 'unknown'}' due to: ${err}`, - name: name - })))) - .catch((err) => LogManager.toConsole({ - level: 'warn', - message: `unable to send result to LoggingPlugin due to: ${err}`, - name: name - })); - } - - /** - * loops through any loaded `LoggingPlugin` objects and calls - * their `dispose` function. This should be called upon completion - * of any logging actions before destroying the `LogManager` instance - */ - async dispose(error?: Error): Promise { - const name = this.logName; - await this.enabled() - .then((plugins: LoggingPlugin[]) => plugins.forEach((p: LoggingPlugin) => p?.dispose(name, error) - .catch((err) => LogManager.toConsole({ - level: 'warn', - message: `unable to call dispose on '${p?.constructor.name || 'unknown'}' due to: ${err}`, - name: name - })))) - .catch((err) => LogManager.toConsole({ - level: 'warn', - message: `unable to dispose of LoggingPlugin due to: ${err}`, - name: name - })); - } - - override async pluginConfigs(): Promise> { - const configs: Array = await this.config('plugins', []); - const updatedConfigs: Array = new Array(); - for (var i=0; i; - -export abstract class LoggingPlugin extends Plugin implements Disposable { - private _level: LogLevel; - - /** - * allows for filtering out of erroneous information from logs by assigning - * values to different types of logging. the purpose of each log level is - * as follows: - * - `trace` - used when logging low-level debug events that occur within a loop - * - `debug` - used for debug logging that does not run within a loop or at a high frequency - * - `info` - used for informational events providing current state of a system - * - `step` - used within a test to denote where within the test steps we are - * - `warn` - used for unexpected errors that are recoverable - * - `pass` - used to indicate the success of a test expectation or assertion - * - `fail` - used to indicate the failure of a test expectation or assertion - * - `error` - used for unexpected errors that are **not** recoverable - * - `none` - used when no logging is desired (disables logging) - */ - get level(): LogLevel { - if (!this._level) { - let lvl: string = this.option('level', 'none'); - this._level = LogLevel.isType(lvl) ? lvl as LogLevel : 'none'; - } - return this._level; - } - /** - * used for logging of message strings. this function would be called often - * @param message the `LogMessageData` to be logged by this plugin - */ - abstract log(message: LogMessageData): Promise; - /** - * used for logging test results. this function would only be called at the end - * of a given test - * @param logName the name of the `LogManager` instance sending this result - * @param result a `TestResult` indicating success or failure of a given test - */ - abstract logResult(logName: string, result: TestResult): Promise; - /** - * called by the parent `LogManager` before terminating to allow each plugin to - * finalise any deferred logging actions - * @param logName the name of the `LogManager` instance calling dispose - * @param err any errors detected on disposal - */ - abstract dispose(logName: string, err?: Error): Promise; -} \ No newline at end of file diff --git a/packages/aft-core/src/plugins/plugin-loader.ts b/packages/aft-core/src/plugins/plugin-loader.ts index 7e720755..8b21df86 100644 --- a/packages/aft-core/src/plugins/plugin-loader.ts +++ b/packages/aft-core/src/plugins/plugin-loader.ts @@ -1,122 +1,132 @@ import * as fs from 'fs'; import * as path from 'path'; import { convert } from '../helpers/convert'; -import { LogManager } from './logging/log-manager'; import { Plugin } from './plugin'; - -export type PluginConfig = { - name?: string; - searchDirectory?: string; - options?: object; -}; +import { AftConfig, aftConfig } from '../configuration/aft-config'; +import { Class } from '../helpers/custom-types'; class PluginLoader { - private readonly _pluginsMap: Map; - + private readonly _pluginsMap: Map; + private _loaded: boolean; + constructor() { - this._pluginsMap = new Map(); + this._pluginsMap = new Map(); + this._loaded = false; + } + + private _load(aftCfg?: AftConfig): void { + if (!this._loaded) { + aftCfg ??= aftConfig; + for (var pname of aftCfg.pluginNames ?? []) { + let searchDir: string = (path.isAbsolute(aftCfg.pluginsSearchDir ?? ".")) + ? aftCfg.pluginsSearchDir : path.join(process.cwd(), aftCfg.pluginsSearchDir); + if (!this._pluginsMap.has(pname)) { + this._findAndInstantiatePlugin(pname, searchDir, aftCfg); + } + } + this._loaded = true; + } } /** - * attempts to load plugins by name and optional path. - * + * iterates over all plugins listed in `AftConfig.pluginNames` looking for any that + * extend the passed in `clazz` and returns those that do as an array of objects. + * ex: * ```typescript - * const plugins: CustomPlugin[] = pluginloader.load([{ - * name: 'custom-plugin', - * searchDirectory: '../../plugins', - * enabled: false, - * options: { - * storagePath: './' - * } - * }, 'custom-plugin-2']); + * const reportingPlugins = pluginloader.getPluginsByType(ReportingPlugin); + * // ReportingPlugins will all extend from ReportingPlugin base class * ``` * - * **NOTE:** the above attempts to load a `custom-plugin` class. if loading - * fails then it will search the filesystem, starting at the current - * execution directory and searching all subdirectories, for a file - * named `custom-plugin.js` which, if found, will be imported and a - * new instance will be created and added to the internal cache and the - * array to be returned - * @param pluginConfigs an array of plugin name strings or `PluginConfig` objects - * used to locate and instantiate the plugins - * @returns an array of singleton plugin instances of the specified type + * NOTE: if this is the first time the `pluginloader` is being called then plugins will + * also be loaded + * @param clazz a `Class` base class like `ReportingPlugin` that must be extended + * by any of the objects returned by this call + * @param aftCfg an optional `AftConfig` instance to use when loading plugins if not + * already loaded + * @returns an array of plugin objects that all extend the passed in `clazz` class */ - async load>(pluginConfigs: Array): Promise { - let plugins: T[] = []; - if (pluginConfigs?.length > 0) { - for (var i=0; i(pname, searchDir, options); - } - const p = this._pluginsMap.get(pname) as T; - if (p) { - plugins.push(p); - } + getPluginsByType(clazz: Class, aftCfg?: AftConfig): Array { + this._load(aftCfg); + const plugins = new Array(); + const classInst = new clazz(); + for (var pKey of this._pluginsMap.keys()) { + let plugin = this._pluginsMap.get(pKey); + let isMatch = true; + for (var cKey of Object.keys(classInst)) { + let pluginKeys = Object.keys(plugin); + if (!pluginKeys.includes(cKey) || typeof plugin[cKey] !== typeof classInst[cKey]) { + isMatch = false; + break; } } + if (isMatch) { + plugins.push(plugin as T); + } } return plugins; } /** - * clears the loaded plugins so that new plugins can be loaded + * returns a plugin by it's name + * ex: + * ```typescript + * let TestExecutionPolicyPlugin = pluginloader.getPluginByName('testrail-test-execution-policy-plugin'); + * // TestExecutionPolicyPlugin will be `undefined` if not found + * ``` + * + * NOTE: if this is the first time the `pluginloader` is being called then plugins will + * also be loaded + * @param pluginName the name of the plugin package or file like `html-reporting-plugin` + * @param aftCfg an optional `AftConfig` instance to use when loading plugins if not + * already loaded + * @returns the requested plugin or `undefined` if not found + */ + getPluginByName(pluginName: string, aftCfg?: AftConfig): T { + this._load(aftCfg); + return this._pluginsMap.get(pluginName) as T; + } + + /** + * clears the cached plugins so that new plugins can be loaded * * **DANGER** * * only use if you are certain you know what you are doing as this * can result in multiple instances of named plugins existing */ - clear(): void { + reset(): void { this._pluginsMap.clear(); + this._loaded = false; } - private _findAndInstantiatePlugin(pluginName: string, searchRoot: string, config: PluginConfig): void { - let plugin: T; - + private _findAndInstantiatePlugin(pluginName: string, searchRoot: string, aftCfg: AftConfig): void { + let plugin: Plugin; + let pathToPlugin: string; try { - // LogManager.toConsole({name: this.constructor.name, message: `searching for plugin '${pluginName}' starting at: ${searchRoot}`, level: 'trace'}); - let pathToPlugin: string = this._findPlugin(searchRoot, new RegExp(`^${pluginName}\.js$`)); + pathToPlugin = this._findPlugin(searchRoot, new RegExp(`^${pluginName}\.js$`)); if (pathToPlugin) { - // LogManager.toConsole({name: this.constructor.name, message: `found plugin '${pluginName}' at: ${pathToPlugin}`, level: 'trace'}); plugin = require(pathToPlugin); } else { throw new Error(`plugin could not be located`); } } catch (ee) { - throw new Error(`unable to load plugin: '${pluginName}' from within directory '${searchRoot}' due to: ${ee}`); + throw new Error(`unable to load plugin: '${pluginName}' from '${pathToPlugin ?? searchRoot}' due to: ${ee}`); } if (plugin) { try { let constructorName: string; let keys: string[] = Object.keys(plugin); - let name: string = convert.toSafeString(pluginName, [{exclude: /[-_.\s\d]/gi, replaceWith: ''}]); - // LogManager.toConsole({name: this.constructor.name, message: `searching for plugin constructor name for ${pluginName}...`, level: 'trace'}); + const name = convert.toSafeString(pluginName, [{exclude: /[-_.\s\d]/gi, replaceWith: ''}]); for (var i=0; i` and would be expected to accept an object extending - * `PluginOptions` object in its constructor. + * attempts to load plugins by name and optional path. * - * ```typescript - * const plugins: CustomPlugin[] = pluginloader.load([{ - * name: 'custom-plugin', - * searchDirectory: '../../plugins', - * enabled: false, - * options: { - * storagePath: './' - * } - * }, 'custom-plugin-2']); + * ```json + * // aftconfig.json + * { + * "pluginsSearchDir": "../", + * "pluginNames": [ + * "testrail-reporting-plugin", + * "testrail-test-execution-policy-plugin" + * "html-reporting-plugin" + * ] + * } * ``` * - * **NOTE:** the above attempts to load a `custom-plugin` class. if loading - * fails then it will search the filesystem, starting at the current - * execution directory and searching all subdirectories, for a file - * named `custom-plugin.js` which, if found, will be imported and a - * new instance will be created and added to the internal cache and the - * array to be returned + * **NOTE:** the above will attempt to load a `testrail-reporting-plugin`, + * `testrail-test-execution-policy-plugin` and `html-reporting-plugin` class. if loading + * fails then it will search the filesystem, starting at the relative + * `pluginsSearchDir` path (relative to current nodejs execution dir) + * and searching all subdirectories, for a file named `custom-plugin.js` + * which, if found, will be imported and a new instance will be created + * and added to the internal cache and the array to be returned */ -export const pluginloader = new PluginLoader(); \ No newline at end of file +export const pluginLoader = new PluginLoader(); \ No newline at end of file diff --git a/packages/aft-core/src/plugins/plugin-manager-with-logging.ts b/packages/aft-core/src/plugins/plugin-manager-with-logging.ts deleted file mode 100644 index 3e9a69f6..00000000 --- a/packages/aft-core/src/plugins/plugin-manager-with-logging.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Merge } from "../helpers/custom-types"; -import { LogManager } from "./logging/log-manager"; -import { Plugin } from "./plugin"; -import { PluginManager, PluginManagerOptions } from "./plugin-manager"; - -export type PluginManagerWithLoggingOptions = Merge; - -export abstract class PluginManagerWithLogging, Tc extends PluginManagerWithLoggingOptions> extends PluginManager { - private _logMgr: LogManager; - - constructor(options?: Tc) { - super(options); - } - - override config(key: K, defaultVal?: V): Promise { - return super.config(key, defaultVal) as Promise; - } - - async logMgr(): Promise { - if (!this._logMgr) { - const logName = await this.config('logName', this.constructor.name); - this._logMgr = new LogManager({logName: logName}); - } - return this._logMgr; - } -} \ No newline at end of file diff --git a/packages/aft-core/src/plugins/plugin-manager.ts b/packages/aft-core/src/plugins/plugin-manager.ts deleted file mode 100644 index 5154e411..00000000 --- a/packages/aft-core/src/plugins/plugin-manager.ts +++ /dev/null @@ -1,128 +0,0 @@ -import { Plugin } from "./plugin"; -import { PluginConfig, pluginloader } from "./plugin-loader"; -import { IConfigProvider } from "../configuration/i-config-provider"; -import { cfgmgr } from "../configuration/config-manager"; -import { IHasConfig } from "../configuration/i-has-config"; -import { IHasOptions } from "../configuration/i-has-options"; - -export type PluginManagerOptions = { - plugins?: Array; -} - -/** - * base class for use by classes that load in and manage plugins. - * `PluginManager` instances should specify their plugin names and - * location in the passed in `options` object or in the - * `aftconfig.json` file under a section whose name - * exactly matches the `PluginManager` instance's class name in all - * lowercase. - * - * ex: `PluginInstance` - * ```typescript - * export type PluginInstanceOptions = Union; - * export class PluginInstance extends Plugin { - * constructor(options?: PluginInstanceOptions) { - * super(options); - * } - * } - * ``` - * ex: `PluginManagerInstance` - * ```typescript - * export type PluginManagerInstanceOptions = Union; - * export class PluginManagerInstance extends PluginManager { - * constructor(options?: PluginManagerInstanceOptions) { - * super(options); - * } - * } - * ``` - * ex: `aftconfig.json` - * ```json - * { - * "PluginManagerInstance": { - * ... - * "plugins": [ - * {"name": "some-custom-plugin", "enabled": false, "searchDirectory": "/full/path/to/search"}, - * {"name": "a-second-plugin", "searchDirectory": "../../relative-path-to-search", "options": {"foo": "option used by plugin instance"}} - * ], - * "bar": "configurataion used by PluginManagerInstance" - * ... - * } - * } - * ``` - * NOTE: the `PluginManagerInstance` will load plugins listed in the `pluginNames` array - * and pass them any additional `options` specified (in this case the values for `foo` and `bar`) - */ -export abstract class PluginManager, Tc extends PluginManagerOptions> implements IHasConfig, IHasOptions { - private _plugins: T[]; - private readonly _config: IConfigProvider; - private readonly _options: Tc; - - /** - * allows for specifying optional configuration for the `PluginManager` that will take - * precedence over other forms of configuration as long as the `cfgmgr` is not overridden - * @param options an object defining configuration to be used by this `PluginManager` instance - */ - constructor(options?: Tc) { - this._options = options || {} as Tc; - this._config = cfgmgr.get(this.constructor.name, options); - } - - async config(key: K, defaultVal?: V): Promise { - return this._config.get(key, defaultVal); - } - - option(key: K, defaultVal?: V): V { - const result: V = this._options[key] as V; - return (result === undefined) ? defaultVal : result; - } - - async pluginConfigs(): Promise> { - return this.config('plugins', []); - } - - /** - * returns the array of loaded plugin instances - */ - async plugins(): Promise { - if (!this._plugins) { - this._plugins = await this.load(); - } - return this._plugins || []; - } - - /** - * returns the first loaded plugin instance - */ - async first(): Promise { - const enabled = await this.enabled(); - return (enabled?.length > 0) ? enabled[0] : null; - } - - async enabled(): Promise { - const plugins = await this.plugins(); - return plugins.filter((p: T) => p.enabled); - } - - /** - * attempts to find the first plugin who's class name matches a specified string - * @param ctorName the class name of the plugin - * @returns the first plugin who's class name matched the passed in `ctorName` (both lowercase) - */ - async named(ctorName: string): Promise { - return await this.plugins() - .then((plugins: T[]) => plugins - .filter((p: T) => p?.constructor.name.toLowerCase() === ctorName?.toLowerCase())) - .catch((err) => null); - } - - /** - * instantiates new plugins and caches them for use at `plugins` - * - * NOTE: this does not destroy previous instances, but removes them - * from the internal array and replaces them with the new instances - */ - async load(): Promise { - const pluginConfigs = await this.pluginConfigs(); - return pluginloader.load(pluginConfigs) || []; - } -} \ No newline at end of file diff --git a/packages/aft-core/src/plugins/plugin.ts b/packages/aft-core/src/plugins/plugin.ts index 99f88ced..dd5d5318 100644 --- a/packages/aft-core/src/plugins/plugin.ts +++ b/packages/aft-core/src/plugins/plugin.ts @@ -1,32 +1,27 @@ -import { IHasOptions } from "../configuration/i-has-options"; -import { optmgr } from "../configuration/options-manager"; +import { AftConfig, aftConfig } from "../configuration/aft-config"; +import { AftLogger, aftLogger } from "../logging/aft-logger"; -export type PluginOptions = { - enabled?: boolean; +export class PluginConfig { + enabled: boolean = false; } /** - * interface to be implemented by any Plugin implementation + * class to be extended by any `Plugin` implementation */ -export abstract class Plugin implements IHasOptions { - private readonly _opts: T; - - private _enabled: boolean; - - constructor(options?: T) { - options = options || {} as T; - this._opts = optmgr.process(options); +export class Plugin { + private readonly _aftCfg: AftConfig; + private readonly _aftLogger: AftLogger; + get aftCfg(): AftConfig { + return this._aftCfg; } - - option(key: K, defaultVal?: V): V { - const result: V = this._opts[key] as V; - return (result === undefined) ? defaultVal : result; + get aftLogger(): AftLogger { + return this._aftLogger; } - get enabled(): boolean { - if (this._enabled == null) { - this._enabled = this.option('enabled', true); - } - return this._enabled; + return false; + } + constructor(aftCfg?: AftConfig) { + this._aftCfg = aftCfg ?? aftConfig; + this._aftLogger = (aftCfg) ? new AftLogger(aftCfg) : aftLogger; } } \ No newline at end of file diff --git a/packages/aft-core/src/plugins/reporting/reporter.ts b/packages/aft-core/src/plugins/reporting/reporter.ts new file mode 100644 index 00000000..e471c1dc --- /dev/null +++ b/packages/aft-core/src/plugins/reporting/reporter.ts @@ -0,0 +1,223 @@ +import { ReportingPlugin } from "./reporting-plugin"; +import { LogLevel } from "../../logging/log-level"; +import { AftConfig } from "../../configuration/aft-config"; +import { pluginLoader } from "../plugin-loader"; +import { AftLogger, aftLogger } from "../../logging/aft-logger"; +import { TestResult } from "./test-result"; +import { Err } from "../../helpers/err"; +import { cloneDeep } from "lodash"; + +/** + * a class that manages reporting plugins. + * Configuration for this class can be passed in directly or + * specified in `aftconfig.json` like: + * ``` + * // aftconfig.json + * { + * ... + * "logLevel": "info" + * ... + * } + * ``` + * NOTE: multiple instances of this class are expected to be created as each instance should have a unique + * `reporterName` associated with it. Ex: + * ```typescript + * const r1 = new Reporter('reporter for test 1'); + * const r2 = new Reporter('reporter for test 2'); + * ``` + */ +export class Reporter { + readonly plugins: Array; + private readonly _aftLogger: AftLogger; + private _stepCount: number = 0; + + /** + * a name unique to a given reporter instance intended to uniquely identify output by + * either the associated test or class doing the reporting + */ + public readonly reporterName: string; + /** + * allows for filtering out of erroneous information from logs by assigning + * values to different types of logging. the purpose of each log level is + * as follows: + * - `trace` - used when logging low-level debug events that occur within a loop + * - `debug` - used for debug logging that does not run within a loop or at a high frequency + * - `info` - used for informational events providing current state of a system + * - `step` - used within a test to denote where within the test steps we are + * - `warn` - used for unexpected errors that are recoverable + * - `pass` - used to indicate the success of a test expectation or assertion + * - `fail` - used to indicate the failure of a test expectation or assertion + * - `error` - used for unexpected errors that are **not** recoverable + * - `none` - used when no logging is desired (disables logging) + */ + public readonly logLevel: LogLevel; + + constructor(logName: string, aftCfg?: AftConfig) { + this.reporterName = logName ?? 'AFT'; + this._aftLogger = (aftCfg) ? new AftLogger(aftCfg) : aftLogger; + this.logLevel = this._aftLogger.logLevel; + this.plugins = pluginLoader.getPluginsByType(ReportingPlugin, this._aftLogger.aftCfg); + this.plugins.filter(p => { + try { + return p?.enabled; + } catch (e) { + return false; + } + }).forEach((p: ReportingPlugin) => { + p?.initialise(logName)?.catch((err) => this._aftLogger.log({ + level: 'warn', + message: err, + name: logName + })); + }) + } + + /** + * calls the `log` function with a `LogLevel` of `trace` + * @param message the message to be logged + */ + async trace(message: string, ...data: Array): Promise { + await this.log('trace', message, ...data); + } + + /** + * calls the `log` function with a `LogLevel` of `debug` + * @param message the message to be logged + */ + async debug(message: string, ...data: Array): Promise { + await this.log('debug', message, ...data); + } + + /** + * calls the `log` function with a `LogLevel` of `info` + * @param message the message to be logged + */ + async info(message: string, ...data: Array): Promise { + await this.log('info', message, ...data); + } + + /** + * calls the `log` function with a `LogLevel` of `step` + * @param message the message to be logged + */ + async step(message: string, ...data: Array): Promise { + await this.log('step', ++this._stepCount + ': ' + message, ...data); + } + + /** + * calls the `log` function with a `LogLevel` of `warn` + * @param message the message to be logged + */ + async warn(message: string, ...data: Array): Promise { + await this.log('warn', message, ...data); + } + + /** + * calls the `log` function with a `LogLevel` of `pass` + * @param message the message to be logged + */ + async pass(message: string, ...data: Array): Promise { + await this.log('pass', message, ...data); + } + + /** + * calls the `log` function with a `LogLevel` of `fail` + * @param message the message to be logged + */ + async fail(message: string, ...data: Array): Promise { + await this.log('fail', message, ...data); + } + + /** + * calls the `log` function with a `LogLevel` of `error` + * @param message the message to be logged + */ + async error(message: string, ...data: Array): Promise { + await this.log('error', message, ...data); + } + + /** + * function will send the `LogLevel` and `message` on to any + * loaded `ReportingPlugin` objects + * @param level the `LogLevel` of this message + * @param message the string to be logged + * @param data an array of additional data to be included in the logs + */ + async log(level: LogLevel, message: string, ...data: any[]): Promise { + this._aftLogger.log({ + name: this.reporterName, + level, + message, + args: data + }); + for (var plugin of this.plugins.filter(p => { + try{ + return p?.enabled; + } catch (e) { + /* ignore */ + } + })) { + try { + await plugin?.log(this.reporterName, level, message, ...data); + } catch (e) { + this._aftLogger.log({ + level: 'warn', + message: `unable to send log message to '${plugin?.constructor.name || 'unknown'}' due to: ${e}`, + name: this.reporterName + }); + } + } + } + + /** + * function will send the passed in `TestResult` to any loaded `IResultsPlugin` implementations + * allowing them to process the result + * @param result a `TestResult` object to be sent + */ + async submitResult(result: TestResult): Promise { + for (var plugin of this.plugins.filter(p => Err.handle(() => p?.enabled))) { + try { + await plugin?.submitResult(this.reporterName, cloneDeep(result)); + } catch (e) { + this._aftLogger.log({ + level: 'warn', + message: `unable to send result to '${plugin?.constructor.name || 'unknown'}' due to: ${Err.short(e)}`, + name: result?.testName ?? this.constructor.name + }); + } + } + } + + /** + * loops through any loaded `ReportingPlugin` objects and calls + * their `dispose` function. This should be called upon completion + * of any logging actions before destroying the `AftLogger` instance + */ + async dispose(error?: Error): Promise { + const name = this.reporterName; + for (var plugin of this.plugins.filter(p => { + try{ + return p?.enabled; + } catch { + /* ignore */ + } + })) { + try { + await plugin?.finalise(name); + } catch (e) { + this._aftLogger.log({ + level: 'warn', + message: `unable to call dispose on '${plugin?.constructor.name || 'unknown'}' due to: ${e}`, + name: name + }); + } + } + if (error) { + this._aftLogger.log({ + level: 'error', + message: error.message, + name: name + }); + } + } +} \ No newline at end of file diff --git a/packages/aft-core/src/plugins/reporting/reporting-plugin.ts b/packages/aft-core/src/plugins/reporting/reporting-plugin.ts new file mode 100644 index 00000000..4f116ccc --- /dev/null +++ b/packages/aft-core/src/plugins/reporting/reporting-plugin.ts @@ -0,0 +1,52 @@ +import { Plugin, PluginConfig } from "../plugin"; +import { LogLevel } from "../../logging/log-level"; +import { TestResult } from "./test-result"; + +export class ReportingPluginConfig extends PluginConfig { + logLevel: LogLevel; +} + +export class ReportingPlugin extends Plugin { + override get enabled(): boolean { + return this.logLevel != 'none'; + } + /** + * allows for filtering out of erroneous information from logs by assigning + * values to different types of logging. the purpose of each log level is + * as follows: + * - `trace` - used when logging low-level debug events that occur within a loop + * - `debug` - used for debug logging that does not run within a loop or at a high frequency + * - `info` - used for informational events providing current state of a system + * - `step` - used within a test to denote where within the test steps we are + * - `warn` - used for unexpected errors that are recoverable + * - `pass` - used to indicate the success of a test expectation or assertion + * - `fail` - used to indicate the failure of a test expectation or assertion + * - `error` - used for unexpected errors that are **not** recoverable + * - `none` - used when no logging is desired (disables logging) + */ + get logLevel(): LogLevel { + return this.aftLogger.logLevel; + } + /** + * called by the parent `Reporter` on load to allow any plugins to configure + * themselves for a new logger + * @param logName the name of the `Reporter` instance calling dispose + */ + initialise = (logName: string): Promise => null; + /** + * used for reporting message strings. this function would be called often + * @param message the `LogMessageData` to be logged by this plugin + */ + log = (name: string, level: LogLevel, message: string, ...data: any[]): Promise => null; + /** + * function will report on the passed in `TestResult` + * @param result a `TestResult` object to be sent + */ + submitResult = (name: string, result: TestResult): Promise => null; + /** + * called by the parent `Reporter` before terminating to allow each plugin to + * finalise any deferred logging actions + * @param name the name of the `Reporter` instance calling finalise + */ + finalise = (name: string): Promise => null; +} \ No newline at end of file diff --git a/packages/aft-core/src/plugins/test-cases/test-result.ts b/packages/aft-core/src/plugins/reporting/test-result.ts similarity index 80% rename from packages/aft-core/src/plugins/test-cases/test-result.ts rename to packages/aft-core/src/plugins/reporting/test-result.ts index 86ed69f7..cb6b5630 100644 --- a/packages/aft-core/src/plugins/test-cases/test-result.ts +++ b/packages/aft-core/src/plugins/reporting/test-result.ts @@ -1,13 +1,12 @@ import { TestStatus } from "./test-status"; -import { Defect } from "../defects/defect"; import { JsonObject } from "../../helpers/custom-types"; export type TestResult = { testId?: string; + testName?: string; resultMessage?: string; status: TestStatus; resultId: string; created: number; - defects?: Defect[]; metadata?: JsonObject; }; \ No newline at end of file diff --git a/packages/aft-core/src/plugins/reporting/test-status.ts b/packages/aft-core/src/plugins/reporting/test-status.ts new file mode 100644 index 00000000..9d90a545 --- /dev/null +++ b/packages/aft-core/src/plugins/reporting/test-status.ts @@ -0,0 +1 @@ +export type TestStatus = 'untested' | 'passed' | 'blocked' | 'retest' | 'failed' | 'skipped'; \ No newline at end of file diff --git a/packages/aft-core/src/plugins/test-cases/test-case-manager.ts b/packages/aft-core/src/plugins/test-cases/test-case-manager.ts deleted file mode 100644 index 74ac8372..00000000 --- a/packages/aft-core/src/plugins/test-cases/test-case-manager.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { LogManager } from "../logging/log-manager"; -import { TestCase } from "./test-case"; -import { TestCasePlugin } from "./test-case-plugin"; -import { PluginManagerWithLogging, PluginManagerWithLoggingOptions } from "../plugin-manager-with-logging"; - -export type TestCaseManagerOptions = PluginManagerWithLoggingOptions; - -/** - * loads and provides access to a `TestCasePlugin` for use in conditional test execution and filtering. - * to specify a plugin use the following `aftconfig.json` key: - * ``` - * { - * ... - * "TestCaseManager": { - * "plugins": [ - * {"name": "test-case-plugin", "options": {"username": "foo@bar.com", "accesskey": "SuperSecretKey"}} - * ] - * } - * ... - * } - * ``` - */ -export class TestCaseManager extends PluginManagerWithLogging, TestCaseManagerOptions> { - async getTestCase(testId: string): Promise { - let testcase: TestCase = await this.first() - .then((p: TestCasePlugin) => p?.getTestCase(testId) - .catch(async (err) => { - await this.logMgr() - .then((l: LogManager) => l.warn(`error calling '${p?.constructor.name || 'unknown'}.getTestCase(${testId}) due to: ${err}`)); - return null; - })) - .catch(async (err) => { - await this.logMgr() - .then((l: LogManager) => l.warn(err)); - return null; - }); - return testcase; - } - - async findTestCases(searchTerm: string): Promise { - let testcases: TestCase[] = await this.first() - .then((p: TestCasePlugin) => p?.findTestCases(searchTerm) - .catch(async (err) => { - await this.logMgr() - .then((l: LogManager) => l.warn(`error calling '${p?.constructor.name || 'unknown'}.findTestCases(${searchTerm}) due to: ${err}`)); - return []; - })) - .catch(async (err) => { - await this.logMgr() - .then((l: LogManager) => l.warn(err)); - return []; - }); - return testcases || []; - } - - async shouldRun(testId: string): Promise { - let shouldrun: boolean = await this.first() - .then((p: TestCasePlugin) => p?.shouldRun(testId) - .catch(async (err) => { - await this.logMgr() - .then((l: LogManager) => l.warn(`error calling '${p?.constructor.name || 'unknown'}.shouldRun(${testId}) due to: ${err}`)); - return false; - })) - .catch(async (err) => { - await this.logMgr() - .then((l: LogManager) => l.warn(err)); - return false; - }); - return shouldrun || true; - } -} - -export const testcases = new TestCaseManager(); \ No newline at end of file diff --git a/packages/aft-core/src/plugins/test-cases/test-case-plugin.ts b/packages/aft-core/src/plugins/test-cases/test-case-plugin.ts deleted file mode 100644 index e9d4a433..00000000 --- a/packages/aft-core/src/plugins/test-cases/test-case-plugin.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Plugin, PluginOptions } from "../plugin"; -import { TestCase } from "./test-case"; - -export type TestCasePluginOptions = PluginOptions; - -export abstract class TestCasePlugin extends Plugin { - abstract getTestCase(testId: string): Promise; - abstract findTestCases(searchTerm: string): Promise; - abstract shouldRun(testId: string): Promise; -} \ No newline at end of file diff --git a/packages/aft-core/src/plugins/test-cases/test-case.ts b/packages/aft-core/src/plugins/test-cases/test-case.ts deleted file mode 100644 index 137dc59e..00000000 --- a/packages/aft-core/src/plugins/test-cases/test-case.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { TestResult } from "./test-result"; -import { TestStatus } from "./test-status"; - -export type TestCase = { - id: string; - created?: number; - title?: string; - description?: string; - status: TestStatus; - result?: TestResult; -}; \ No newline at end of file diff --git a/packages/aft-core/src/plugins/test-cases/test-status.ts b/packages/aft-core/src/plugins/test-cases/test-status.ts deleted file mode 100644 index e44bc905..00000000 --- a/packages/aft-core/src/plugins/test-cases/test-status.ts +++ /dev/null @@ -1 +0,0 @@ -export type TestStatus = 'Untested' | 'Passed' | 'Blocked' | 'Retest' | 'Failed' | 'Skipped'; \ No newline at end of file diff --git a/packages/aft-core/src/plugins/test-execution-policy/test-execution-policy-manager.ts b/packages/aft-core/src/plugins/test-execution-policy/test-execution-policy-manager.ts new file mode 100644 index 00000000..af5cf761 --- /dev/null +++ b/packages/aft-core/src/plugins/test-execution-policy/test-execution-policy-manager.ts @@ -0,0 +1,57 @@ +import { AftConfig, aftConfig } from "../../configuration/aft-config"; +import { AftLogger, aftLogger } from "../../logging/aft-logger"; +import { ProcessingResult } from "../../helpers/custom-types"; +import { Err } from "../../helpers/err"; +import { pluginLoader } from "../plugin-loader"; +import { TestExecutionPolicyPlugin } from "./test-execution-policy-plugin"; +import { LogMessageData } from "../../logging/log-message-data"; + +export class TestExecutionPolicyManager { + public readonly aftCfg: AftConfig; + public readonly plugins: Array; + + private readonly _aftLogger: AftLogger; + + constructor(aftCfg?: AftConfig) { + this.aftCfg = aftCfg ?? aftConfig; + this._aftLogger = (aftCfg) ? new AftLogger(aftCfg) : aftLogger; + this.plugins = pluginLoader.getPluginsByType(TestExecutionPolicyPlugin, this.aftCfg); + } + + /** + * iterates over all enabled `ITestExecutionPolicyPlugin` implementations calling `shouldRun` + * and if any of the results return `false` then a `ShouldRunResult` containing `false` + * and a reason comprised of all plugin reasons will be returned, otherwise `true` + * @param testId the test case id to check + * @returns a `ShouldRunResult` containing `shouldRun=true` if test should be run + * otherwise `false` and a `reason` stating why + */ + async shouldRun(testId: string): Promise> { + const plugins = this._getEnabledPlugins(); + if (plugins?.length > 0) { + const results = await Promise.all(plugins.map(async p => { + try { + return await p.shouldRun(testId); + } catch (e) { + let logData: LogMessageData = { + name: this.constructor.name, + level: 'warn', + message: `error calling '${plugins.constructor.name}.shouldRun(${testId})': ${Err.short(e)}` + }; + this._aftLogger.log(logData); + return { result: true, message: logData.message }; + } + })); + const mgrResult: ProcessingResult = { + result: results.every(r => r.result === true), + message: results.map(r => r.message).join('\n') + } + return mgrResult; + } + return { result: true }; + } + + private _getEnabledPlugins(): Array { + return this.plugins.filter(p => Err.handle(() => p?.enabled)); + } +} \ No newline at end of file diff --git a/packages/aft-core/src/plugins/test-execution-policy/test-execution-policy-plugin.ts b/packages/aft-core/src/plugins/test-execution-policy/test-execution-policy-plugin.ts new file mode 100644 index 00000000..2fc84975 --- /dev/null +++ b/packages/aft-core/src/plugins/test-execution-policy/test-execution-policy-plugin.ts @@ -0,0 +1,6 @@ +import { ProcessingResult } from "../../helpers/custom-types"; +import { Plugin } from "../plugin"; + +export class TestExecutionPolicyPlugin extends Plugin { + shouldRun = (testId: string): Promise> => null; +} \ No newline at end of file diff --git a/packages/aft-core/src/verification/verifier-internals.ts b/packages/aft-core/src/verification/verifier-internals.ts new file mode 100644 index 00000000..a7b2ab92 --- /dev/null +++ b/packages/aft-core/src/verification/verifier-internals.ts @@ -0,0 +1,12 @@ +import { AftConfig } from "../configuration/aft-config"; +import { BuildInfoManager } from "../plugins/build-info/build-info-manager" +import { Reporter } from "../plugins/reporting/reporter"; +import { TestExecutionPolicyManager } from "../plugins/test-execution-policy/test-execution-policy-manager"; +import { Verifier } from "./verifier" + +export type VerifierInternals = { + usingAftConfig: (cfg: AftConfig) => Verifier, + usingBuildInfoManager: (mgr: BuildInfoManager) => Verifier, + usingReporter: (mgr: Reporter) => Verifier, + usingTestExecutionPolicyManager: (mgr: TestExecutionPolicyManager) => Verifier +} \ No newline at end of file diff --git a/packages/aft-core/src/helpers/verifier-matcher.ts b/packages/aft-core/src/verification/verifier-matcher.ts similarity index 100% rename from packages/aft-core/src/helpers/verifier-matcher.ts rename to packages/aft-core/src/verification/verifier-matcher.ts diff --git a/packages/aft-core/src/verification/verifier.ts b/packages/aft-core/src/verification/verifier.ts new file mode 100644 index 00000000..86f0206a --- /dev/null +++ b/packages/aft-core/src/verification/verifier.ts @@ -0,0 +1,426 @@ +import { Reporter } from "../plugins/reporting/reporter"; +import { TestResult } from "../plugins/reporting/test-result"; +import { TestExecutionPolicyManager } from "../plugins/test-execution-policy/test-execution-policy-manager"; +import { TestStatus } from "../plugins/reporting/test-status"; +import { convert } from "../helpers/convert"; +import { Action, Func, ProcessingResult } from "../helpers/custom-types"; +import { rand } from "../helpers/rand"; +import { equaling, VerifierMatcher } from "./verifier-matcher"; +import { Err } from "../helpers/err"; +import { BuildInfoManager } from "../plugins/build-info/build-info-manager"; +import { AftConfig, aftConfig } from "../configuration/aft-config"; +import { VerifierInternals } from "./verifier-internals"; + +export type VerifierEvent = 'skipped' | 'started' | 'done'; + +/** + * class to be used for executing some Functional Test Assertion after checking with any + * `TestExecutionPolicyPlugin` instances that have been loaded to confirm that the + * assertion should be executed based on referenced Test ID(s) + * + * Ex: + * ``` + * await verify(async (v: Verifier) => { + * await v.reporter.info('doing some testing...'); + * let feature = new FeatureObj(); + * return await feature.returnExpectedValue(); + * }).withDescription('example usage for Verifier') + * .and.withTestIds('C1234') // if TestExecutionPolicyPlugin.shouldRun('C1234') returns `false` the assertion is not run + * .returns('expected value'); + * ``` + * @param assertion the `Func` function to be executed by this `Verifier` + * @returns a new `Verifier` instance + */ +export class Verifier implements PromiseLike { + protected _aftCfg?: AftConfig; + protected _assertion: Func; + protected _matcher: VerifierMatcher; + protected _description: string; + protected _startTime: number; + protected _innerPromise: Promise; + protected _testIds: Set; + protected _reporter: Reporter; + protected _policyEngMgr: TestExecutionPolicyManager; + protected _buildInfoMgr: BuildInfoManager; + protected _actionMap: Map>; + + constructor() { + this._startTime = new Date().getTime(); + this._testIds = new Set(); + this._actionMap = new Map>(); + } + + get aftCfg(): AftConfig { + if (!this._aftCfg) { + this._aftCfg = aftConfig; + } + return this._aftCfg; + } + + /** + * a `Reporter` that uses either the Description + * or a list of Test Ids or a `uuid` as the `logName` depending + * on which is available (NOTE: description is preferred most and + * will be used if other values are also present) + */ + get reporter(): Reporter { + let logName: string; + if (this._description) { + logName = this._description; + } else if (this._testIds.size > 0) { + logName = Array.from(this._testIds).join('_'); + } else { + logName = this.constructor.name; + } + if (!this._reporter) { + this._reporter = new Reporter(logName, this.aftCfg); + } + return this._reporter; + } + + get policyEngMgr(): TestExecutionPolicyManager { + if (!this._policyEngMgr) { + this._policyEngMgr = new TestExecutionPolicyManager(this.aftCfg); + } + return this._policyEngMgr; + } + + get buildInfoMgr(): BuildInfoManager { + if (!this._buildInfoMgr) { + this._buildInfoMgr = new BuildInfoManager(this.aftCfg); + } + return this._buildInfoMgr; + } + + async then(onfulfilled?: (value: void) => TResult1 | PromiseLike, onrejected?: (reason: any) => TResult2 | PromiseLike): Promise { + return this._getInnerPromise() + .then(onfulfilled, onrejected); + } + + protected async _getInnerPromise(): Promise { + if (!this._innerPromise) { + this._innerPromise = new Promise(async (resolve, reject) => { + try { + const shouldRun = await this.shouldRun(); + if (shouldRun.result === true) { + const action = this._actionMap.get('started'); + if (action) { + Err.handle(() => action(), { + errLevel: 'warn', + logger: this.reporter + }); + } + await this._resolveAssertion(); + await this._logResult('passed'); + } else { + await this._logResult('skipped', shouldRun.message); + const action = this._actionMap.get('skipped'); + if (action) { + Err.handle(() => action(), { + errLevel: 'warn', + logger: this.reporter + }); + } + } + resolve(); + } catch(e) { + await this._logResult('failed', e); + reject(e); + } + }); + } + const action = this._actionMap.get('done'); + if (action) { + Err.handle(() => action(), { + errLevel: 'warn', + logger: this.reporter + }); + } + return this._innerPromise; + } + + protected async _resolveAssertion(): Promise { + let result: any = await Promise.resolve(this._assertion(this)); + if (this._matcher !== undefined) { + if (!this._matcher.setActual(result).compare()) { + return Promise.reject(`${this._matcher.failureString()}`); + } + } + } + + /** + * a syntactic way of connecting fluent functions for the Verifier + */ + get and(): this { + return this; + } + + /** + * allows for specifying actions to be called on certain events + * @param event an event trigger + * @param action the action to be run on the event + * @returns a reference to this {Verifier} instance + */ + on(event: VerifierEvent, action: Action): this { + this._actionMap.set(event, action); + return this; + } + + /** + * the starting point for setting up a `Verifier` execution. Generally it is preferred + * to use the `verify(...)` `const` instead of creating individual `Verifier` instances. + * ex: + * ``` + * await verify(async (v: Verifier) => { + * await v.reporter.info('doing some testing...'); + * let feature = new FeatureObj(); + * return await feature.returnExpectedValue(); + * }).withDescription('example usage for Verifier') + * .and.withTestId('C1234') + * .returns('expected value'); + * ``` + * @param assertion the `Func` function to be executed by this `Verifier` + * @returns this `Verifier` instance + */ + verify(assertion: Func): this { + this._assertion = assertion; + return this; + } + + /** + * allows for setting the `description` to be used as the `logName` in any + * logging output from this `Verifier` + * @param description the description of this `Verifier` + * @returns this `Verifier` instance + */ + withDescription(description: string): this { + this._description = description; + return this; + } + + /** + * allows for setting a `testId` to be checked before executing the `assertion` + * and to be reported to from any connected logging plugins that connect to + * your test case management system. if all the referenced `testId` values should not be + * run (as returned by your `TestExecutionPolicyPlugin.shouldRun(testId)`) then + * the `assertion` will not be run. + * NOTE: multiple `testId` values can be chained together + * @param testIds a test identifier for your connected `TestExecutionPolicyPlugin` + * @returns this `Verifier` instance + */ + withTestIds(...testIds: string[]): this { + if (testIds?.length) { + for (var i=0; i { + this._aftCfg = cfg; + return this; + }, + /** + * allows for using a specific `Reporter` instance. if not + * set then one will be created for use by this `Verifier` + * @param reporter a `Reporter` instance + * @returns this `Verifier` instance + */ + usingReporter: (reporter: Reporter): this => { + this._reporter = reporter; + return this; + }, + + /** + * allows for using a specific `TestExecutionPolicyManager` instance. if not + * set then the global `TestExecutionPolicyManager.instance()` will be used + * @param policyMgr a `TestExecutionPolicyManager` instance + * @returns this `Verifier` instance + */ + usingTestExecutionPolicyManager: (policyMgr: TestExecutionPolicyManager): this => { + this._policyEngMgr = policyMgr; + return this; + }, + + /** + * allows for using a specific `BuildInfoManager` instance. if not + * set then the global `BuildInfoManager.instance()` will be used + * @param buildMgr a `BuildInfoManager` instance + * @returns this `Verifier` instance + */ + usingBuildInfoManager: (buildMgr: BuildInfoManager): this => { + this._buildInfoMgr = buildMgr; + return this; + } + } + } + + /** + * checks if any of the supplied test ids should be run and returns `true` if at least + * one of them should + * @param testIds iterates over all test ids checking the `TestExecutionPolicyManager` to see + * if any should be run and returns `true` if any should be run, otherwise `false` + * @returns a `ProcessingResult` indicating if the testing should proceed + */ + async shouldRun(): Promise> { + const shouldRunTests = new Array(); + const shouldNotRunTests = new Array(); + const testIds = Array.from(this._testIds.keys()); + if (testIds?.length) { + for (var i=0; i = await this.policyEngMgr.shouldRun(testId); + if (result.result === true) { + shouldRunTests.push(testId); + } else { + shouldNotRunTests.push(testId); + } + } + if (shouldRunTests.length === 0) { + return {result: false, message: `none of the supplied tests should be run: [${testIds.join(', ')}]`}; + } + return {result: true, message: `the following supplied tests should be run: [${shouldRunTests.join(', ')}]`}; + } else if (this.policyEngMgr.plugins?.filter(p => Err.handle(() => p?.enabled)).length > 0) { + return {result: false, message: `no associated testIds found for test, but enabled 'ITestExecutionPolicyPlugins' exist so test should not be run`} + } + return {result: true}; + } + + /** + * creates `TestResult` objects for each `testId` and sends these + * to the `Reporter.logResult` function + */ + protected async _logResult(status: TestStatus, message?: string): Promise { + try { + status ??= 'untested'; + if (this._testIds.size) { + this._testIds.forEach(async (testId: string) => { + if (message) { + await this._logMessage(status, `${testId} - ${message}`); + } else { + await this._logMessage(status, testId); + } + }); + } else { + await this._logMessage(status, message); + } + + let results: TestResult[] = await this._generateTestResults(status, message, ...Array.from(this._testIds.values())); + for (var i=0; i { + message = message || this.reporter.reporterName; + switch (status) { + case 'blocked': + case 'retest': + case 'skipped': + case 'untested': + await this.reporter.warn(message); + break; + case 'failed': + await this.reporter.fail(message); + break; + case 'passed': + default: + await this.reporter.pass(message); + break; + } + } + + protected async _generateTestResults(status: TestStatus, logMessage: string, ...testIds: string[]): Promise { + let results: TestResult[] = []; + if (testIds.length > 0) { + for (var i=0; i { + let result: TestResult = { + testName: this.reporter.reporterName, + testId: testId, + created: Date.now(), + resultId: rand.guid, + resultMessage: logMessage, + status: status, + metadata: { + durationMs: convert.toElapsedMs(this._startTime), + buildName: await this.buildInfoMgr.buildName() || 'unknown', + buildNumber: await this.buildInfoMgr.buildNumber() || 'unknown' + } + }; + return result; + } +} + +/** + * creates a new `Verifier` instace to be used for executing some Functional + * Test Assertion. + * + * Ex: + * ```typescript + * await verify(async (v: Verifier) => { + * await v.reporter.info('doing some testing...'); + * let feature = new FeatureObj(); + * return await feature.returnExpectedValue(); + * }).withDescription('example usage for Verifier') + * .and.withTestIds('C1234') // if TestExecutionPolicyManager.shouldRun('C1234') returns `false` the assertion is not run + * .returns('expected value'); + * ``` + * @param assertion the `Func` function to be executed by this `Verifier` + * @returns a new `Verifier` instance + */ +export const verify = (assertion: Func): Verifier => { + return new Verifier().verify(assertion); +}; \ No newline at end of file diff --git a/packages/aft-core/test/configuration/aft-config-spec.ts b/packages/aft-core/test/configuration/aft-config-spec.ts new file mode 100644 index 00000000..efe03dd1 --- /dev/null +++ b/packages/aft-core/test/configuration/aft-config-spec.ts @@ -0,0 +1,39 @@ +import { AftConfig, rand } from "../../src" + +describe('AftConfig', () => { + class FakeSectionConfig { + constructor() {} + option1: number = -1; + option2: boolean = false; + option3: string = "option3val"; + }; + + it('can use a Class type to get an existing section from aftconfig.json', () => { + let randomEnvVarKey = rand.getString(12); + process.env[randomEnvVarKey] = rand.getString(15); + let aftcfg = new AftConfig({ + FakeSectionConfig: { + option1: 1, + option2: true, + option3: `%${randomEnvVarKey}%` + } + }); + + let actual = aftcfg.getSection(FakeSectionConfig); + expect(actual).not.toBeNull(); + expect(actual.option1).toEqual(1); + expect(actual.option2).toEqual(true); + expect(actual.option3).toEqual(process.env[randomEnvVarKey]); + }) + + it('can use a Class type to create a non-existing section from aftconfig.json', () => { + let aftcfg = new AftConfig({}); + + let expected = new FakeSectionConfig(); + let actual = aftcfg.getSection(FakeSectionConfig); + expect(actual).not.toBeNull(); + expect(actual.option1).toEqual(expected.option1); + expect(actual.option2).toEqual(expected.option2); + expect(actual.option3).toEqual(expected.option3); + }) +}) \ No newline at end of file diff --git a/packages/aft-core/test/configuration/aftconfig-provider-spec.ts b/packages/aft-core/test/configuration/aftconfig-provider-spec.ts deleted file mode 100644 index 86e0aaf1..00000000 --- a/packages/aft-core/test/configuration/aftconfig-provider-spec.ts +++ /dev/null @@ -1,42 +0,0 @@ -import * as path from 'path'; -import { AftConfigProvider, JsonObject } from '../../src'; -import { rand } from "../../src/helpers/rand"; - -describe('AftConfigProvider', () => { - describe('aftConfig', () => { - it('can read from aftconfig.json config file', () => { - const aftcfg: JsonObject = new AftConfigProvider('any').aftConfig; - let level: string = aftcfg['LogManager'].level; - - expect(level).not.toBeNull(); - expect(level).not.toBeUndefined(); - expect(level).toEqual('none'); - }); - - it('can modify loaded aftconfig.json object', () => { - const config = new AftConfigProvider('any'); - const aftcfg: JsonObject = config.aftConfig; - - let key: string = rand.getString(10); - let val: string = rand.getString(11); - aftcfg[key] = val; - - let aftcfg2: JsonObject = config.aftConfig; - - expect(aftcfg2[key]).toBe(val); - delete(aftcfg[key]); - }); - - it('modifying loaded aftconfig.json object does not affect actual file', () => { - const aftcfg: JsonObject = new AftConfigProvider('any').aftConfig; - - let key: string = rand.getString(10); - let val: string = rand.getString(11); - aftcfg[key] = val; - - let conf2: JsonObject = require(path.resolve(process.cwd(), 'aftconfig.json')); - - expect(conf2[key]).not.toBeDefined(); - }); - }); -}); \ No newline at end of file diff --git a/packages/aft-core/test/configuration/config-manager-spec.ts b/packages/aft-core/test/configuration/config-manager-spec.ts deleted file mode 100644 index 6271463d..00000000 --- a/packages/aft-core/test/configuration/config-manager-spec.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { cfgmgr, IConfigProvider } from "../../src"; - -describe('ConfigManager', () => { - afterEach(() => { - cfgmgr.reset(); - }); - - it('can be overridden', async () => { - class FakeProvider implements IConfigProvider { - async get(key: K, defaultVal?: V): Promise { - switch(key) { - case 'foo': - return 'bar' as unknown as V; - case 'bar': - return 'foo' as unknown as V; - } - } - } - - cfgmgr.set((configKey: string, options: object) => new FakeProvider()); - - const actual = cfgmgr.get('any', { - foo: 'foo', - bar: 'bar' - }); - - expect(await actual.get('foo')).toEqual('bar'); - expect(await actual.get('bar')).toEqual('foo'); - }); -}); \ No newline at end of file diff --git a/packages/aft-core/test/configuration/config-provider-chain-spec.ts b/packages/aft-core/test/configuration/config-provider-chain-spec.ts deleted file mode 100644 index bf0ac1ae..00000000 --- a/packages/aft-core/test/configuration/config-provider-chain-spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { ChainedProvider, EnvVarProvider, OptionsProvider, rand } from "../../src"; - -describe('ConfigProviderChain', () => { - it('will iterate through ConfigProvider instances', async () => { - type FooBar = { - foo?: string; - fooz?: boolean; - } - const configKey: string = rand.getString(10); - const env = new EnvVarProvider(configKey); - const envStrSpy = spyOn(env, 'get').and.callThrough(); - const opt = new OptionsProvider({foo: 'foo-value'}); - const optStrSpy = spyOn(opt, 'get').and.callThrough(); - - const chain = new ChainedProvider([env, opt]); - - const actualFoo: string = await chain.get('foo'); - const actualFooz: boolean = await chain.get('fooz', true); - - expect(actualFoo).toEqual('foo-value'); - expect(actualFooz).toBeTrue(); - expect(envStrSpy).toHaveBeenCalledTimes(2); - expect(optStrSpy).toHaveBeenCalledTimes(2); - }); -}); \ No newline at end of file diff --git a/packages/aft-core/test/configuration/options-manager-spec.ts b/packages/aft-core/test/configuration/options-manager-spec.ts deleted file mode 100644 index 96232f8a..00000000 --- a/packages/aft-core/test/configuration/options-manager-spec.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { optmgr, rand } from "../../src"; - -describe('OptionsManager', () => { - it('can process environment vars', () => { - const key = rand.getString(15); - const val = rand.getString(200); - const notexist = rand.getString(10); - const options = { - foo: `%${key}%`, - bar: `${key}`, - baz: `%${notexist}%` - }; - process.env[key] = val; - - const actual = optmgr.process(options); - - expect(actual.foo).toEqual(val); - expect(actual.bar).toEqual(key); - expect(actual.baz).toEqual(`%${notexist}%`); - }); - - it('can process JSON', () => { - const options = { - foo: '["bar", true, 10]' - }; - - const actual = optmgr.process(options); - - expect(actual.foo.length).toBe(3); - expect(actual.foo[0]).toEqual('bar'); - expect(actual.foo[1]).toBeTrue(); - expect(actual.foo[2]).toBe(JSON.parse('10')); - }); - - it('can process environment vars as JSON', () => { - const key = rand.getString(15); - const val = '["bar", true, 10]'; - const options = { - foo: `%${key}%` - }; - process.env[key] = val; - - const actual = optmgr.process(options); - - expect(actual.foo.length).toBe(3); - expect(actual.foo[0]).toEqual('bar'); - expect(actual.foo[1]).toBeTrue(); - expect(actual.foo[2]).toBe(JSON.parse('10')); - }) -}); \ No newline at end of file diff --git a/packages/aft-core/test/configuration/options-provider-spec.ts b/packages/aft-core/test/configuration/options-provider-spec.ts deleted file mode 100644 index ea8b60af..00000000 --- a/packages/aft-core/test/configuration/options-provider-spec.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { OptionsProvider, rand } from "../../src"; - -describe('OptionsProvider', () => { - it('can read from a simple object', async () => { - type Bar = {bar: string;}; - const expected: string = rand.guid; - const oMgr = new OptionsProvider({'bar': expected}); - - expect(expected.length).toBeGreaterThan(0); - expect(await oMgr.get('bar')).toEqual(expected); - }); - - it('returns the default value if specified key not found internally', async () => { - type FooBarBaz = { - foo?: string; - bar?: number; - baz?: boolean; - }; - const oMgr = new OptionsProvider({bar: 10, baz: true}); - - const result: string = await oMgr.get('foo', 'default-value-return'); - - expect(result).withContext('result is valid').toBeDefined(); - expect(result).withContext('default value was returned').toEqual('default-value-return'); - }); - - it('can load values from environment variables', async () => { - let key: string = rand.getString(12); - let envKey: string = rand.getString(14); - let expected: string = rand.getString(9); - process.env[envKey] = expected; - const conf = new OptionsProvider({[`${key}`]: `%${envKey}%`}); - - let actual: string = await conf.get(key, 'unexpected'); - expect(actual).not.toBeNull(); - expect(actual).toBe(expected); - - delete(process.env[envKey]); - }); - - it('will return original string if environment variable contains no data', async () => { - let key: string = rand.getString(11); - let envKey: string = rand.getString(12); - let expected: string = `%${envKey}%`; - const conf = new OptionsProvider({[`${key}`]: expected}); - - let actual: string = await conf.get(key, 'unexpected'); - expect(actual).not.toBeNull(); - expect(actual).toBe(expected); - }); - - it('can handle passing in array as options', async () => { - type FooArray = Array<{[x: string]: string}>; - const expected: string = rand.guid; - const oMgr = new OptionsProvider([{'bar': expected},{'baz': 'unexpected'}]); - - expect(await oMgr.get(0)).toEqual({'bar': expected}); - }); - - it('can load JSON from environment variables', async () => { - let key: string = rand.getString(12); - let envKey: string = rand.getString(14); - let expected: FooBar = { - foo: rand.getString(9), - bar: rand.getInt(999, 9999) - }; - process.env[envKey] = JSON.stringify(expected); - const conf = new OptionsProvider({[`${key}`]: `%${envKey}%`}); - - let actual: FooBar = await conf.get(key, null); - expect(actual).not.toBeNull(); - expect(actual.foo).toBe(expected.foo); - expect(actual.bar).toBe(expected.bar); - - delete(process.env[envKey]); - }); -}); - -type FooBar = { - foo: string; - bar: number; -} \ No newline at end of file diff --git a/packages/aft-core/test/helpers/err-spec.ts b/packages/aft-core/test/helpers/err-spec.ts index c0032c8e..31a3669b 100644 --- a/packages/aft-core/test/helpers/err-spec.ts +++ b/packages/aft-core/test/helpers/err-spec.ts @@ -1,6 +1,16 @@ -import { rand, Err, LogManager, LogLevel } from "../../src"; +import { rand, Err, Reporter, LogLevel, AftConfig } from "../../src"; + +const consolelog = console.log; describe('Err', () => { + beforeAll(() => { + console.log = (...data: any[]) => null; + }) + + afterAll(() => { + console.log = consolelog; + }) + it('exposes the original Error', () => { const err: Error = new Error(rand.getString(25)); @@ -8,17 +18,17 @@ describe('Err', () => { expect(actual.err).toBeDefined(); expect(actual.err.message).toEqual(err.message); - expect(actual.verbosity).toEqual('full'); + expect(actual.verbosity).toEqual('short'); }); it('verbosity can be set', () => { const err: Error = new Error(rand.getString(25)); - const actual = new Err(err).setVerbosity('short'); + const actual = new Err(err).setVerbosity('full'); expect(actual.err).toBeDefined(); expect(actual.err.message).toEqual(err.message); - expect(actual.verbosity).toEqual('short'); + expect(actual.verbosity).toEqual('full'); }); describe('short', () => { @@ -56,54 +66,54 @@ describe('Err', () => { describe('handle', () => { it('can handle try-catch for a Func that does not throw', async () => { const func = function () { return 'foo'; }; - const val = await Err.handle(func); + const val = Err.handle(func); expect(val).toEqual('foo'); }); it('can handle try-catch for a Func that throws', async () => { const func = function () { throw 'foo'; }; - const val = await Err.handle(func); + const val = Err.handle(func); expect(val).toBeNull(); }); it('can handle try-catch for a Func that rejects a Promise', async () => { const func = () => Promise.reject('foo'); - const val = await Err.handle(func); + const val = await Err.handleAsync(func); expect(val).toBeNull(); }); - it('will log a warning if a LogManager is supplied and the Func throws', async () => { - const logMgr = new LogManager({logName: 'will log a warning if a LogManager is supplied and the Func throws', plugins: []}); + it('will log a warning if a Reporter is supplied and the Func throws', async () => { + const reporter = new Reporter('will log a warning if a Reporter is supplied and the Func throws', new AftConfig({ pluginNames: [] })); let logMessage: string; - spyOn(logMgr, 'warn').and.callFake((message: string) => { + spyOn(reporter, 'warn').and.callFake((message: string) => { logMessage = message; return Promise.resolve(); }); const func = function () { throw 'foo'; }; - const val = await Err.handle(func, logMgr); + const val = await Err.handleAsync(func, {logger: reporter}); expect(val).toBeNull(); - expect(logMgr.warn).toHaveBeenCalledTimes(2); // 1 time for logging and 1 time to output deprecation warning for passing LogMgr instead of ErrOptions + expect(reporter.warn).toHaveBeenCalledTimes(1); expect(logMessage).toContain('Error: foo'); }); it('accepts ErrOptions as a second argument', async () => { const func = function () { throw 'foo'; }; - const logger = new LogManager({logName: 'accepts ErrOptions as a second argument'}); + const logger = new Reporter('accepts ErrOptions as a second argument'); let actualLevel: LogLevel; let actualMessage: string; - spyOn(logger, 'log').and.callFake((level: LogLevel, message: string) => { + spyOn(logger, 'log').and.callFake((level: LogLevel, message: string, ...data: any[]) => { actualLevel = level; actualMessage = message; return Promise.resolve(); }); - const val = await Err.handle(func, { + const val = await Err.handleAsync(func, { verbosity: 'short', errLevel: 'info', - logMgr: logger + logger: logger }); expect(val).toBeNull(); diff --git a/packages/aft-core/test/helpers/retry-spec.ts b/packages/aft-core/test/helpers/retry-spec.ts index 86d5431c..b0dec27b 100644 --- a/packages/aft-core/test/helpers/retry-spec.ts +++ b/packages/aft-core/test/helpers/retry-spec.ts @@ -1,16 +1,15 @@ -import { RetryBackOffType } from "../../src"; +import { AftConfig, RetryBackOffType, retry, Retry } from "../../src"; import { convert } from "../../src/helpers/convert"; -import { Retry, retry } from "../../src/helpers/retry"; describe('Retry', () => { it('can delay by specified number of milliseconds and delay type constant', async () => { const now: number = Date.now(); let result: number = 0; - await retry(() => ++result) - .until((res: number) => res > 2) - .withStartDelayBetweenAttempts(100) - .withBackOff('constant'); + await retry(() => ++result, new AftConfig({ + retryDelayMs: 100, + retryBackOffType: 'constant' + })).until((res: number) => res > 2); let elapsed: number = convert.toElapsedMs(now); expect(elapsed).toBeGreaterThan(3); @@ -21,10 +20,10 @@ describe('Retry', () => { it('can use a linearly increasing back-off delay', async () => { const now: number = Date.now(); let result: number = 0; - await retry(() => ++result) - .until((res: number) => res > 9) - .withStartDelayBetweenAttempts(10) - .withBackOff('linear'); + await retry(() => ++result, new AftConfig({ + retryDelayMs: 10, + retryBackOffType: 'linear' + })).until((res: number) => res > 9); const elapsed: number = convert.toElapsedMs(now); expect(elapsed).toBeGreaterThan(450); @@ -38,10 +37,10 @@ describe('Retry', () => { await retry(() => { actual += 1; return actual > 5; - }) - .until((res: boolean) => res) - .withStartDelayBetweenAttempts(10) - .withBackOff('exponential'); + }, new AftConfig({ + retryDelayMs: 10, + retryBackOffType: 'exponential' + })).until((res: boolean) => res); const elapsed = convert.toElapsedMs(now); expect(elapsed).toBeGreaterThan(300); @@ -52,10 +51,10 @@ describe('Retry', () => { it('can set a maximum number of attempts', async () => { const now = Date.now(); let attempts: number = 0; - await retry(() => ++attempts) - .until((res: number) => res > 100) - .withMaxAttempts(10) - .rejectIfUnsuccessful(false); + await retry(() => ++attempts, new AftConfig({ + retryMaxAttempts: 10, + retryRejectOnFail: false + })).until((res: number) => res > 100); expect(attempts).toEqual(10); const elapsed = convert.toElapsedMs(now); @@ -65,12 +64,14 @@ describe('Retry', () => { it('can set a maximum duration to run', async () => { const now = Date.now(); let attempts: number = 0; - const r = retry(() => ++attempts) - .until((res: number) => res > Infinity) - .withStartDelayBetweenAttempts(100) - .withBackOff('constant') - .withMaxDuration(500) - .rejectIfUnsuccessful(false); + const aftCfg = new AftConfig({ + retryDelayMs: 100, + retryBackOffType: 'constant', + retryMaxDurationMs: 500, + retryRejectOnFail: false, + }); + const r = retry(() => ++attempts, aftCfg) + .until((res: number) => res > Infinity); await Promise.resolve(r); const elapsed = convert.toElapsedMs(now); @@ -84,9 +85,9 @@ describe('Retry', () => { it('returns a rejected promise if max duration or attempts is exceeded before success', async () => { let attempts = 0; let errStr: string; - const r = retry(() => ++attempts) - .until((res: number) => res > Infinity) - .withMaxAttempts(100); + const r = retry(() => ++attempts, new AftConfig({ + retryMaxAttempts: 100 + })).until((res: number) => res > Infinity); await Promise.resolve(r).catch((err) => errStr = err); expect(errStr).toBeDefined(); @@ -103,9 +104,9 @@ describe('Retry', () => { return Promise.reject('fake error'); } return result > 1; - }) - .until((res: boolean) => res) - .withStartDelayBetweenAttempts(1) + }, new AftConfig({ + retryDelayMs: 1 + })).until((res: boolean) => res) .withFailAction(() => Promise.reject('fake fail action error')); expect(result).toEqual(2); @@ -120,9 +121,9 @@ describe('Retry', () => { throw new Error('fake error'); } return result > 1; - }) - .until((res: boolean) => res) - .withStartDelayBetweenAttempts(200) + }, new AftConfig({ + retryDelayMs: 200 + })).until((res: boolean) => res) .withFailAction(() => {throw new Error('fake fail action error');}); expect(result).toEqual(2); diff --git a/packages/aft-core/test/helpers/verifier-spec.ts b/packages/aft-core/test/helpers/verifier-spec.ts deleted file mode 100644 index c7527d15..00000000 --- a/packages/aft-core/test/helpers/verifier-spec.ts +++ /dev/null @@ -1,359 +0,0 @@ -import { DefectManager, Defect, LogManager, rand, TestCaseManager, Verifier, verify } from "../../src"; -import { containing, equaling } from "../../src/helpers/verifier-matcher"; - -describe('Verifier', () => { - beforeEach(() => { - testStore.clear(); - }); - - it('uses \'description\' as logMgr name if provided', async () => { - let description: string = rand.getString(22); - await verify(async (v: Verifier) => { - expect(v.logMgr.logName).toEqual(description); - }) - .withDescription(description); - }); - - it('uses \'test case IDs\' as logMgr name if no description provided', async () => { - let tcMgr = new TestCaseManager(); - spyOn(tcMgr, 'shouldRun').and.callFake((testId: string): Promise => { - return Promise.resolve(true); - }); - let dMgr = new DefectManager(); - spyOn(dMgr, 'findDefects').and.callFake((searchTerm: string): Promise => { - return Promise.resolve([]); - }); - spyOn(dMgr, 'getDefect').and.callFake((defectId: string): Promise => { - return Promise.resolve(null); - }); - - await verify(async (v: Verifier) => { - expect(v.logMgr.logName).toEqual('C1234_C2345'); - }) - .withTestIds('C1234','C2345') - .and.withTestCaseManager(tcMgr) - .and.withDefectManager(dMgr); - }); - - it('can execute a passing expectation', async () => { - let logMgr: LogManager = new LogManager({logName: 'can execute a passing expectation'}); - spyOn(logMgr, 'logResult').and.callThrough(); - spyOn(logMgr, 'pass').and.callThrough(); - let tcMgr = new TestCaseManager(); - spyOn(tcMgr, 'shouldRun').and.callFake((testId: string): Promise => { - return Promise.resolve(true); - }); - let dMgr = new DefectManager(); - spyOn(dMgr, 'findDefects').and.callFake((searchTerm: string): Promise => { - return Promise.resolve([]); - }); - spyOn(dMgr, 'getDefect').and.callFake((defectId: string): Promise => { - return Promise.resolve(null); - }); - - await verify(async (v: Verifier) => 'foo') - .returns('foo') - .withLogManager(logMgr) - .and.withTestCaseManager(tcMgr) - .and.withDefectManager(dMgr) - .and.withDescription('true should be true') - .and.withTestIds('C1234','C2345'); - - expect(tcMgr.shouldRun).toHaveBeenCalledTimes(2); - expect(dMgr.findDefects).toHaveBeenCalledTimes(2); - expect(logMgr.logResult).toHaveBeenCalledTimes(2); - expect(logMgr.pass).toHaveBeenCalledTimes(2); - }); - - it('accepts a VerifierMatcher in the returns function', async () => { - let logMgr: LogManager = new LogManager({logName: 'accepts a VerifierMatcher in the returns function'}); - spyOn(logMgr, 'logResult').and.callThrough(); - spyOn(logMgr, 'pass').and.callThrough(); - let tcMgr = new TestCaseManager(); - spyOn(tcMgr, 'shouldRun').and.callFake((testId: string): Promise => { - return Promise.resolve(true); - }); - let dMgr = new DefectManager(); - spyOn(dMgr, 'findDefects').and.callFake((searchTerm: string): Promise => { - return Promise.resolve([]); - }); - spyOn(dMgr, 'getDefect').and.callFake((defectId: string): Promise => { - return Promise.resolve(null); - }); - - await verify(async (v: Verifier) => ['foo', 'bar', 'baz']) - .returns(containing('bar')) - .withLogManager(logMgr) - .and.withTestCaseManager(tcMgr) - .and.withDefectManager(dMgr) - .and.withDescription('array contains "bar"') - .and.withTestIds('C1234','C2345'); - - expect(tcMgr.shouldRun).toHaveBeenCalledTimes(2); - expect(dMgr.findDefects).toHaveBeenCalledTimes(2); - expect(logMgr.logResult).toHaveBeenCalledTimes(2); - expect(logMgr.pass).toHaveBeenCalledTimes(2); - }); - - it('throws on exception in assertion', async () => { - let logMgr: LogManager = new LogManager({logName: 'throws on exception in assertion'}); - spyOn(logMgr, 'logResult').and.callThrough(); - spyOn(logMgr, 'fail').and.callThrough(); - let tcMgr = new TestCaseManager(); - spyOn(tcMgr, 'shouldRun').and.callFake((testId: string): Promise => { - return Promise.resolve(true); - }); - let dMgr = new DefectManager(); - spyOn(dMgr, 'findDefects').and.callFake((searchTerm: string): Promise => { - return Promise.resolve([]); - }); - spyOn(dMgr, 'getDefect').and.callFake((defectId: string): Promise => { - return Promise.resolve(null); - }); - - try { - await verify(() => { - throw new Error('fake error'); - }) - .withLogManager(logMgr) - .withTestCaseManager(tcMgr) - .withDefectManager(dMgr) - .withDescription('true should be true') - .and.withTestIds('C1234').and.withTestIds('C2345'); - - expect(true).toBe(false); // force failure - } catch (e) { - expect(e.toString()).toEqual('Error: fake error'); - } - - expect(tcMgr.shouldRun).toHaveBeenCalledTimes(2); - expect(dMgr.findDefects).toHaveBeenCalledTimes(2); - expect(logMgr.logResult).toHaveBeenCalledTimes(2); - expect(logMgr.fail).toHaveBeenCalledTimes(2); - }); - - it('throws on failed comparison with expected result', async () => { - let logMgr: LogManager = new LogManager({logName: 'throws on failed comparison with expected result',}); - spyOn(logMgr, 'logResult').and.callThrough(); - spyOn(logMgr, 'fail').and.callThrough(); - let tcMgr = new TestCaseManager(); - spyOn(tcMgr, 'shouldRun').and.callFake((testId: string): Promise => { - return Promise.resolve(true); - }); - let dMgr = new DefectManager(); - spyOn(dMgr, 'findDefects').and.callFake((searchTerm: string): Promise => { - return Promise.resolve([]); - }); - spyOn(dMgr, 'getDefect').and.callFake((defectId: string): Promise => { - return Promise.resolve(null); - }); - - try { - await verify(() => true) - .returns(false) - .and.withLogManager(logMgr) - .and.withTestCaseManager(tcMgr) - .and.withDefectManager(dMgr) - .and.withDescription('failure expected due to true not being false') - .and.withTestIds('C1234').and.withTestIds('C2345'); - - expect('foo').toBe('bar'); // force failure - } catch (e) { - expect(e.toString()).toEqual(equaling(false).setActual(true).failureString()); - } - - expect(tcMgr.shouldRun).toHaveBeenCalledTimes(2); - expect(dMgr.findDefects).toHaveBeenCalledTimes(2); - expect(logMgr.logResult).toHaveBeenCalledTimes(2); - expect(logMgr.fail).toHaveBeenCalledTimes(2); - }); - - it('will not execute expectation if test case manager says should not run for all cases', async () => { - let logMgr: LogManager = new LogManager({logName: 'will not execute expectation if test case manager says should not run for all cases'}); - spyOn(logMgr, 'logResult').and.callThrough(); - spyOn(logMgr, 'warn').and.callThrough(); - let tcMgr = new TestCaseManager(); - spyOn(tcMgr, 'shouldRun').and.callFake((testId: string): Promise => { - return Promise.resolve(false); - }); - let dMgr = new DefectManager(); - spyOn(dMgr, 'findDefects').and.callFake((searchTerm: string): Promise => { - return Promise.resolve([]); - }); - spyOn(dMgr, 'getDefect').and.callFake((defectId: string): Promise => { - return Promise.resolve(null); - }); - - await verify(() => { - testStore.set('executed', true); - }) - .withLogManager(logMgr) - .and.withTestCaseManager(tcMgr) - .and.withDefectManager(dMgr) - .and.withTestIds('C1234','C2345'); - - expect(tcMgr.shouldRun).toHaveBeenCalledTimes(2); - expect(dMgr.findDefects).not.toHaveBeenCalled(); - expect(testStore.has('executed')).toBeFalse(); - expect(logMgr.logResult).toHaveBeenCalledTimes(2); - expect(logMgr.warn).toHaveBeenCalledTimes(2); - }); - - it('will execute expectation if test case manager says any cases should be run', async () => { - let logMgr: LogManager = new LogManager({logName: 'will execute expectation if test case manager says any cases should be run'}); - spyOn(logMgr, 'logResult').and.callThrough(); - spyOn(logMgr, 'pass').and.callThrough(); - let tcMgr = new TestCaseManager(); - spyOn(tcMgr, 'shouldRun').and.callFake((testId: string): Promise => { - if (testId == 'C1234') { - return Promise.resolve(false); - } else { - return Promise.resolve(true); - } - }); - let dMgr = new DefectManager(); - spyOn(dMgr, 'findDefects').and.callFake((searchTerm: string): Promise => { - return Promise.resolve([]); - }); - spyOn(dMgr, 'getDefect').and.callFake((defectId: string): Promise => { - return Promise.resolve(null); - }); - - await verify(() => { - testStore.set('executed', true); - }) - .withLogManager(logMgr) - .and.withTestCaseManager(tcMgr) - .and.withDefectManager(dMgr) - .and.withTestIds('C1234','C2345'); - - expect(tcMgr.shouldRun).toHaveBeenCalledWith('C1234'); - expect(tcMgr.shouldRun).toHaveBeenCalledWith('C2345'); - expect(dMgr.findDefects).toHaveBeenCalledTimes(1); - expect(testStore.has('executed')).toBeTrue(); - expect(logMgr.logResult).toHaveBeenCalledTimes(2); - expect(logMgr.pass).toHaveBeenCalledTimes(2); - }); - - it('will not execute expectation if defect manager finds open defect referencing test id', async () => { - let logMgr: LogManager = new LogManager({logName: 'will not execute expectation if defect manager finds open defect referencing test id'}); - spyOn(logMgr, 'logResult').and.callThrough(); - spyOn(logMgr, 'warn').and.callThrough(); - let tcMgr = new TestCaseManager(); - spyOn(tcMgr, 'shouldRun').and.callFake((testId: string): Promise => { - return Promise.resolve(true); - }); - let dMgr = new DefectManager(); - spyOn(dMgr, 'findDefects').and.callFake((searchTerm: string): Promise => { - return Promise.resolve([{ - id: 'DEFECT-123', - title: '[C1234] problem with feature functionality', - status: 'open' - } as Defect]); - }); - spyOn(dMgr, 'getDefect').and.callFake((defectId: string): Promise => { - return Promise.resolve(null); - }); - - await verify(() => { - testStore.set('executed', true); - }) - .withLogManager(logMgr) - .and.withTestCaseManager(tcMgr) - .and.withDefectManager(dMgr) - .and.withTestIds('C1234'); - - expect(tcMgr.shouldRun).toHaveBeenCalledTimes(1); - expect(dMgr.findDefects).toHaveBeenCalledTimes(1); - expect(testStore.has('executed')).toBeFalse(); - expect(logMgr.logResult).toHaveBeenCalledTimes(1); - expect(logMgr.warn).toHaveBeenCalledTimes(1); - }); - - it('will not execute expectation if any referenced defect is open', async () => { - let logMgr: LogManager = new LogManager({logName: 'will not execute expectation if any referenced defect is open'}); - spyOn(logMgr, 'logResult').and.callThrough(); - spyOn(logMgr, 'warn').and.callThrough(); - let tcMgr = new TestCaseManager(); - spyOn(tcMgr, 'shouldRun').and.callFake((testId: string): Promise => { - return Promise.resolve(true); - }); - let dMgr = new DefectManager(); - spyOn(dMgr, 'findDefects').and.callFake((searchTerm: string): Promise => { - return Promise.resolve([]); - }); - spyOn(dMgr, 'getDefect').and.callFake((defectId: string): Promise => { - if (defectId == 'DEFECT-123') { - return Promise.resolve({ - id: defectId, - status: 'closed' - }); - } else { - return Promise.resolve({ - id: defectId, - status: 'open' - }) - } - }); - - await verify(() => { - testStore.set('executed', true); - }) - .withLogManager(logMgr) - .and.withTestCaseManager(tcMgr) - .and.withDefectManager(dMgr) - .and.withTestIds('C1234') - .and.withKnownDefectIds('DEFECT-123','DEFECT-234'); - - expect(tcMgr.shouldRun).toHaveBeenCalledTimes(1); - expect(dMgr.findDefects).toHaveBeenCalledTimes(1); - expect(dMgr.getDefect).toHaveBeenCalledTimes(2); - expect(testStore.has('executed')).toBeFalse(); - expect(logMgr.logResult).toHaveBeenCalledTimes(1); - expect(logMgr.warn).toHaveBeenCalledTimes(1); - }); - - it('will execute expectation if all defects are closed', async () => { - let logMgr: LogManager = new LogManager({logName: 'will execute expectation if all defects are closed'}); - spyOn(logMgr, 'logResult').and.callThrough(); - spyOn(logMgr, 'pass').and.callThrough(); - let tcMgr = new TestCaseManager(); - spyOn(tcMgr, 'shouldRun').and.callFake((testId: string): Promise => { - return Promise.resolve(true); - }); - let dMgr = new DefectManager(); - spyOn(dMgr, 'findDefects').and.callFake((searchTerm: string): Promise => { - return Promise.resolve([]); - }); - spyOn(dMgr, 'getDefect').and.callFake((defectId: string): Promise => { - return Promise.resolve({ - id: defectId, - status: 'closed' - }); - }); - - await verify(() => { - testStore.set('executed', true); - }) - .withLogManager(logMgr) - .and.withTestCaseManager(tcMgr) - .and.withDefectManager(dMgr) - .and.withKnownDefectIds('DEFECT-123','DEFECT-234'); - - expect(tcMgr.shouldRun).not.toHaveBeenCalled(); - expect(dMgr.findDefects).not.toHaveBeenCalled(); - expect(dMgr.getDefect).toHaveBeenCalledWith('DEFECT-123'); - expect(dMgr.getDefect).toHaveBeenCalledWith('DEFECT-234'); - expect(testStore.has('executed')).toBeTrue(); - expect(logMgr.logResult).toHaveBeenCalledTimes(1); - expect(logMgr.pass).toHaveBeenCalledTimes(1); - }); - - it('assertion return value not checked if \'returns\' not used', async () => { - await verify(() => { - return 'foo'; - }); - }); -}); - -const testStore: Map = new Map(); \ No newline at end of file diff --git a/packages/aft-core/test/index-spec.ts b/packages/aft-core/test/index-spec.ts index df27d9df..358b62a0 100644 --- a/packages/aft-core/test/index-spec.ts +++ b/packages/aft-core/test/index-spec.ts @@ -20,8 +20,8 @@ describe('AFT', () => { let count: number = 10; let result: boolean = true; for (var i=0; i { + it('gets its logLevel from aftconfig.json', () => { + const aftCfg = new AftConfig({ + logLevel: 'trace' + }); + const logger = new AftLogger(aftCfg); + + expect(logger.logLevel).toEqual('trace'); + }) + + it('will not log or format data at a logLevel below the configured logLevel', () => { + const aftCfg = new AftConfig({ + logLevel: 'warn' + }); + const logger = new AftLogger(aftCfg); + spyOn(logger, 'toConsole').and.callFake((level: LogLevel, message: string) => null); + spyOn(logger, 'format').and.callThrough(); + + logger.log({name: rand.getString(10), level: 'trace', message: 'trace'}); + logger.log({name: rand.getString(10), level: 'debug', message: 'debug'}); + logger.log({name: rand.getString(10), level: 'info', message: 'info'}); + logger.log({name: rand.getString(10), level: 'warn', message: 'warn'}); + logger.log({name: rand.getString(10), level: 'error', message: 'error'}); + + expect(logger.toConsole).toHaveBeenCalledTimes(2); + expect(logger.format).toHaveBeenCalledTimes(2); + }) +}) \ No newline at end of file diff --git a/packages/aft-core/test/plugins/logging/log-level-spec.ts b/packages/aft-core/test/logging/log-level-spec.ts similarity index 96% rename from packages/aft-core/test/plugins/logging/log-level-spec.ts rename to packages/aft-core/test/logging/log-level-spec.ts index 2c589cdd..8d8ec575 100644 --- a/packages/aft-core/test/plugins/logging/log-level-spec.ts +++ b/packages/aft-core/test/logging/log-level-spec.ts @@ -1,4 +1,4 @@ -import { LogLevel } from "../../../src"; +import { LogLevel } from "../../src"; const consoleLog = console.log; diff --git a/packages/aft-core/test/plugins/build-info/aft-build-info-spec.ts b/packages/aft-core/test/plugins/build-info/aft-build-info-spec.ts new file mode 100644 index 00000000..37d90d6e --- /dev/null +++ b/packages/aft-core/test/plugins/build-info/aft-build-info-spec.ts @@ -0,0 +1,64 @@ +import { BuildInfoManager, AftConfig, convert, machineInfo, MachineInfoData, pluginLoader, rand } from "../../../src"; +import { MockBuildInfoPlugin } from "./mock-build-info-plugin"; + +describe('AftBuildInfo', () => { + beforeEach(() => { + pluginLoader.reset(); + }) + + afterEach(() => { + pluginLoader.reset(); + }) + + it('can load expected plugin', async () => { + const randomName = rand.getString(12); + const actual = new BuildInfoManager(new AftConfig({ + pluginNames: ['mock-build-info-plugin'], + MockBuildInfoPluginConfig: { + enabled: true, + buildName: randomName, + buildNumberMin: 100, + buildNumberMax: 999 + } + })); + + expect(actual).toBeDefined(); + expect(actual.plugins.length).toBe(1); + expect(actual.plugins[0].constructor.name).toBe(MockBuildInfoPlugin.name); + expect(actual.plugins[0].enabled).toBe(true); + expect(await actual.plugins[0].buildName()).toEqual(`MockBuildName-${randomName}`); + expect(await actual.plugins[0].buildNumber()).toMatch(/MockBuildNumber-[0-9]{3}/); + }); + + it('will generate a string based on the machine user and name if no BuildInfoPlugin available', async () => { + const mgr: BuildInfoManager = new BuildInfoManager(); + const actual: string = await mgr.get(); + const mi: MachineInfoData = machineInfo.data; + + expect(actual).withContext('is valid string').toBeDefined(); + const safeStr = [{exclude: /[\()\;\\\/\|\<\>""'*&^%$#@!,.\-\+_=\?]/gi, replaceWith: ''}]; + expect(actual).withContext('machineName').toContain(convert.toSafeString(mi.hostname, safeStr).toLocaleUpperCase()); + expect(actual).withContext('machineUser').toContain(convert.toSafeString(mi.user, safeStr).toLocaleUpperCase()); + }); + + it('will generate a string based on the plugin if a BuildInfoPlugin is available', async () => { + const randomName = rand.getString(22); + const mgr: BuildInfoManager = new BuildInfoManager(new AftConfig({ + pluginNames: ['mock-build-info-plugin'], + MockBuildInfoPluginConfig: { + enabled: true, + buildName: randomName, + buildNumberMin: 100, + buildNumberMax: 999 + } + })); + const actual: string = await mgr.get(); + const mi: MachineInfoData = machineInfo.data; + + expect(actual).withContext('is valid string').toBeDefined(); + expect(actual).withContext('machineName').not.toContain(mi.hostname.toLocaleUpperCase()); + expect(actual).withContext('machineUser').not.toContain(mi.user.toLocaleUpperCase()); + expect(actual).withContext('buildName').toContain('MockBuildName-'); + expect(actual).withContext('buildNumber').toContain('MockBuildNumber-'); + }); +}); \ No newline at end of file diff --git a/packages/aft-core/test/plugins/build-info/build-info-manager-spec.ts b/packages/aft-core/test/plugins/build-info/build-info-manager-spec.ts deleted file mode 100644 index ebb8e71a..00000000 --- a/packages/aft-core/test/plugins/build-info/build-info-manager-spec.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { BuildInfoManager, convert, machineInfo, MachineInfoData } from "../../../src"; - -describe('BuildInfoManager', () => { - it('can load a specified BuildInfoPlugin', async () => { - const manager: BuildInfoManager = new BuildInfoManager({ - plugins: ['mock-build-info-plugin'] - }); - const actual = await manager.plugins(); - - expect(actual).toBeDefined(); - expect(actual.length).toBe(1); - expect(actual[0].constructor.name).toBe('MockBuildInfoPlugin'); - expect(actual[0].enabled).toBe(true); - expect(await actual[0].buildName()).toMatch(/MockBuildName-[0-9]{1,2}/); - expect(await actual[0].buildNumber()).toMatch(/MockBuildNumber-[0-9]{3}/); - }); - - it('returns the build name from the first enabled plugin', async () => { - const mgr: BuildInfoManager = new BuildInfoManager({ - plugins: ['mock-build-info-plugin'] - }); - - expect(await mgr.buildName()).toMatch(/MockBuildName-[0-9]{1,2}/); - }); - - it('returns the build number from the first enabled plugin', async () => { - let mgr: BuildInfoManager = new BuildInfoManager({ - plugins: ['mock-build-info-plugin'] - }); - - expect(await mgr.buildNumber()).toMatch(/MockBuildNumber-[0-9]{3}/); - }); - - it('will generate a string based on the machine user and name if no BuildInfoPlugin available', async () => { - const mgr: BuildInfoManager = new BuildInfoManager(); - const actual: string = await mgr.get(); - const mi: MachineInfoData = machineInfo.data; - - expect(actual).withContext('is valid string').toBeDefined(); - const safeStr = [{exclude: /[\()\;\\\/\|\<\>""'*&^%$#@!,.\-\+_=\?]/gi, replaceWith: ''}]; - expect(actual).withContext('machineName').toContain(convert.toSafeString(mi.hostname, safeStr)); - expect(actual).withContext('machineUser').toContain(convert.toSafeString(mi.user, safeStr)); - }); - - it('will generate a string based on the plugin if a BuildInfoPlugin is available', async () => { - const mgr: BuildInfoManager = new BuildInfoManager({ - plugins: ['mock-build-info-plugin'] - }); - const actual: string = await mgr.get(); - const mi: MachineInfoData = machineInfo.data; - - expect(actual).withContext('is valid string').toBeDefined(); - expect(actual).withContext('machineName').not.toContain(mi.hostname); - expect(actual).withContext('machineUser').not.toContain(mi.user); - }); -}); \ No newline at end of file diff --git a/packages/aft-core/test/plugins/build-info/mock-build-info-plugin.ts b/packages/aft-core/test/plugins/build-info/mock-build-info-plugin.ts index f136e543..9aa37cd0 100644 --- a/packages/aft-core/test/plugins/build-info/mock-build-info-plugin.ts +++ b/packages/aft-core/test/plugins/build-info/mock-build-info-plugin.ts @@ -1,19 +1,39 @@ -import { BuildInfoPlugin, BuildInfoPluginOptions, Merge, rand } from "../../../src"; +import { AftConfig, BuildInfoPlugin, PluginConfig, rand } from "../../../src"; -export type MockBuildInfoPluginOptions = Merge; +export class MockBuildInfoPluginConfig extends PluginConfig { + buildName: string; + buildNumberMin: number; + buildNumberMax: number; +}; -export class MockBuildInfoPlugin extends BuildInfoPlugin { - override async buildName(): Promise { - return this.option('buildName', `MockBuildName-${rand.getInt(0, 99)}`); +export class MockBuildInfoPlugin extends BuildInfoPlugin { + private readonly _enabled: boolean; + public override get enabled(): boolean { + return this._enabled; } - override async buildNumber(): Promise { - const min = this.option('buildNumberMin', 100); - const max = this.option('buildNumberMax', 999); - return this.option('buildNumber', `MockBuildNumber-${rand.getInt(min, max)}`); + private readonly _buildName: string; + private readonly _buildNumberMin: number; + private readonly _buildNumberMax: number; + constructor(aftCfg?: AftConfig) { + super(aftCfg); + const cfg = this.aftCfg.getSection(MockBuildInfoPluginConfig); + this._enabled = cfg.enabled ?? false; + if (this.enabled) { + this._buildName = cfg.buildName ?? rand.getString(4, false, true); + this._buildNumberMin = cfg.buildNumberMin ?? 0; + this._buildNumberMax = cfg.buildNumberMax ?? 9999; + } + } + override buildName = async (): Promise => { + if (this.enabled) { + return `MockBuildName-${this._buildName}`; + } + return null; + } + override buildNumber = async (): Promise => { + if (this.enabled) { + return `MockBuildNumber-${rand.getInt(this._buildNumberMin, this._buildNumberMax)}`; + } + return null; } } \ No newline at end of file diff --git a/packages/aft-core/test/plugins/defects/defect-manager-spec.ts b/packages/aft-core/test/plugins/defects/defect-manager-spec.ts deleted file mode 100644 index f062f184..00000000 --- a/packages/aft-core/test/plugins/defects/defect-manager-spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { DefectManager } from "../../../src"; - -describe('DefectManager', () => { - it('can load a specified DefectPlugin implementation', async () => { - const dpm: DefectManager = new DefectManager({ - plugins: ['mock-defect-plugin'] - }); - const actual = await dpm.plugins(); - - expect(actual).withContext('an array of plugins should be returned').toBeDefined(); - expect(actual.length).withContext('there should be at least 1 plugin').toBe(1); - expect(actual[0]).withContext('plugin should be defined').toBeDefined(); - expect(actual[0].constructor.name).withContext('plugin should be instance of MockDefectPlugin').toEqual('MockDefectPlugin'); - }); -}); \ No newline at end of file diff --git a/packages/aft-core/test/plugins/defects/mock-defect-plugin.ts b/packages/aft-core/test/plugins/defects/mock-defect-plugin.ts deleted file mode 100644 index 7dddea02..00000000 --- a/packages/aft-core/test/plugins/defects/mock-defect-plugin.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { DefectStatus, Defect, DefectPlugin, rand, DefectPluginOptions } from "../../../src"; - -export class MockDefectPlugin extends DefectPlugin { - override async getDefect(defectId: string): Promise { - return { - id: defectId, - title: rand.getString(17), - description: rand.getString(150), - status: rand.getFrom('open', 'closed') - } as Defect; - } - override async findDefects(searchTerm: string): Promise { - switch (searchTerm) { - case 'C1234': - let d1: Defect = await this.getDefect('AUTO-123'); - d1.status = 'open'; - return [d1]; - case 'C2345': - let d2: Defect = await this.getDefect('AUTO-234'); - d2.status = 'closed'; - return [d2]; - default: - let defects: Defect[] = []; - let randomCount: number = rand.getInt(1, 5); - for (var i=0; i('open', 'closed') - } as Defect; - defects.push(defect); - } - return defects; - } - } -} \ No newline at end of file diff --git a/packages/aft-core/test/plugins/logging/log-manager-spec.ts b/packages/aft-core/test/plugins/logging/log-manager-spec.ts deleted file mode 100644 index 46895d66..00000000 --- a/packages/aft-core/test/plugins/logging/log-manager-spec.ts +++ /dev/null @@ -1,193 +0,0 @@ -import { TestResult, LogManager, rand, LogMessageData, pluginloader } from "../../../src"; -import { MockLoggingPlugin } from "./mock-logging-plugin"; - -const consoleLog = console.log; -describe('LogManager', () => { - beforeAll(() => { - console.log = function(){}; - }); - - beforeEach(() => { - pluginloader.clear(); - }); - - afterAll(() => { - console.log = consoleLog; - }); - - it('will send logs to any registered LoggingPlugin implementations', async () => { - const logName = 'will send logs to any registered LoggingPlugin implementations'; - const logMgr: LogManager = new LogManager({ - logName: logName, - level: 'trace', - plugins: ['mock-logging-plugin'] - }); - const plugin = await logMgr.first(); - const logs = new Array(); - const logSpy = spyOn(plugin, 'log').and.callFake((message: LogMessageData) => { - logs.push(message); - return Promise.resolve(); - }); - const resultSpy = spyOn(plugin, 'logResult').and.callThrough(); - let messages: string[] = []; - - for (var i=0; i<5; i++) { - let message: string = rand.getString(rand.getInt(10, 30)); - messages.push(message); - await logMgr.trace(message); - await logMgr.debug(message); - await logMgr.step(message); - await logMgr.info(message); - await logMgr.warn(message); - await logMgr.pass(message); - await logMgr.fail(message); - await logMgr.error(message); - await logMgr.log('none', message); - } - expect(logSpy).toHaveBeenCalledTimes(5 * 9); - expect(resultSpy).not.toHaveBeenCalled(); - expect(logs[0].message).toEqual(messages[0]); - expect(logs[logs.length - 1].message).toEqual(messages[messages.length - 1]); - }); - - it('will not output if level set to LogLevel of none', async () => { - const logName = 'will not output if level set to LogLevel of none'; - const logMgr: LogManager = new LogManager({ - logName: logName, - level: 'none', - plugins: [] - }); - const consoleSpy = spyOn(console, 'log').and.callThrough(); - - await logMgr.error('fake error'); - await logMgr.log('none', 'will not be logged'); - - expect(consoleSpy).not.toHaveBeenCalled(); - }); - - it('will send cloned LogMessageData to any registered LoggingPlugin implementations', async () => { - const logName = 'will send cloned LogMessageData to any registered LoggingPlugin implementations'; - const logMgr: LogManager = new LogManager({ - logName: logName, - plugins: ['mock-logging-plugin'] - }); - const plugin = await logMgr.first() as MockLoggingPlugin; - const logs: LogMessageData[] = []; - const logSpy = spyOn(plugin, 'log').and.callFake((message: LogMessageData): Promise => { - logs.push(message); - return Promise.resolve(); - }) - const expected: string = rand.getString(25, true, true, true, true); - await logMgr.log('trace', expected); - - expect(logSpy).toHaveBeenCalledTimes(1); - expect(logs[0].message).toBe(expected); - }); - - it('will send cloned TestResult to any registered LoggingPlugin implementations', async () => { - const logName = 'will send cloned TestResult to any registered LoggingPlugin implementations'; - const logMgr: LogManager = new LogManager({ - logName: logName, - plugins: ['mock-logging-plugin'] - }); - const plugin = await logMgr.first(); - const logSpy = spyOn(plugin, 'log').and.callThrough(); - const results = new Array(); - const names = new Array(); - const resultSpy = spyOn(plugin, 'logResult').and.callFake((logName: string, result: TestResult) => { - names.push(logName); - results.push(result); - return Promise.resolve(); - }); - let result: TestResult = { - testId: 'C' + rand.getInt(1000, 999999), - created: Date.now(), - resultId: rand.guid, - status: 'Untested', - resultMessage: rand.getString(100) - }; - - await logMgr.logResult(result); - - expect(logSpy).not.toHaveBeenCalled(); - expect(resultSpy).toHaveBeenCalledTimes(1); - expect(names[0]).toEqual(logName); - expect(results.length).toEqual(1); - expect(results[0]).not.toBe(result); - expect(results[0].testId).toEqual(result.testId); - expect(results[0].created).toEqual(result.created); - }); - - it('calls LoggingPlugin.dispose on LogManager.dispose', async () => { - const logName = 'calls LoggingPlugin.dispose on LogManager.dispose'; - const logMgr: LogManager = new LogManager({ - logName: logName, - plugins: ['mock-logging-plugin'] - }); - const plugin = await logMgr.first(); - const errors = new Array(); - const names = new Array(); - const disposeSpy = spyOn(plugin, 'dispose').and.callFake((logName: string, message: LogMessageData) => { - names.push(logName); - errors.push(message); - return Promise.resolve(); - }); - await logMgr.info(rand.getString(18)); - - expect(disposeSpy).not.toHaveBeenCalled(); - - const expectedErr = new Error(rand.getString(10, false, false, false, true)); - await logMgr.dispose(expectedErr); - - expect(disposeSpy).toHaveBeenCalledTimes(1); - expect(names[0]).toEqual(logName); - expect(errors[0].message).toEqual(expectedErr.message); - }); - - it('handles exceptions thrown by loaded plugins', async () => { - const logName = 'handles exceptions thrown by loaded plugins'; - const logMgr: LogManager = new LogManager({ - logName: logName, - plugins: ['throws-logging-plugin'] - }); - - expect((await logMgr.first()).constructor.name).toEqual('ThrowsLoggingPlugin'); - expect(async () => await logMgr.log('error', rand.guid)).withContext('log').not.toThrow(); - expect(async () => await logMgr.logResult({created: Date.now(), resultId: rand.guid, status: 'Passed'})).withContext('logResult').not.toThrow(); - expect(async () => await logMgr.dispose()).withContext('dispose').not.toThrow(); - }); - - it('passes manager LogLevel to plugins if not set in PluginConfig', async () => { - const logName = 'passes manager LogLevel to plugins if not set in PluginConfig'; - const logMgr: LogManager = new LogManager({ - logName: logName, - level: 'error', - plugins: ['mock-logging-plugin'] - }); - - const plugin = await logMgr.first(); - - expect(plugin.level).toEqual(logMgr.option('level')); - expect(plugin.enabled).toBe(true); - }); - - it('allows setting config for plugins in their PluginConfig', async () => { - const logName = 'passes manager LogLevel to plugins if not set in PluginConfig'; - const logMgr: LogManager = new LogManager({ - logName: logName, - level: 'error', - plugins: [{ - name: 'mock-logging-plugin', - options: { - level: 'trace', - enabled: false - } - }] - }); - - const plugin = (await logMgr.plugins())[0]; - - expect(plugin.level).toEqual('trace'); - expect(plugin.enabled).toBe(false); - }); -}); \ No newline at end of file diff --git a/packages/aft-core/test/plugins/logging/mock-logging-plugin.ts b/packages/aft-core/test/plugins/logging/mock-logging-plugin.ts deleted file mode 100644 index 665b1155..00000000 --- a/packages/aft-core/test/plugins/logging/mock-logging-plugin.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { LoggingPlugin, TestResult, LogMessageData, Merge, LoggingPluginOptions } from "../../../src"; - -export type MockLoggingPluginOptions = Merge; - -export class MockLoggingPlugin extends LoggingPlugin { - override async log(message: LogMessageData): Promise { - return Promise.resolve(); - } - override async logResult(name: string, result: TestResult): Promise { - return Promise.resolve(); - } - override async dispose(name: string, error?: Error): Promise { - return Promise.resolve(); - } -} \ No newline at end of file diff --git a/packages/aft-core/test/plugins/logging/throws-logging-plugin.ts b/packages/aft-core/test/plugins/logging/throws-logging-plugin.ts deleted file mode 100644 index ab363e76..00000000 --- a/packages/aft-core/test/plugins/logging/throws-logging-plugin.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { LoggingPlugin, TestResult, LogMessageData, LoggingPluginOptions } from "../../../src"; - -export class ThrowsLoggingPlugin extends LoggingPlugin { - override async log(messageData: LogMessageData): Promise { - throw 'log exception'; - } - override async logResult(name: string, result: TestResult): Promise { - throw 'logResult exception'; - } - override async dispose(name: string, error?: Error): Promise { - throw 'dispose exception'; - } -} \ No newline at end of file diff --git a/packages/aft-core/test/plugins/mock-plugin.ts b/packages/aft-core/test/plugins/mock-plugin.ts new file mode 100644 index 00000000..1c870fd0 --- /dev/null +++ b/packages/aft-core/test/plugins/mock-plugin.ts @@ -0,0 +1,16 @@ +import { AftConfig, Plugin, PluginConfig } from "../../src"; + +export class MockPluginConfig extends PluginConfig {} + +export class MockPlugin extends Plugin { + private readonly _enabled: boolean; + public override get enabled(): boolean { + return this._enabled; + } + public readonly implements: string = 'mock'; + constructor(aftCfg?: AftConfig) { + super(aftCfg); + const cfg = this.aftCfg.getSection(MockPluginConfig); + this._enabled = cfg.enabled; + } +} \ No newline at end of file diff --git a/packages/aft-core/test/plugins/plugin-loader-spec.ts b/packages/aft-core/test/plugins/plugin-loader-spec.ts new file mode 100644 index 00000000..a6faf81b --- /dev/null +++ b/packages/aft-core/test/plugins/plugin-loader-spec.ts @@ -0,0 +1,25 @@ +import { AftConfig, Plugin, pluginLoader } from "../../src" +import { MockPlugin } from "./mock-plugin"; + +describe('PluginLoader', () => { + beforeEach(() => { + pluginLoader.reset(); + }) + + afterEach(() => { + pluginLoader.reset(); + }) + + it('can load a class implementing IPlugin', () => { + const plugins = pluginLoader.getPluginsByType(Plugin, new AftConfig({ + pluginNames: ['mock-plugin'], + MockPluginConfig: { + enabled: true + } + })); + + expect(plugins.length).toBe(1); + expect(plugins[0].constructor.name).toEqual(MockPlugin.name); + expect(plugins[0].enabled).toBeTrue(); + }) +}) \ No newline at end of file diff --git a/packages/aft-core/test/plugins/reporting/mock-reporting-plugin.ts b/packages/aft-core/test/plugins/reporting/mock-reporting-plugin.ts new file mode 100644 index 00000000..2c62a735 --- /dev/null +++ b/packages/aft-core/test/plugins/reporting/mock-reporting-plugin.ts @@ -0,0 +1,31 @@ +import { ReportingPlugin, LogLevel, AftConfig, ReportingPluginConfig, TestResult } from "../../../src"; + +export class MockReportingPluginConfig extends ReportingPluginConfig { + mockConfigKey: string; +}; + +export class MockReportingPlugin extends ReportingPlugin { + public readonly results = new Array(); + private readonly _level: LogLevel; + public override get logLevel(): LogLevel { + return this._level; + } + constructor(aftCfg?: AftConfig) { + super(aftCfg); + var cfg = this.aftCfg.getSection(MockReportingPluginConfig); + this._level = cfg.logLevel ?? this.aftCfg.logLevel ?? 'warn'; + } + override initialise = async (logName: string): Promise => { + return Promise.resolve(); + } + override log = async (name: string, level: LogLevel, message: string, ): Promise => { + return Promise.resolve(); + } + override submitResult = async (name: string, result: TestResult): Promise => { + this.results.push(result); + return Promise.resolve(); + } + override finalise = async (name: string, error?: Error): Promise => { + return Promise.resolve(); + } +} \ No newline at end of file diff --git a/packages/aft-core/test/plugins/reporting/reporter-spec.ts b/packages/aft-core/test/plugins/reporting/reporter-spec.ts new file mode 100644 index 00000000..68c46eae --- /dev/null +++ b/packages/aft-core/test/plugins/reporting/reporter-spec.ts @@ -0,0 +1,201 @@ +import { Reporter, rand, LogMessageData, pluginLoader, AftConfig, LogLevel, TestResult } from "../../../src"; +import { MockReportingPlugin } from "./mock-reporting-plugin"; + +const consoleLog = console.log; +describe('Reporter', () => { + beforeAll(() => { + console.log = function(){}; + }); + + beforeEach(() => { + pluginLoader.reset(); + }); + + afterEach(() => { + pluginLoader.reset(); + }); + + afterAll(() => { + console.log = consoleLog; + }); + + it('will send logs to any registered ReportingPlugin implementations', async () => { + const reporterName = 'will send logs to any registered ReportingPlugin implementations'; + const reporter: Reporter = new Reporter(reporterName, new AftConfig({ + logLevel: 'trace', + pluginNames: ['mock-reporting-plugin'] + })); + const plugin = reporter.plugins.find(p => p?.enabled); + const logs = new Array(); + const logSpy = spyOn(plugin, 'log').and.callFake((name: string, level: LogLevel, message: string, ...data: any[]) => { + logs.push({name, level, message}); + return Promise.resolve(); + }); + let messages: string[] = []; + + for (var i=0; i<5; i++) { + let message: string = rand.getString(rand.getInt(10, 30)); + messages.push(message); + await reporter.trace(message); + await reporter.debug(message); + await reporter.step(message); + await reporter.info(message); + await reporter.warn(message); + await reporter.pass(message); + await reporter.fail(message); + await reporter.error(message); + await reporter.log('none', message); + } + expect(logSpy).toHaveBeenCalledTimes(5 * 9); + expect(logs[0].message).toEqual(messages[0]); + expect(logs[logs.length - 1].message).toEqual(messages[messages.length - 1]); + }); + + it('will not output if level set to LogLevel of none', async () => { + const reporterName = 'will not output if level set to LogLevel of none'; + const reporter: Reporter = new Reporter(reporterName, new AftConfig({ + logLevel: 'none', + pluginNames: [] + })); + const consoleSpy = spyOn(console, 'log').and.callThrough(); + + await reporter.error('fake error'); + await reporter.log('none', 'will not be logged'); + + expect(consoleSpy).not.toHaveBeenCalled(); + }); + + it('will send cloned LogMessageData to any registered ReportingPlugin implementations', async () => { + const reporterName = 'will send cloned LogMessageData to any registered ReportingPlugin implementations'; + const reporter = new Reporter(reporterName, new AftConfig({ + pluginNames: ['mock-reporting-plugin'], + logLevel: 'trace' + })); + const plugin = reporter.plugins.find(p => p.enabled) as MockReportingPlugin; + const logs: LogMessageData[] = []; + const logSpy = spyOn(plugin, 'log').and.callFake((name: string, level: LogLevel, message: string, ...data: any[]): Promise => { + logs.push({name, level, message, args: data}); + return Promise.resolve(); + }) + const expected: string = rand.getString(25, true, true, true, true); + await reporter.log('trace', expected); + + expect(logSpy).toHaveBeenCalledTimes(1); + expect(logs[0].message).toBe(expected); + }); + + it('calls ReportingPlugin.finalise on logger.dispose', async () => { + const reporterName = 'calls ReportingPlugin.finalise on logger.dispose'; + const reporter = new Reporter(reporterName, new AftConfig({ + pluginNames: ['mock-reporting-plugin'], + logLevel: 'trace' + })); + const plugin = reporter.plugins.find(p => p.enabled); + const errors = new Array(); + const names = new Array(); + const disposeSpy = spyOn(plugin, 'finalise').and.callFake((logName: string) => { + names.push(logName); + return Promise.resolve(); + }); + await reporter.info(rand.getString(18)); + + expect(disposeSpy).not.toHaveBeenCalled(); + + const expectedErr = new Error(rand.getString(10, false, false, false, true)); + await reporter.dispose(expectedErr); + + expect(disposeSpy).toHaveBeenCalledTimes(1); + expect(names[0]).toEqual(reporterName); + }); + + it('handles exceptions thrown by loaded plugins', async () => { + const reporterName = 'handles exceptions thrown by loaded plugins'; + const reporter = new Reporter(reporterName, new AftConfig({ + pluginNames: ['mock-reporting-plugin', 'throws-reporting-plugin'] + })); + + expect(async () => await reporter.log('error', rand.guid)).withContext('log').not.toThrow(); + expect(async () => await reporter.dispose()).withContext('dispose').not.toThrow(); + }); + + it('passes manager LogLevel to plugins if not set in PluginConfig', () => { + const reporterName = 'passes manager LogLevel to plugins if not set in PluginConfig'; + const reporter: Reporter = new Reporter(reporterName, new AftConfig({ + logLevel: 'error', + pluginNames: ['mock-reporting-plugin'] + })); + + expect(reporter.plugins.length).withContext('expect at least 1 loaded plugin').toBeGreaterThan(0); + const plugin = reporter.plugins[0]; + + expect(plugin.logLevel).toEqual(reporter.logLevel); + expect(plugin.enabled).withContext('expect plugin to be enabled').toBe(true); + }); + + it('allows setting config for plugins in their PluginConfig', async () => { + const reporterName = 'passes manager LogLevel to plugins if not set in PluginConfig'; + const reporter: Reporter = new Reporter(reporterName, new AftConfig({ + logLevel: 'error', + pluginNames: ['mock-reporting-plugin'], + MockReportingPluginConfig: { + logLevel: 'trace' + } + })); + + const plugin = reporter.plugins[0]; + + expect(plugin.logLevel).toEqual('trace'); + expect(plugin.enabled).toBe(true); + }); + + it('will not call any plugin methods if plugin is not enabled', async () => { + const logName = 'will not call any plugin methods if plugin is not enabled'; + const reporter: Reporter = new Reporter(logName, new AftConfig({ + pluginNames: ['mock-reporting-plugin'], + MockReportingPluginConfig: { + logLevel: 'none' + } + })); + + const plugin = reporter.plugins[0]; + const initSpy = spyOn(plugin, 'initialise'); + const logSpy = spyOn(plugin, 'log'); + const finSpy = spyOn(plugin, 'finalise'); + + await reporter.log('error', rand.getString(33)); + reporter.dispose(); + + expect(initSpy).not.toHaveBeenCalled(); + expect(logSpy).not.toHaveBeenCalled(); + expect(finSpy).not.toHaveBeenCalled(); + }) + + it('sends cloned results to all loaded and enabled plugins', () => { + const name = rand.getString(12); + const reporter = new Reporter(name, new AftConfig({ + pluginNames: ['mock-reporting-plugin'], + MockReportingPluginConfig: { + logLevel: 'trace' + } + })); + const result: TestResult = { + created: Date.now(), + resultId: rand.guid, + status: 'passed', + testId: rand.guid, + testName: name + } + reporter.submitResult(result); + + expect(reporter.plugins.length).toBe(1); + expect(reporter.plugins[0].constructor.name).toEqual(MockReportingPlugin.name); + expect(reporter.plugins[0].enabled).toBeTrue(); + expect((reporter.plugins[0] as MockReportingPlugin).results.length).toBe(1); + expect((reporter.plugins[0] as MockReportingPlugin).results[0].testId).toEqual(result.testId); + + const origName = result.testName; + result.testName = rand.guid; + expect((reporter.plugins[0] as MockReportingPlugin).results[0].testName).toEqual(origName); + expect((reporter.plugins[0] as MockReportingPlugin).results[0].testName).not.toEqual(result.testName); + }) +}); \ No newline at end of file diff --git a/packages/aft-core/test/plugins/reporting/throws-reporting-plugin.ts b/packages/aft-core/test/plugins/reporting/throws-reporting-plugin.ts new file mode 100644 index 00000000..4a23494a --- /dev/null +++ b/packages/aft-core/test/plugins/reporting/throws-reporting-plugin.ts @@ -0,0 +1,19 @@ +import { ReportingPlugin, LogLevel, AftConfig, TestResult } from "../../../src"; + +export class ThrowsReportingPlugin extends ReportingPlugin { + constructor(aftCfg?: AftConfig) { + super(aftCfg); + } + override initialise = async (logName: string): Promise => { + throw 'initialise exception'; + } + override log = async (name: string, level: LogLevel, message: string, ...data: any[]): Promise => { + throw 'log exception'; + } + override submitResult = async (name: string, result: TestResult): Promise => { + throw 'submitResult exception'; + } + override finalise = async (name: string, error?: Error): Promise => { + throw 'dispose exception'; + } +} \ No newline at end of file diff --git a/packages/aft-core/test/plugins/test-cases/mock-test-case-plugin.ts b/packages/aft-core/test/plugins/test-cases/mock-test-case-plugin.ts deleted file mode 100644 index 55df4244..00000000 --- a/packages/aft-core/test/plugins/test-cases/mock-test-case-plugin.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { rand, TestStatus, TestCase, TestCasePlugin, TestCasePluginOptions } from "../../../src"; - -export type MockTestCasePluginOptions = TestCasePluginOptions; - -export class MockTestCasePlugin extends TestCasePlugin { - override async getTestCase(testId: string): Promise { - return { - id: testId, - title: rand.getString(8), - description: rand.getString(100), - status: rand.getFrom('Blocked', 'Failed', 'Passed', 'Retest', 'Skipped', 'Untested') - } as TestCase; - } - override async findTestCases(searchTerm: string): Promise { - let cases: TestCase[] = []; - let resultCount: number = rand.getInt(1, 5); - for (var i=0; i('Blocked', 'Failed', 'Passed', 'Retest', 'Skipped', 'Untested') - } as TestCase; - cases.push(c); - } - return cases; - } - override async shouldRun(testId: string): Promise { - switch(testId) { - case 'C1234': - let c1: TestCase = await this.getTestCase(testId); - return false; - case 'C2345': - let c2: TestCase = await this.getTestCase(testId); - return true; - default: - let c3: TestCase = await this.getTestCase(testId); - return rand.boolean; - } - } -} \ No newline at end of file diff --git a/packages/aft-core/test/plugins/test-cases/test-case-manager-spec.ts b/packages/aft-core/test/plugins/test-cases/test-case-manager-spec.ts deleted file mode 100644 index 393721ce..00000000 --- a/packages/aft-core/test/plugins/test-cases/test-case-manager-spec.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { TestCasePlugin, TestCaseManager } from "../../../src"; - -describe('TestCaseManager', () => { - it('can load a specified TestCasePlugin', async () => { - let tcm: TestCaseManager = new TestCaseManager({ - plugins: ['mock-test-case-plugin'] - }); - let actual = await tcm.plugins(); - - expect(actual).toBeDefined(); - expect(actual.length).withContext('plugins array length').toBe(1); - expect(actual[0]).toBeDefined(); - expect(actual[0].constructor.name).withContext('plugin should be instance of MockTestCasePlugin').toEqual('MockTestCasePlugin'); - }); - - describe('shouldRun', () => { - it('returns true if no plugins found or loaded', async () => { - let tcm = new TestCaseManager(); - const plugins = await tcm.plugins(); - expect(plugins.length).toBe(0); - - const actual: boolean = await tcm.shouldRun('C1234'); - - expect(actual).toBe(true); - }); - }); -}); \ No newline at end of file diff --git a/packages/aft-core/test/plugins/test-execution-policy/mock-test-execution-policy-plugin.ts b/packages/aft-core/test/plugins/test-execution-policy/mock-test-execution-policy-plugin.ts new file mode 100644 index 00000000..4a78f854 --- /dev/null +++ b/packages/aft-core/test/plugins/test-execution-policy/mock-test-execution-policy-plugin.ts @@ -0,0 +1,28 @@ +import { TestExecutionPolicyPlugin, AftConfig, ProcessingResult } from "../../../src"; + +export class MockTestExecutionPolicyPluginConfig { + enabled: boolean = false; + expectedResults: Map> = new Map>(); +} + +export class MockTestExecutionPolicyPlugin extends TestExecutionPolicyPlugin { + private readonly _enabled: boolean; + public override get enabled(): boolean { + return this._enabled; + } + private readonly _tests: Map>; + constructor(aftCfg?: AftConfig) { + super(aftCfg); + const cfg = this.aftCfg.getSection(MockTestExecutionPolicyPluginConfig); + this._enabled = cfg.enabled ?? false; + if (this.enabled) { + this._tests = cfg.expectedResults ?? new Map>(); + } + } + override shouldRun = async (testId: string): Promise> => { + if (this.enabled) { + return this._tests.get(testId) ?? {result: false, message: `${testId} is not in known set of tests`}; + } + return {result: true}; + } +} \ No newline at end of file diff --git a/packages/aft-core/test/plugins/test-execution-policy/test-execution-policy-manager-spec.ts b/packages/aft-core/test/plugins/test-execution-policy/test-execution-policy-manager-spec.ts new file mode 100644 index 00000000..9c11415f --- /dev/null +++ b/packages/aft-core/test/plugins/test-execution-policy/test-execution-policy-manager-spec.ts @@ -0,0 +1,53 @@ +import { AftConfig, TestExecutionPolicyManager, ProcessingResult, pluginLoader } from "../../../src"; +import { MockTestExecutionPolicyPlugin } from "./mock-test-execution-policy-plugin"; + +describe('TestExecutionPolicyManager', () => { + beforeEach(() => { + pluginLoader.reset(); + }) + + afterEach(() => { + pluginLoader.reset(); + }) + + it('can load a specified TestExecutionPolicyPlugin', async () => { + let tcm: TestExecutionPolicyManager = new TestExecutionPolicyManager(new AftConfig({ + pluginNames: ['mock-test-execution-policy-plugin'], + MockTestExecutionPolicyPluginConfig: { + enabled: true + } + })); + let actual = tcm.plugins; + + expect(actual).toBeDefined(); + expect(actual.length).withContext('plugins array length').toBe(1); + expect(actual[0]).toBeDefined(); + expect(actual[0].constructor.name).withContext('plugin should be instance of MockTestExecutionPolicyPlugin').toEqual(MockTestExecutionPolicyPlugin.name); + }); + + describe('shouldRun', () => { + it('returns true if no plugins found or loaded', async () => { + let tcm = new TestExecutionPolicyManager(); + const plugins = tcm.plugins; + expect(plugins.length).toBe(0); + + const actual: ProcessingResult = await tcm.shouldRun('C1234'); + + expect(actual.result).toBe(true); + }); + + it('returns true if no enabled plugins found', async () => { + pluginLoader.reset(); + let tcm: TestExecutionPolicyManager = new TestExecutionPolicyManager(new AftConfig({ + pluginNames: ['mock-test-execution-policy-plugin'] + })); + let plugins = tcm.plugins; + expect(plugins.length).toBe(1); + expect(plugins[0].constructor.name).toEqual(MockTestExecutionPolicyPlugin.name); + + const actual: ProcessingResult = await tcm.shouldRun('C1234'); + + expect(actual.result).toBe(true); + }) + }); +}); \ No newline at end of file diff --git a/packages/aft-core/test/helpers/verifier-matcher-spec.ts b/packages/aft-core/test/verification/verifier-matcher-spec.ts similarity index 97% rename from packages/aft-core/test/helpers/verifier-matcher-spec.ts rename to packages/aft-core/test/verification/verifier-matcher-spec.ts index 425cf8fe..d677f2fb 100644 --- a/packages/aft-core/test/helpers/verifier-matcher-spec.ts +++ b/packages/aft-core/test/verification/verifier-matcher-spec.ts @@ -1,4 +1,4 @@ -import { between, containing, equaling, exactly, greaterThan, havingValue, lessThan, not } from "../../src/helpers/verifier-matcher"; +import { between, containing, equaling, exactly, greaterThan, havingValue, lessThan, not } from "../../src"; describe('VerifierMatcher', () => { describe('Equaling', () => { diff --git a/packages/aft-core/test/verification/verifier-spec.ts b/packages/aft-core/test/verification/verifier-spec.ts new file mode 100644 index 00000000..82d4ddb3 --- /dev/null +++ b/packages/aft-core/test/verification/verifier-spec.ts @@ -0,0 +1,223 @@ +import { Reporter, rand, TestExecutionPolicyManager, Verifier, verify, TestResult, LogLevel, ProcessingResult, AftConfig, pluginLoader, containing, equaling } from "../../src"; + +var consoleLog = console.log; +describe('Verifier', () => { + /* comment `beforeAll` and `afterAll` out to see actual test output */ + beforeAll(() => { + console.log = function(){}; + }); + + afterAll(() => { + console.log = consoleLog; + }); + + beforeEach(() => { + testStore.clear(); + }); + + it('uses "description" as reporter name if provided', async () => { + let description: string = rand.getString(22); + await verify(async (v: Verifier) => { + expect(v.reporter.reporterName).toEqual(description); + }) + .withDescription(description); + }); + + it('uses "test case IDs" as reporter name if no description provided', async () => { + const peMgr = new TestExecutionPolicyManager(); + spyOn(peMgr, 'shouldRun').and.callFake((testId: string): Promise> => { + return Promise.resolve({result: true}); + }); + + await verify(async (v: Verifier) => { + expect(v.reporter.reporterName).toEqual('C1234_C2345'); + }) + .withTestIds('C1234','C2345') + .internals.usingTestExecutionPolicyManager(peMgr); + }); + + it('can execute a passing expectation', async () => { + const reporter = new Reporter('can execute a passing expectation'); + spyOn(reporter, 'submitResult').and.callFake((result: TestResult) => Promise.resolve()); + spyOn(reporter, 'log').and.callFake((level: LogLevel, message: string) => Promise.resolve()); + spyOn(reporter, 'pass').and.callThrough(); + const peMgr = new TestExecutionPolicyManager(); + spyOn(peMgr, 'shouldRun').and.callFake((testId: string): Promise> => { + return Promise.resolve({result: true}); + }); + + await verify(async (v: Verifier) => 'foo') + .returns('foo') + .internals.usingReporter(reporter) + .internals.usingTestExecutionPolicyManager(peMgr) + .and.withDescription('true should be true') + .and.withTestIds('C1234','C2345'); + + expect(peMgr.shouldRun).toHaveBeenCalledTimes(2); + expect(reporter.submitResult).toHaveBeenCalledTimes(2); + expect(reporter.pass).toHaveBeenCalledTimes(2); + }); + + it('accepts a VerifierMatcher in the returns function', async () => { + const reporter = new Reporter('accepts a VerifierMatcher in the returns function'); + spyOn(reporter, 'submitResult').and.callFake((result: TestResult) => Promise.resolve()); + spyOn(reporter, 'log').and.callFake((level: LogLevel, message: string) => Promise.resolve()); + spyOn(reporter, 'pass').and.callThrough(); + const peMgr = new TestExecutionPolicyManager(); + spyOn(peMgr, 'shouldRun').and.callFake((testId: string): Promise> => { + return Promise.resolve({result: true}); + }); + + await verify(async (v: Verifier) => ['foo', 'bar', 'baz']) + .returns(containing('bar')) + .internals.usingReporter(reporter) + .internals.usingTestExecutionPolicyManager(peMgr) + .and.withDescription('array contains "bar"') + .and.withTestIds('C1234','C2345'); + + expect(peMgr.shouldRun).toHaveBeenCalledTimes(2); + expect(reporter.submitResult).toHaveBeenCalledTimes(2); + expect(reporter.pass).toHaveBeenCalledTimes(2); + }); + + it('throws on exception in assertion', async () => { + const reporter = new Reporter('throws on exception in assertion'); + spyOn(reporter, 'submitResult').and.callFake((result: TestResult) => Promise.resolve()); + spyOn(reporter, 'log').and.callFake((level: LogLevel, message: string) => Promise.resolve()); + spyOn(reporter, 'fail').and.callThrough(); + const peMgr = new TestExecutionPolicyManager(); + spyOn(peMgr, 'shouldRun').and.callFake((testId: string): Promise> => { + return Promise.resolve({result: true}); + }); + + try { + await verify(() => { + throw new Error('fake error'); + }) + .internals.usingReporter(reporter) + .internals.usingTestExecutionPolicyManager(peMgr) + .withDescription('true should be true') + .and.withTestIds('C1234').and.withTestIds('C2345'); + + expect(true).toBe(false); // force failure + } catch (e) { + expect(e.toString()).toEqual('Error: fake error'); + } + + expect(peMgr.shouldRun).toHaveBeenCalledTimes(2); + expect(reporter.submitResult).toHaveBeenCalledTimes(2); + expect(reporter.fail).toHaveBeenCalledTimes(2); + }); + + it('throws on failed comparison with expected result', async () => { + const reporter = new Reporter('throws on failed comparison with expected result'); + spyOn(reporter, 'submitResult').and.callFake((result: TestResult) => Promise.resolve()); + spyOn(reporter, 'log').and.callFake((level: LogLevel, message: string) => Promise.resolve()); + spyOn(reporter, 'fail').and.callThrough(); + const peMgr = new TestExecutionPolicyManager(); + spyOn(peMgr, 'shouldRun').and.callFake((testId: string): Promise> => { + return Promise.resolve({result: true}); + }); + + try { + await verify(() => true) + .returns(false) + .internals.usingReporter(reporter) + .internals.usingTestExecutionPolicyManager(peMgr) + .and.withDescription('failure expected due to true not being false') + .and.withTestIds('C1234').and.withTestIds('C2345'); + + expect('foo').toBe('bar'); // force failure + } catch (e) { + expect(e.toString()).toEqual(equaling(false).setActual(true).failureString()); + } + + expect(peMgr.shouldRun).toHaveBeenCalledTimes(2); + expect(reporter.submitResult).toHaveBeenCalledTimes(2); + expect(reporter.fail).toHaveBeenCalledTimes(2); + }); + + it('will not execute expectation if TestExecutionPolicyManager says should not run for all cases', async () => { + const reporter = new Reporter('will not execute expectation if TestExecutionPolicyManager says should not run for all cases'); + spyOn(reporter, 'submitResult').and.callFake((result: TestResult) => Promise.resolve()); + spyOn(reporter, 'log').and.callFake((level: LogLevel, message: string) => Promise.resolve()); + spyOn(reporter, 'warn').and.callThrough(); + const peMgr = new TestExecutionPolicyManager(); + spyOn(peMgr, 'shouldRun').and.callFake((testId: string): Promise> => { + return Promise.resolve({result: false}); + }); + + await verify(() => { + testStore.set('executed', true); + }) + .internals.usingReporter(reporter) + .internals.usingTestExecutionPolicyManager(peMgr) + .and.withTestIds('C1234','C2345'); + + expect(peMgr.shouldRun).toHaveBeenCalledTimes(2); + expect(testStore.has('executed')).toBeFalse(); + expect(reporter.submitResult).toHaveBeenCalledTimes(2); + expect(reporter.warn).toHaveBeenCalledTimes(2); + }); + + it('will execute expectation if TestExecutionPolicyManager says any cases should be run', async () => { + const reporter = new Reporter('will execute expectation if TestExecutionPolicyManager says any cases should be run'); + spyOn(reporter, 'submitResult').and.callFake((result: TestResult) => Promise.resolve()); + spyOn(reporter, 'log').and.callFake((level: LogLevel, message: string) => Promise.resolve()); + spyOn(reporter, 'pass').and.callThrough(); + const peMgr = new TestExecutionPolicyManager(); + spyOn(peMgr, 'shouldRun').and.callFake((testId: string): Promise> => { + if (testId == 'C1234') { + return Promise.resolve({result: false, message: 'do not run C1234'}); + } else { + return Promise.resolve({result: true}); + } + }); + + await verify(() => { + testStore.set('executed', true); + }) + .internals.usingReporter(reporter) + .internals.usingTestExecutionPolicyManager(peMgr) + .and.withTestIds('C1234','C2345'); + + expect(peMgr.shouldRun).toHaveBeenCalledWith('C1234'); + expect(peMgr.shouldRun).toHaveBeenCalledWith('C2345'); + expect(testStore.has('executed')).toBeTrue(); + expect(reporter.submitResult).toHaveBeenCalledTimes(2); + expect(reporter.pass).toHaveBeenCalledTimes(2); + }); + + it('will not execute expectation if no associated testIds and TestExecutionPolicyManager has enabled plugins', async () => { + const reporter = new Reporter('will not execute expectation if no associated testIds and TestExecutionPolicyManager has enabled plugins'); + spyOn(reporter, 'submitResult').and.callFake((result: TestResult) => Promise.resolve()); + spyOn(reporter, 'log').and.callFake((level: LogLevel, message: string) => Promise.resolve()); + spyOn(reporter, 'warn').and.callThrough(); + pluginLoader.reset(); + const peMgr = new TestExecutionPolicyManager(new AftConfig({ + pluginNames: ['mock-test-execution-policy-plugin'], + MockTestExecutionPolicyPluginConfig: { + enabled: true + } + })); + + await verify(() => { + testStore.set('executed', true); + }) + .internals.usingReporter(reporter) + .internals.usingTestExecutionPolicyManager(peMgr); + + expect(peMgr.plugins.length).toEqual(1); + expect(testStore.has('executed')).toBeFalse(); + expect(reporter.submitResult).toHaveBeenCalledTimes(1); + expect(reporter.warn).toHaveBeenCalledTimes(1); + }); + + it('assertion return value not checked if "returns" not used', async () => { + await verify(() => { + return 'foo'; + }); + }); +}); + +const testStore: Map = new Map(); \ No newline at end of file diff --git a/packages/aft-core/tsconfig.tsbuildinfo b/packages/aft-core/tsconfig.tsbuildinfo index 4c01199a..2cc8398c 100644 --- a/packages/aft-core/tsconfig.tsbuildinfo +++ b/packages/aft-core/tsconfig.tsbuildinfo @@ -211,7 +211,7 @@ "signature": "d15aa4b304f02574b4213cd59da4d0fac666764d52d495a8d736d7c4ed9d3a64", "affectsGlobalScope": false }, - "./src/plugins/logging/abstract-logging-plugin.ts": { + "./src/plugins/logging/abstract-reporting-plugin.ts": { "version": "1e99291aae42f095eba90f5fffadcac0bf26991bbfe6ab9e91f383a95aed0edc", "signature": "55e9d5946701fecc14a73ff28a447fb4ad6bfcac3bbd90867036795daad92161", "affectsGlobalScope": false @@ -301,7 +301,7 @@ "signature": "a17e831d16c27cbe4d6f0bb238c1ded0d4a26c282009e431c68733be0b792f4f", "affectsGlobalScope": true }, - "./src/plugins/logging/console-logging-plugin.ts": { + "./src/plugins/logging/console-reporting-plugin.ts": { "version": "9d197d6bfc56b1babc057b934c7ab58a0b00115e71b6f1ed108dcda547c0ca31", "signature": "ee01a1f1cba211c640ad1f8325cec55a362b979c7cc48805e0f65af1bad09b10", "affectsGlobalScope": false @@ -311,12 +311,12 @@ "signature": "93da6e20ede459aea80c271457a033c0c32709ae00d4da6fd26f37b2b6a95302", "affectsGlobalScope": false }, - "./src/plugins/test-cases/abstract-test-case-plugin.ts": { + "./src/plugins/test-cases/abstract-test-execution-policy-plugin.ts": { "version": "976edf4bd15f400d069ce4a4456a7338c0c713f9c856faded85e10c6feb94dfa", "signature": "4fd96cfa9844c789bcaf697684dee4cb394aa7584259861b5fb448ad11f77afb", "affectsGlobalScope": false }, - "./src/plugins/test-cases/test-case-plugin-manager.ts": { + "./src/plugins/test-cases/test-execution-policy-plugin-manager.ts": { "version": "ace96968030a00718e6477ffb1ebf042676b2ee918f04d04e944115cd2f5b0bd", "signature": "03432fb7ba12653e228986044d8619a7d2623d66242b32b5f497083f73ce3690", "affectsGlobalScope": false @@ -921,16 +921,16 @@ "./src/plugins/defects/defect-plugin-manager.ts", "./src/plugins/defects/defect-status.ts", "./src/plugins/defects/idefect.ts", - "./src/plugins/logging/abstract-logging-plugin.ts", - "./src/plugins/logging/console-logging-plugin.ts", + "./src/plugins/logging/abstract-reporting-plugin.ts", + "./src/plugins/logging/console-reporting-plugin.ts", "./src/plugins/logging/format-options.ts", "./src/plugins/logging/logging-level.ts", "./src/plugins/logging/logging-plugin-manager.ts", "./src/plugins/plugin-loader.ts", - "./src/plugins/test-cases/abstract-test-case-plugin.ts", + "./src/plugins/test-cases/abstract-test-execution-policy-plugin.ts", "./src/plugins/test-cases/itest-case.ts", "./src/plugins/test-cases/itest-result.ts", - "./src/plugins/test-cases/test-case-plugin-manager.ts", + "./src/plugins/test-cases/test-execution-policy-plugin-manager.ts", "./src/plugins/test-cases/test-exception.ts", "./src/plugins/test-cases/test-status.ts", "./src/wrappers/should.ts", @@ -971,17 +971,17 @@ "./src/plugins/defects/idefect.ts": [ "./src/plugins/defects/defect-status.ts" ], - "./src/plugins/logging/abstract-logging-plugin.ts": [ + "./src/plugins/logging/abstract-reporting-plugin.ts": [ "../../node_modules/ts-simple-nameof/index.d.ts", "./src/helpers/random-generator.ts", "./src/plugins/abstract-plugin.ts", "./src/plugins/logging/logging-level.ts", "./src/plugins/test-cases/itest-result.ts" ], - "./src/plugins/logging/console-logging-plugin.ts": [ + "./src/plugins/logging/console-reporting-plugin.ts": [ "../../node_modules/colors/index.d.ts", "../../node_modules/ts-simple-nameof/index.d.ts", - "./src/plugins/logging/abstract-logging-plugin.ts", + "./src/plugins/logging/abstract-reporting-plugin.ts", "./src/plugins/logging/logging-level.ts", "./src/plugins/test-cases/itest-result.ts" ], @@ -993,7 +993,7 @@ "./src/helpers/converter.ts", "./src/helpers/random-generator.ts", "./src/plugins/abstract-plugin-manager.ts", - "./src/plugins/logging/abstract-logging-plugin.ts", + "./src/plugins/logging/abstract-reporting-plugin.ts", "./src/plugins/logging/format-options.ts", "./src/plugins/logging/logging-level.ts", "./src/plugins/test-cases/itest-result.ts" @@ -1003,7 +1003,7 @@ "../../node_modules/@types/node/path.d.ts", "./src/plugins/abstract-plugin.ts" ], - "./src/plugins/test-cases/abstract-test-case-plugin.ts": [ + "./src/plugins/test-cases/abstract-test-execution-policy-plugin.ts": [ "./src/helpers/processing-result.ts", "./src/plugins/abstract-plugin.ts", "./src/plugins/test-cases/itest-case.ts" @@ -1016,12 +1016,12 @@ "./src/plugins/defects/idefect.ts", "./src/plugins/test-cases/test-status.ts" ], - "./src/plugins/test-cases/test-case-plugin-manager.ts": [ + "./src/plugins/test-cases/test-execution-policy-plugin-manager.ts": [ "../../node_modules/ts-simple-nameof/index.d.ts", "./src/helpers/processing-result.ts", "./src/plugins/abstract-plugin-manager.ts", "./src/plugins/logging/logging-plugin-manager.ts", - "./src/plugins/test-cases/abstract-test-case-plugin.ts", + "./src/plugins/test-cases/abstract-test-execution-policy-plugin.ts", "./src/plugins/test-cases/itest-case.ts" ], "./src/plugins/test-cases/test-exception.ts": [ @@ -1043,7 +1043,7 @@ "./src/plugins/defects/idefect.ts", "./src/plugins/logging/logging-plugin-manager.ts", "./src/plugins/test-cases/itest-result.ts", - "./src/plugins/test-cases/test-case-plugin-manager.ts", + "./src/plugins/test-cases/test-execution-policy-plugin-manager.ts", "./src/plugins/test-cases/test-status.ts" ] }, @@ -1334,16 +1334,16 @@ "./src/plugins/defects/defect-plugin-manager.ts", "./src/plugins/defects/defect-status.ts", "./src/plugins/defects/idefect.ts", - "./src/plugins/logging/abstract-logging-plugin.ts", - "./src/plugins/logging/console-logging-plugin.ts", + "./src/plugins/logging/abstract-reporting-plugin.ts", + "./src/plugins/logging/console-reporting-plugin.ts", "./src/plugins/logging/format-options.ts", "./src/plugins/logging/logging-level.ts", "./src/plugins/logging/logging-plugin-manager.ts", "./src/plugins/plugin-loader.ts", - "./src/plugins/test-cases/abstract-test-case-plugin.ts", + "./src/plugins/test-cases/abstract-test-execution-policy-plugin.ts", "./src/plugins/test-cases/itest-case.ts", "./src/plugins/test-cases/itest-result.ts", - "./src/plugins/test-cases/test-case-plugin-manager.ts", + "./src/plugins/test-cases/test-execution-policy-plugin-manager.ts", "./src/plugins/test-cases/test-exception.ts", "./src/plugins/test-cases/test-status.ts", "./src/wrappers/should.ts", @@ -1378,13 +1378,13 @@ "./src/plugins/defects/idefect.ts": [ "./src/plugins/defects/defect-status.ts" ], - "./src/plugins/logging/abstract-logging-plugin.ts": [ + "./src/plugins/logging/abstract-reporting-plugin.ts": [ "./src/plugins/abstract-plugin.ts", "./src/plugins/logging/logging-level.ts", "./src/plugins/test-cases/itest-result.ts" ], - "./src/plugins/logging/console-logging-plugin.ts": [ - "./src/plugins/logging/abstract-logging-plugin.ts", + "./src/plugins/logging/console-reporting-plugin.ts": [ + "./src/plugins/logging/abstract-reporting-plugin.ts", "./src/plugins/logging/logging-level.ts", "./src/plugins/test-cases/itest-result.ts" ], @@ -1393,7 +1393,7 @@ ], "./src/plugins/logging/logging-plugin-manager.ts": [ "./src/plugins/abstract-plugin-manager.ts", - "./src/plugins/logging/abstract-logging-plugin.ts", + "./src/plugins/logging/abstract-reporting-plugin.ts", "./src/plugins/logging/format-options.ts", "./src/plugins/logging/logging-level.ts", "./src/plugins/test-cases/itest-result.ts" @@ -1401,7 +1401,7 @@ "./src/plugins/plugin-loader.ts": [ "./src/plugins/abstract-plugin.ts" ], - "./src/plugins/test-cases/abstract-test-case-plugin.ts": [ + "./src/plugins/test-cases/abstract-test-execution-policy-plugin.ts": [ "./src/helpers/processing-result.ts", "./src/plugins/abstract-plugin.ts", "./src/plugins/test-cases/itest-case.ts" @@ -1414,11 +1414,11 @@ "./src/plugins/defects/idefect.ts", "./src/plugins/test-cases/test-status.ts" ], - "./src/plugins/test-cases/test-case-plugin-manager.ts": [ + "./src/plugins/test-cases/test-execution-policy-plugin-manager.ts": [ "./src/helpers/processing-result.ts", "./src/plugins/abstract-plugin-manager.ts", "./src/plugins/logging/logging-plugin-manager.ts", - "./src/plugins/test-cases/abstract-test-case-plugin.ts", + "./src/plugins/test-cases/abstract-test-execution-policy-plugin.ts", "./src/plugins/test-cases/itest-case.ts" ], "./src/wrappers/should.ts": [ @@ -1431,7 +1431,7 @@ "./src/plugins/build-info/build-info-plugin-manager.ts", "./src/plugins/defects/defect-plugin-manager.ts", "./src/plugins/logging/logging-plugin-manager.ts", - "./src/plugins/test-cases/test-case-plugin-manager.ts" + "./src/plugins/test-cases/test-execution-policy-plugin-manager.ts" ] }, "semanticDiagnosticsPerFile": [ @@ -1540,16 +1540,16 @@ "./src/plugins/defects/defect-plugin-manager.ts", "./src/plugins/defects/defect-status.ts", "./src/plugins/defects/idefect.ts", - "./src/plugins/logging/abstract-logging-plugin.ts", - "./src/plugins/logging/console-logging-plugin.ts", + "./src/plugins/logging/abstract-reporting-plugin.ts", + "./src/plugins/logging/console-reporting-plugin.ts", "./src/plugins/logging/format-options.ts", "./src/plugins/logging/logging-level.ts", "./src/plugins/logging/logging-plugin-manager.ts", "./src/plugins/plugin-loader.ts", - "./src/plugins/test-cases/abstract-test-case-plugin.ts", + "./src/plugins/test-cases/abstract-test-execution-policy-plugin.ts", "./src/plugins/test-cases/itest-case.ts", "./src/plugins/test-cases/itest-result.ts", - "./src/plugins/test-cases/test-case-plugin-manager.ts", + "./src/plugins/test-cases/test-execution-policy-plugin-manager.ts", "./src/plugins/test-cases/test-exception.ts", "./src/plugins/test-cases/test-status.ts", "./src/wrappers/should.ts", diff --git a/packages/aft-examples/README.md b/packages/aft-examples/README.md index adb135d3..c2225b77 100644 --- a/packages/aft-examples/README.md +++ b/packages/aft-examples/README.md @@ -8,141 +8,106 @@ using AFT allows for setting configuration values in the `aftconfig.json` depend ```json { - "LogManager": { - "level": "info", - "plugins": [{ - "name": "testrail-logging-plugin", - "searchDirectory": "../", - "options": { - "level": "warn", - "enabled": false - } - },{ - "name": "kinesis-logging-plugin", - "searchDirectory": "../", - "options": { - "level": "trace", - "batch": true, - "batchSize": 10, - "enabled": false - } - },{ - "name": "html-logging-plugin", - "searchDirectory": "../", - "options": { - "level": "warn" - } - }, { - "name": "filesystem-logging-plugin", - "searchDirectory": "../", - "options": { - "level": "trace" - } - }] - }, - "TestCaseManager": { - "plugins": [{ - "name": "testrail-test-case-plugin", - "searchDirectory": "../", - "options": { - "enabled": false - } - }] + "pluginNames": [ + "testrail-reporting-plugin", + "testrail-test-execution-policy-plugin", + "kinesis-reporting-plugin", + "html-reporting-plugin", + "filesystem-reporting-plugin", + "grid-session-generator-plugin", + "local-session-generator-plugin", + "webdriverio-remote-session-generator-plugin" + ], + "pluginsSearchDir": "../", + "logLevel": "info", + "KinesisReportingPluginConfig": { + "logLevel": "warn", + "region": "eu-west-1", + "deliveryStream": "%aws_kinesis_delivery_stream%" }, "TestRailConfig": { "url": "%testrail_url%", "user": "%testrail_user%", - "access_key": "%testrail_pass%", - "project_id": 3, - "suite_ids": [744] + "accessKey": "%testrail_pass%", + "projectId": 3, + "suiteIds": [744], + "logLevel": "error", + "policyEngineEnabled": true }, - "BrowserSessionGeneratorManager": { - "uiplatform": "windows_10_chrome", - "plugins": [{ - "name": "browserstack-browser-session-generator-plugin", - "searchDirectory": "../", - "options": { - "user": "%browserstack_user%", - "key": "%browserstack_key%", - "debug": true - } - }, { - "name": "sauce-labs-browser-session-generator-plugin", - "searchDirectory": "../", - "options": { - "username": "%saucelabs_username%", - "accessKey": "%saucelabs_accessKey%" - } - }] - }, - "MobileAppSessionGeneratorManager": { - "uiplatform": "android_11_+_+_Google Pixel 5", - "plugins": [{ - "name": "browserstack-mobile-app-session-generator-plugin", - "searchDirectory": "../", - "options": { - "user": "%browserstack_user%", - "key": "%browserstack_key%", - "debug": true, - "remoteOptions": { - "logLevel": "silent" + "UiSessionManagerConfig": { + "generatorName": "grid-session-generator-plugin", + "options": { + "url": "https://hub-cloud.browserstack.com/wd/hub", + "capabilities": { + "browserName": "chrome", + "bstack:options": { + "userName": "%browserstack_user%", + "accessKey": "%browserstack_key%", + "os": "windows", + "osVersion": "11", + "debug": true } } - }, { - "name": "sauce-labs-mobile-app-session-generator-plugin", - "searchDirectory": "../", - "options": { - "username": "%saucelabs_username%", - "accessKey": "%saucelabs_accessKey%" - } - }] + } } } ``` -- **LogManager** - allows for loading of `LoggingPlugin` implementations - - **plugins** - an `array` of `PluginConfig` objects (objects containing `name: string`, `searchDirectory: string`, and `options: object` properties) containing the options used to locate and instantiate logging plugins - - **level** - `string` containing the default `LogLevel` to set for logging plugins if they don't specify a value in their `PluginConfig.options`. valid values can be any of the following: `trace`, `debug`, `info`, `step`, `warn`, `error` -- **TestCaseManager** - allows for loading of `TestCasePlugin` implementations - - **plugins** - an `array` of `PluginConfig` objects (objects containing `name: string`, `searchDirectory: string`, and `options: object` properties) containing the options used to locate and instantiate test case plugins (NOTE: only the first enabled plugin will be used) +- **pluginNames** - `Array` containing names that should match the filename and classname (if you remove characters like `-`, `_` and `.`) of the plugins to load +- **pluginsSearchDir** - `string` containing a relative path (to `process.cwd()`) used to search for the plugins listed in the `pluginNames` array. _(defaults to `process.cwd()`)_ +- **logLevel** - `string` containing the minimum `LogLevel` where logs will be sent to the console. this value can also serve as a global fall-back for logging plugin implementations using `aftConfig.logLevel` if no value is specified for the given plugin. _(defaults to `'warn'`)_ +- **KinesisReportingPluginConfig** - configuration for the `kinesis-reporting-plugin` + - **logLevel** - the minimum level where logs will be forwarded to your AWS Kinesis Firehose delivery stream. _(defaults to `'none'`)_ + - **region** - `string` containing an AWS Region System Name like `'eu-west-1'` + - **deliveryStream** - `string` containing the Kinesis Firehose delivery stream to use + - **batch** - `boolean` indicating if logs should be batched before being sent to reduce the number of calls being made. _(defaults to `true`)_ + - **batchSize** - `number` indicating the number of log records to wait for before sending. _(defaults to `10`)_ - **TestRailConfig** - configuration values to use for TestRail integration - **url** - `string` containing the URL used for accessing your TestRail instance. _NOTE: this is **NOT** the API url, but the URL to access the base instance of TestRail_ - **user** - `string` containing a valid username for logging in to TestRail - - **accesskey** - `string` containing your API access key used to access the TestRail API. see [here](https://www.gurock.com/testrail/docs/api/getting-started/accessing) for more info. - - **projectid** - `number` containing the TestRail project you are referencing in your tests. _NOTE: this is not used if specifying a value for `planid`_ - - **suiteids** - `number[]` containing a list of the TestRail suites you are referencing in your tests. _NOTE: this is not used if specifying a value for `planid`_ - - **planid** - `number` containing the TestRail plan you are referencing in your tests. _NOTE: if not specified and using the `testrail-logging-plugin` a new TestRail plan will be created based on your `projectid` and `suiteids`_ -- **BrowserSessionGeneratorManager** - allows for loading of `BrowserSessionGeneratorPlugin` implementations - - **plugins** - an `array` of `PluginConfig` objects (objects containing `name: string`, `searchDirectory: string`, and `options: object` properties) containing the options used to locate and instantiate browser session generator plugins (NOTE: only the first enabled plugin will be used) -- **MobileAppSessionGeneratorManager** - allows for loading of `MobileAppSessionGeneratorPlugin` implementations - - **plugins** - an `array` of `PluginConfig` objects (objects containing `name: string`, `searchDirectory: string`, and `options: object` properties) containing the options used to locate and instantiate browser session generator plugins (NOTE: only the first enabled plugin will be used) + - **accessKey** - `string` containing your API access key used to access the TestRail API. see [here](https://www.gurock.com/testrail/docs/api/getting-started/accessing) for more info. + - **projectId** - `number` containing the TestRail project you are referencing in your tests. _NOTE: this is not used if specifying a value for `planid`_ + - **suiteIds** - `Array` containing a list of the TestRail suites you are referencing in your tests. _NOTE: this is not used if specifying a value for `planid`_ + - **planId** - `number` containing the TestRail plan you are referencing in your tests. _NOTE: if not specified and the `testrail-reporting-plugin` is using a `logLevel` of anything other than `'none'` a new TestRail plan will be created based on your `projectId` and `suiteIds`_ + - **logLevel** - `string` containing the minimum `LogLevel` where logs will be captured and sent to TestRail on completion of a test. _NOTE: setting this to a value of `'none'` disabled sending results to TestRail, but you can still use TestRail to control test execution via the `policyEngineEnabled` configuration setting_ + - **policyEngineEnabled** - `boolean` indicating if TestRail should be used to control the execution of tests run within a `Verifier` +- **UiSessionConfig** - configuration for the `UiSessionGeneratorManager` to use to determine which `UiSessionGeneratorPlugin` to use + - **generatorName** - `string` containing the name of the `UiSessionGeneratorPlugin` to use when generating UI sessions + - **options** - `object` containing any properties that will be passed to the loaded `UiSessionGeneratorPlugin.getSession` function and that can be used by the plugin to control the type of session to create ## Test Execution -executing the tests using `npm test` should result in the output like the following sent to the console (assuming the `LogManager.level` is set to something like `info` in your `aftconfig.json`): +executing the tests using `npm test` should result in the output like the following sent to the console (assuming the `Reporter.level` is set to something like `info` in your `aftconfig.json`): ``` -14:51:33 - can access websites using AFT and Page Widgets and Facets - STEP - 1: navigate to LoginPage... -14:51:35 - can access websites using AFT and Page Widgets and Facets - STEP - 2: login -14:51:36 - can access websites using AFT and Page Widgets and Facets - INFO - sending tomsmith to the Username Input -14:51:36 - can access websites using AFT and Page Widgets and Facets - INFO - username entered -14:51:37 - can access websites using AFT and Page Widgets and Facets - INFO - sending SuperSecretPassword! to the Password Input -14:51:37 - can access websites using AFT and Page Widgets and Facets - INFO - password entered -14:51:37 - can access websites using AFT and Page Widgets and Facets - INFO - clicking Login Button... -14:51:39 - can access websites using AFT and Page Widgets and Facets - INFO - Login Button clicked -14:51:39 - can access websites using AFT and Page Widgets and Facets - STEP - 3: wait for message to appear... -14:51:39 - can access websites using AFT and Page Widgets and Facets - STEP - 4: get message... -14:51:41 - can access websites using AFT and Page Widgets and Facets - PASS - C3456 -14:51:41 - can access websites using AFT and Page Widgets and Facets - PASS - C2345 -14:51:41 - can access websites using AFT and Page Widgets and Facets - PASS - C1234 +14:51:33 - [can access websites using AFT and Page Widgets and Facets] - STEP - 1: navigate to LoginPage... +14:51:35 - [can access websites using AFT and Page Widgets and Facets] - STEP - 2: login +14:51:36 - [can access websites using AFT and Page Widgets and Facets] - INFO - sending tomsmith to the Username Input +14:51:36 - [can access websites using AFT and Page Widgets and Facets] - INFO - username entered +14:51:37 - [can access websites using AFT and Page Widgets and Facets] - INFO - sending SuperSecretPassword! to the Password Input +14:51:37 - [can access websites using AFT and Page Widgets and Facets] - INFO - password entered +14:51:37 - [can access websites using AFT and Page Widgets and Facets] - INFO - clicking Login Button... +14:51:39 - [can access websites using AFT and Page Widgets and Facets] - INFO - Login Button clicked +14:51:39 - [can access websites using AFT and Page Widgets and Facets] - STEP - 3: wait for message to appear... +14:51:39 - [can access websites using AFT and Page Widgets and Facets] - STEP - 4: get message... +14:51:41 - [can access websites using AFT and Page Widgets and Facets] - PASS - C3456 +14:51:41 - [can access websites using AFT and Page Widgets and Facets] - PASS - C2345 +14:51:41 - [can access websites using AFT and Page Widgets and Facets] - PASS - C1234 ``` ## TestRail Logging -if using `testrail-logging-plugin` then you must ensure your `verify(assertion)`, `verifyWithBrowser(assertion)`, `verifyWithMobileApp(assertion)`, `Verifier`, `BrowserVerifier`, or `MobileAppVerifier` instances have valid TestRail Case ID's referenced. The values specified for the `withTestId` function must be the TestRail Case ID's referenced by your existing TestRail Plan (not to be confused with the TestRail Test ID's that start with the letter _T_). Modifications will need to be made in two places per test: +if using `testrail-reporting-plugin` then you must ensure your `verify(assertion)`, `verifyWithSelenium(assertion)`, `verifyWithWebdriverIO(assertion)`, `Verifier`, `SeleniumVerifier`, or `WebdriverIoVerifier` instances have valid TestRail Case ID's referenced. The values specified for the `withTestIds` function must be the TestRail Case ID's referenced by your existing TestRail Plan (not to be confused with the TestRail Test ID's that start with the letter _T_). Modifications will need to be made in two places per test: ### Specifying Test IDs -in the options object, set the following: +on the `Verifier` instance, set the following: +```typescript +await verify(() => someTestAction()) + .withTestIds('C1234', 'C2345', 'C3456'); +``` +or, if using the `aft-jasmine-reporter` or `aft-mocha-reporter` packages, modify your test function titles to include the test case IDs like the following: ```typescript -await verify(() => someTestAction()).withTestId('C1234').and.withTestId('C2345').and.withTestId('C3456'); +it('[C1234] can include tests [C2345] in the title [C3456]', async function() { + const aft = new AftTest(this); // if using Jasmine, leave off the `this` + await aft.verify(() => someTestAction()); +}) ``` -specifying the TestRail Case ID's for the Cases you wish to cover. > WARNING: Jasmine's _expect_ calls do not return a boolean as their type definitions would make you think and failed `expect` calls will only throw exceptions if the stop on failure option is enabled: ```typescript diff --git a/packages/aft-examples/aftconfig.json b/packages/aft-examples/aftconfig.json index ea44b237..e11b8fa6 100644 --- a/packages/aft-examples/aftconfig.json +++ b/packages/aft-examples/aftconfig.json @@ -1,93 +1,42 @@ { - "LogManager": { - "level": "info", - "plugins": [{ - "name": "testrail-logging-plugin", - "searchDirectory": "../", - "options": { - "level": "warn", - "enabled": false - } - },{ - "name": "kinesis-logging-plugin", - "searchDirectory": "../", - "options": { - "level": "trace", - "batch": true, - "batchSize": 10, - "enabled": false - } - },{ - "name": "html-logging-plugin", - "searchDirectory": "../", - "options": { - "level": "warn" - } - }, { - "name": "filesystem-logging-plugin", - "searchDirectory": "../", - "options": { - "level": "trace" - } - }] - }, - "TestCaseManager": { - "plugins": [{ - "name": "testrail-test-case-plugin", - "searchDirectory": "../", - "options": { - "enabled": false - } - }] - }, + "pluginNames": [ + "testrail-reporting-plugin", + "testrail-test-execution-policy-plugin", + "kinesis-reporting-plugin", + "html-reporting-plugin", + "filesystem-reporting-plugin", + "grid-session-generator-plugin", + "local-session-generator-plugin", + "webdriverio-remote-session-generator-plugin" + ], + "pluginsSearchDir": "../", + "logLevel": "debug", "TestRailConfig": { "url": "%testrail_url%", "user": "%testrail_user%", - "access_key": "%testrail_pass%", - "project_id": 3, - "suite_ids": [744] + "accessKey": "%testrail_pass%", + "projectId": 3, + "suiteIds": [744], + "logLevel": "none", + "policyEngineEnabled": false }, - "BrowserSessionGeneratorManager": { - "uiplatform": "windows_10_chrome", - "plugins": [{ - "name": "browserstack-browser-session-generator-plugin", - "searchDirectory": "../", - "options": { - "user": "%browserstack_user%", - "key": "%browserstack_key%", - "debug": true - } - }, { - "name": "sauce-labs-browser-session-generator-plugin", - "searchDirectory": "../", - "options": { - "username": "%saucelabs_username%", - "accessKey": "%saucelabs_accessKey%", - "enabled": false - } - }] + "KinesisReportingPluginConfig": { + "logLevel": "none", + "region": "eu-west-1", + "deliveryStream": "%aws_kinesis_delivery_stream%" }, - "MobileAppSessionGeneratorManager": { - "uiplatform": "android_11_+_+_Google Pixel 5", - "plugins": [{ - "name": "browserstack-mobile-app-session-generator-plugin", - "searchDirectory": "../", - "options": { - "user": "%browserstack_user%", - "key": "%browserstack_key%", - "debug": true, - "remoteOptions": { - "logLevel": "silent" + "UiSessionConfig": { + "generatorName": "grid-session-generator-plugin", + "options": { + "url": "https://hub-cloud.browserstack.com/wd/hub", + "capabilities": { + "bstack:options": { + "userName": "%browserstack_user%", + "accessKey": "%browserstack_key%", + "debug": true, + "projectName": "AFT-Examples" } } - }, { - "name": "sauce-labs-mobile-app-session-generator-plugin", - "searchDirectory": "../", - "options": { - "username": "%saucelabs_username%", - "accessKey": "%saucelabs_accessKey%", - "enabled": false - } - }] + } } } \ No newline at end of file diff --git a/packages/aft-examples/package.json b/packages/aft-examples/package.json index 4fc52ac9..d19c00b2 100644 --- a/packages/aft-examples/package.json +++ b/packages/aft-examples/package.json @@ -1,12 +1,12 @@ { "name": "aft-examples", - "version": "9.0.0", + "version": "10.0.0", "description": "Automated Functional Testing (AFT) package containing examples of how it can be used", "private": true, "scripts": { "clean": "rimraf ./dist && rimraf ./logs && rimraf ./FileSystemMap && rimraf ./testresults.html", - "build-e2e": "npm run clean && tsc --build", - "test-e2e": "npm run build-e2e && mocha" + "build": "npm run clean && tsc --build", + "test:e2e": "npm run build && mocha" }, "repository": { "type": "git", @@ -19,7 +19,7 @@ "integration", "functional", "ui", - "logging", + "http", "test", "examples" ], @@ -30,13 +30,14 @@ }, "homepage": "https://github.com/bicarbon8/automated-functional-testing#readme", "dependencies": { - "aft-mocha-reporter": "^9.0.0", - "aft-logging-awskinesis": "^9.0.0", - "aft-logging-filesystem": "^9.0.0", - "aft-logging-html": "^9.0.0", - "aft-testrail": "^9.0.0", - "aft-ui-browsers": "^9.0.0", - "aft-ui-mobile-apps": "^9.0.0" + "aft-mocha-reporter": "^10.0.0", + "aft-reporting-aws-kinesis-firehose": "^10.0.0", + "aft-reporting-filesystem": "^10.0.0", + "aft-reporting-html": "^10.0.0", + "aft-testrail": "^10.0.0", + "aft-ui-selenium": "^10.0.0", + "aft-ui-webdriverio": "^10.0.0", + "aft-web-services": "^10.0.0" }, "devDependencies": { "@types/chai": "^4.2.17", diff --git a/packages/aft-examples/test/ui/browser-tests/browsers.spec.ts b/packages/aft-examples/test/ui/browser-tests/browsers.spec.ts index 7db142c2..b19b3515 100644 --- a/packages/aft-examples/test/ui/browser-tests/browsers.spec.ts +++ b/packages/aft-examples/test/ui/browser-tests/browsers.spec.ts @@ -1,92 +1,125 @@ -import { containing, retry, Verifier, verify } from "aft-core"; -import { AftLog, AftTest } from "aft-mocha-reporter"; -import { verifyWithBrowser, BrowserVerifier, BrowserFacetOptions } from "aft-ui-browsers"; -import { expect } from "chai"; +import { AftConfig, BuildInfoManager, containing, pluginLoader, retry, Verifier } from "aft-core"; +import { AftTest } from "aft-mocha-reporter"; +import { SeleniumVerifier } from "aft-ui-selenium"; import { HerokuLoginPage } from "./page-objects/heroku-login-page"; -describe('Functional Browser Tests using AFT-UI-BROWSERS', () => { - it('can access websites using AFT and Page Widgets and Facets', async function() { - const aft = new AftLog(this); - await verifyWithBrowser(async (tw: BrowserVerifier) => { - let loginPage: HerokuLoginPage = await tw.session.getFacet(HerokuLoginPage); +describe('Functional Browser Tests using AFT-UI-SELENIUM', () => { + beforeEach(() => { + /** + * normally this call would not be necessary, but because these examples switch between + * multiple configurations and UI Session Generators it is necessary to clear out any + * cached plugins and force a reload with fresh configuration before each test + */ + pluginLoader.reset(); + }); + + it('[C3456][C2345][C1234] can access websites using AFT and BrowserComponents', async function() { + const aftCfg = new AftConfig(); + const aft = new AftTest(this, aftCfg); + await aft.verify(async (tw: SeleniumVerifier) => { + let loginPage: HerokuLoginPage = tw.getComponent(HerokuLoginPage); - await tw.logMgr.step('navigate to LoginPage...'); + await tw.reporter.step('navigate to LoginPage...'); await loginPage.navigateTo(); - await tw.logMgr.step('login'); + await tw.reporter.step('login'); await loginPage.login("tomsmith", "SuperSecretPassword!"); - await tw.logMgr.step('wait for message to appear...') + await tw.reporter.step('wait for message to appear...') await retry(() => loginPage.hasMessage()) - .withStartDelayBetweenAttempts(100) + .withDelay(100) .withBackOff('exponential') .withMaxDuration(20000); - await tw.logMgr.step('get message...'); + await tw.reporter.step('get message...'); return await loginPage.getMessage(); - }).withLogManager(aft.logMgr) - .and.withTestIds('C3456').and.withTestIds('C2345').and.withTestIds('C1234') - .returns(containing("You logged into a secure area!")); + }, SeleniumVerifier).withAdditionalSessionOptions({ + capabilities: { + browserName: 'chrome', + "bstack:options": { + sessionName: aft.reporter.reporterName, + os: 'windows', + osVersion: '11', + buildName: await new BuildInfoManager().get() + } + } + }).returns(containing("You logged into a secure area!")); }); it('can recover from StaleElementExceptions automatically', async function() { - const aft = new AftTest(this); - const shouldRun = await aft.shouldRun(); - if (!shouldRun) { - this.skip(); - } - await verifyWithBrowser(async (tw: BrowserVerifier) => { - let loginPage: HerokuLoginPage = await tw.session.getFacet(HerokuLoginPage, {maxWaitMs: 5000}); + const aftCfg = new AftConfig(); + const aft = new AftTest(this, aftCfg); + await aft.verify(async (tw: SeleniumVerifier) => { + let loginPage: HerokuLoginPage = tw.getComponent(HerokuLoginPage); - await verify(async (v: Verifier) => { - await v.logMgr.step('navigate to LoginPage'); + await aft.verify(async (v: Verifier) => { + await v.reporter.step('navigate to LoginPage'); await loginPage.navigateTo(); - return await loginPage.session.driver.getCurrentUrl(); - }).withLogManager(tw.logMgr).and.withTestIds('C4567') + return await loginPage.driver.getCurrentUrl(); + }).withTestIds('C4567') .returns(containing('the-internet.herokuapp.com/login')); - await verify(async (v: Verifier) => { - await v.logMgr.step('click login button...'); - await loginPage.content().then(c => c.getLoginButton()).then(button => button.click()); - await v.logMgr.info('no exception thrown on click'); - }).withLogManager(tw.logMgr).and.withTestIds('C5678'); + await aft.verify(async (v: Verifier) => { + await v.reporter.step('click login button...'); + await loginPage.content.getLoginButton().then(button => button.click()); + await v.reporter.info('no exception thrown on click'); + }).withTestIds('C5678'); - await verify(async (v: Verifier) => { - await v.logMgr.step('refresh page...'); - await tw.session.refresh(); - await v.logMgr.info('page refreshed'); - }).withLogManager(tw.logMgr).and.withTestIds('C6789'); + await aft.verify(async (v: Verifier) => { + await v.reporter.step('refresh page...'); + await tw.driver.navigate().refresh(); + await v.reporter.info('page refreshed'); + }).withTestIds('C6789'); - await verify(async (v: Verifier) => { - await tw.logMgr.step('click login button after refresh...'); - await loginPage.content().then(c => c.getLoginButton()).then(button => button.click()); - await tw.logMgr.info('no exception thrown on click'); - }).withLogManager(tw.logMgr).and.withTestIds('C7890'); - }).withLogManager(aft.logMgr); + await aft.verify(async (v: Verifier) => { + await tw.reporter.step('click login button after refresh...'); + await loginPage.content.getLoginButton().then(button => button.click()); + await tw.reporter.info('no exception thrown on click'); + }).withTestIds('C7890'); + }, SeleniumVerifier).withAdditionalSessionOptions({ + capabilities: { + browserName: 'chrome', + "bstack:options": { + sessionName: aft.reporter.reporterName, + os: 'windows', + osVersion: '11', + buildName: await new BuildInfoManager().get() + } + } + }); }); const uiplatforms = [ - 'os x_+_safari_latest', - 'windows_11_firefox', - 'windows_11_edge_+_+' + { browser: 'safari', os: 'os x', osV: 'ventura' }, + { browser: 'firefox', os: 'windows', osV: '11' }, + { browser: 'edge', os: 'windows', osV: '11' }, ]; - for (var i=0; i { - let loginPage: HerokuLoginPage = await tw.session.getFacet(HerokuLoginPage); + for (let uiplatform of uiplatforms) { + it(`can run with multiple uiplatforms: ${JSON.stringify(uiplatform)}`, async function() { + const platform = Object.freeze({...uiplatform}); + const aftCfg = new AftConfig(); + const aft = new AftTest(this, aftCfg); + await aft.verify(async (tw: SeleniumVerifier) => { + let loginPage: HerokuLoginPage = tw.getComponent(HerokuLoginPage); await loginPage.navigateTo(); await loginPage.login("tomsmith", "SuperSecretPassword!"); await retry(() => loginPage.hasMessage()) - .until((res: boolean) => res) - .withStartDelayBetweenAttempts(100) + .withDelay(100) .withBackOff('exponential') - .withMaxDuration(20000); + .withMaxDuration(20000) + .until((res: boolean) => res); return await loginPage.getMessage(); - }).withLogManager(aft.logMgr) - .and.withBrowserSessionOptions({uiplatform: uiplatform}) - .returns(containing("You logged into a secure area!")); + }, SeleniumVerifier).withAdditionalSessionOptions({ + capabilities: { + browserName: platform.browser, + "bstack:options": { + sessionName: aft.reporter.reporterName, + os: platform.os, + osVersion: platform.osV, + buildName: await new BuildInfoManager(aftCfg).get() + } + } + }).returns(containing("You logged into a secure area!")); }); } }); \ No newline at end of file diff --git a/packages/aft-examples/test/ui/browser-tests/page-objects/heroku-content-widget.ts b/packages/aft-examples/test/ui/browser-tests/page-objects/heroku-content-widget.ts index 8657836c..8fbca6de 100644 --- a/packages/aft-examples/test/ui/browser-tests/page-objects/heroku-content-widget.ts +++ b/packages/aft-examples/test/ui/browser-tests/page-objects/heroku-content-widget.ts @@ -1,7 +1,7 @@ import { By, Locator, WebElement } from 'selenium-webdriver'; -import { BrowserFacet } from 'aft-ui-browsers'; +import { SeleniumComponent } from 'aft-ui-selenium'; -export class HerokuContentWidget extends BrowserFacet { +export class HerokuContentWidget extends SeleniumComponent { /** * this Facet sets a static locator instead of using a passed * in value on the constructor @@ -11,32 +11,38 @@ export class HerokuContentWidget extends BrowserFacet { } private async usernameInput(): Promise { - return await this.getElement({ locator: By.id("username") }); + return this.getRoot() + .then(r => r.findElement(By.id("username"))) + .catch((err) => null); } private async passwordInput(): Promise { - return await this.getElement({ locator: By.id('password') }); + return this.getRoot() + .then(r => r.findElement(By.id('password'))) + .catch((err) => null); } private async loginButton(): Promise { - return await this.getElement({ locator: By.css('button.radius') }); + return this.getRoot() + .then(r => r.findElement(By.css('button.radius'))) + .catch((err) => null); } async login(username: string, password: string): Promise { let ui: WebElement = await this.usernameInput(); - await this.logMgr.info(`sending ${username} to the Username Input`); + await this.reporter.info(`sending ${username} to the Username Input`); await ui.sendKeys(username); - await this.logMgr.info('username entered'); + await this.reporter.info('username entered'); let pi: WebElement = await this.passwordInput(); - await this.logMgr.info(`sending ${password} to the Password Input`); + await this.reporter.info(`sending ${password} to the Password Input`); await pi.sendKeys(password); - await this.logMgr.info('password entered'); + await this.reporter.info('password entered'); await this.clickLoginButton(); } async clickLoginButton(): Promise { - await this.logMgr.info('clicking Login Button...'); + await this.reporter.info('clicking Login Button...'); let lb: WebElement = await this.loginButton(); await lb.click(); - await this.logMgr.info('Login Button clicked'); + await this.reporter.info('Login Button clicked'); } async getLoginButton(): Promise { diff --git a/packages/aft-examples/test/ui/browser-tests/page-objects/heroku-login-page.ts b/packages/aft-examples/test/ui/browser-tests/page-objects/heroku-login-page.ts index 4dd70d28..f4cabe3d 100644 --- a/packages/aft-examples/test/ui/browser-tests/page-objects/heroku-login-page.ts +++ b/packages/aft-examples/test/ui/browser-tests/page-objects/heroku-login-page.ts @@ -1,48 +1,45 @@ import { By, Locator } from 'selenium-webdriver'; -import { BrowserFacet } from 'aft-ui-browsers'; import { HerokuContentWidget } from './heroku-content-widget'; import { HerokuMessagesWidget } from './heroku-messages-widget'; +import { SeleniumComponent } from 'aft-ui-selenium'; +import { Err } from 'aft-core'; -export class HerokuLoginPage extends BrowserFacet { +export class HerokuLoginPage extends SeleniumComponent { /** * this Facet sets a static locator instead of using a passed * in value on the constructor */ override get locator(): Locator { - return By.css('html') - }; + return By.css('html'); + } /* begin: widgets */ - async content(): Promise { - return await this.getFacet(HerokuContentWidget); + get content(): HerokuContentWidget { + return this.getComponent(HerokuContentWidget); } - async messages(): Promise { - return await this.getFacet(HerokuMessagesWidget, {maxWaitMs: 20000}); + get messages(): HerokuMessagesWidget { + return this.getComponent(HerokuMessagesWidget); } /* end: widgets */ async navigateTo(): Promise { - try { - await this.session.goTo('https://the-internet.herokuapp.com/login'); - } catch (e) { - return Promise.reject(e); - } + await Err.handleAsync(async () => await this.driver.navigate().to('https://the-internet.herokuapp.com/login'), { + logger: this.reporter, + errLevel: 'error' + }); } /* begin: page actions */ async login(username: string, password: string): Promise { - let hc: HerokuContentWidget = await this.content(); - return hc.login(username, password); + return await this.content.login(username, password); } async hasMessage(): Promise { - let hm: HerokuMessagesWidget = await this.messages(); - return hm.hasMessage(); + return await this.messages.hasMessage(); } async getMessage(): Promise { - let hm: HerokuMessagesWidget = await this.messages(); - return hm.getMessage(); + return await this.messages.getMessage(); } /* end: page actions */ } \ No newline at end of file diff --git a/packages/aft-examples/test/ui/browser-tests/page-objects/heroku-messages-widget.ts b/packages/aft-examples/test/ui/browser-tests/page-objects/heroku-messages-widget.ts index d060a247..8ab4d441 100644 --- a/packages/aft-examples/test/ui/browser-tests/page-objects/heroku-messages-widget.ts +++ b/packages/aft-examples/test/ui/browser-tests/page-objects/heroku-messages-widget.ts @@ -1,7 +1,7 @@ +import { SeleniumComponent } from "aft-ui-selenium"; import { By, Locator, WebElement } from "selenium-webdriver"; -import { BrowserFacet } from "aft-ui-browsers"; -export class HerokuMessagesWidget extends BrowserFacet { +export class HerokuMessagesWidget extends SeleniumComponent { /** * this Facet sets a static locator instead of using a passed * in value on the constructor @@ -11,27 +11,32 @@ export class HerokuMessagesWidget extends BrowserFacet { } private async message(): Promise { - let elements: WebElement[] = await this.getElements({ locator: By.id('flash') }); - return elements[0]; + let elements: WebElement[]; + try { + elements = await this.getRoot() + .then(r => r.findElements(By.id('flash'))) + .catch((err) => []); + } catch (e) { + return null; + } + if (elements.length > 0) { + return elements[0]; + } + return null; } async hasMessage(): Promise { - return await this.message() - .then((message) => { - return message !== undefined; - }).catch((err: Error) => { - return false; - }); + const message = await this.message(); + if (message != null) { + return true; + } + return false; } async getMessage(): Promise { if (await this.hasMessage()) { - return await this.message() - .then(message => { - return message.getText(); - }).catch((err) => { - return null; - }); + const messageEl = await this.message(); + return await messageEl.getText(); } return null; } diff --git a/packages/aft-examples/test/ui/mobile-app-tests/mobile-apps.spec.ts b/packages/aft-examples/test/ui/mobile-app-tests/mobile-apps.spec.ts index 2143eb08..1bae27ad 100644 --- a/packages/aft-examples/test/ui/mobile-app-tests/mobile-apps.spec.ts +++ b/packages/aft-examples/test/ui/mobile-app-tests/mobile-apps.spec.ts @@ -1,47 +1,78 @@ import * as path from "path"; -import { rand } from "aft-core"; -import { MobileAppFacetOptions, mobileAppSessionGeneratorMgr, MobileAppVerifier, verifyWithMobileApp } from "aft-ui-mobile-apps"; +import * as fs from "fs"; +import * as FormData from "form-data"; +import { AftConfig, BuildInfoManager, Reporter, aftConfig, pluginLoader } from "aft-core"; import { WikipediaView } from "./page-objects/wikipedia-view"; -import { assert } from "chai"; import { AftTest } from "aft-mocha-reporter"; +import { httpService, httpData, HttpHeaders } from "aft-web-services"; +import { UiSessionConfig } from "aft-ui"; +import { WebdriverIoVerifier } from "aft-ui-webdriverio"; var customId: string; -describe('Functional Mobile App Tests using AFT-UI-MOBILE-APPS', () => { +describe('Functional Mobile App Tests using AFT-UI-WEBDRIVERIO', () => { + beforeEach(() => { + /** + * normally this call would not be necessary, but because these examples switch between + * multiple configurations and UI Session Generators it is necessary to clear out any + * cached plugins and force a reload with fresh configuration before each test + */ + pluginLoader.reset(); + }); + before(async () => { - let resp = await mobileAppSessionGeneratorMgr.sendCommand('getApps'); + const logger = new Reporter('MobileAppsSpec Before'); + const uisc = aftConfig.getSection(UiSessionConfig); + const username = uisc.options.capabilities?.["bstack:options"]?.userName; + const password = uisc.options.capabilities?.["bstack:options"]?.accessKey; + const resp = await httpService.performRequest({ + url: "https://api-cloud.browserstack.com/app-automate/recent_group_apps", + headers: { + ...HttpHeaders.Authorization.basic(username, password) + }, + reporter: logger + }); let app: any; - for (var i=0; i>(resp); + for (var i=0; i(result); } + customId = app.shareable_id ?? app.custom_id ?? app.app_url ?? 'AFT.WikipediaApp'; }); it('can search in Wikipedia App', async function() { - const aft = new AftTest(this); - const shouldRun = await aft.shouldRun(); - if (!shouldRun) { - this.skip(); - } - await verifyWithMobileApp(async (tw: MobileAppVerifier) => { - await tw.logMgr.step('get the WikipediaView Facet from the Session...'); - let view: WikipediaView = await tw.session.getFacet(WikipediaView); - await tw.logMgr.step('enter a search term...'); + const aftCfg = new AftConfig(); + const uisc = aftCfg.getSection(UiSessionConfig); + uisc.generatorName = 'webdriverio-remote-session-generator-plugin'; + const username = uisc.options.capabilities?.["bstack:options"]?.userName; + const password = uisc.options.capabilities?.["bstack:options"]?.accessKey; + const aft = new AftTest(this, aftCfg); + await aft.verify(async (tw: WebdriverIoVerifier) => { + await tw.reporter.step('get the WikipediaView Component from the Session...'); + let view: WikipediaView = tw.getComponent(WikipediaView); + await tw.reporter.step('enter a search term...'); await view.searchFor('pizza'); - await tw.logMgr.step('get the results and ensure they contain the search term...'); + await tw.reporter.step('get the results and ensure they contain the search term...'); let results: string[] = await view.getResults(); for (var i=0; i { return true; } } - }).withMobileAppSessionOptions({app: customId}) - .and.withLogManager(aft.logMgr) - .returns(true); + }, WebdriverIoVerifier).withAdditionalSessionOptions({ + user: username, + key: password, + capabilities: { + browserName: 'android', + platformName: 'android', + "appium:platformVersion": '13.0', + "appium:deviceName": 'Samsung Galaxy S23', + "appium:app": customId, + "bstack:options": { + "sessionName": aft.reporter.reporterName, + buildName: await new BuildInfoManager(aftCfg).get() + } + } + }).returns(true); }); }); \ No newline at end of file diff --git a/packages/aft-examples/test/ui/mobile-app-tests/page-objects/wikipedia-view.ts b/packages/aft-examples/test/ui/mobile-app-tests/page-objects/wikipedia-view.ts index 0dc54dd5..f25dcf86 100644 --- a/packages/aft-examples/test/ui/mobile-app-tests/page-objects/wikipedia-view.ts +++ b/packages/aft-examples/test/ui/mobile-app-tests/page-objects/wikipedia-view.ts @@ -1,38 +1,38 @@ -import { MobileAppFacet } from "aft-ui-mobile-apps"; -import { Element, ElementArray } from "webdriverio"; +import { WebdriverIoComponent } from "aft-ui-webdriverio"; +import { Element } from "webdriverio"; -export class WikipediaView extends MobileAppFacet { +export class WikipediaView extends WebdriverIoComponent { override get locator(): string { return '//*'; } - private _searchButton = async (): Promise> => await this.getElement({locator: "~Search Wikipedia", maxWaitMs: 10000}); - private _searchInput = async (): Promise> => await this.session.driver.$('android=new UiSelector().resourceId("org.wikipedia.alpha:id/search_src_text")'); - private _searchResults = async (): Promise => await this.getElements({locator: "android.widget.TextView", maxWaitMs: 10000}); + private _searchButton = async (): Promise> => await (await this.getRoot()).$("~Search Wikipedia"); + private _searchInput = async (): Promise> => await this.driver.$('android=new UiSelector().resourceId("org.wikipedia.alpha:id/search_src_text")'); + private _searchResults = async (): Promise>> => await (await this.getRoot()).$$("android.widget.TextView"); async searchFor(term: string): Promise { - await this.logMgr.info("tapping on 'SearchButton'"); + await this.reporter.info("tapping on 'SearchButton'"); await this._searchButton().then(b => b.click()); await this.sendTextToSearch(term); return await this.getResults(); } async sendTextToSearch(text: string): Promise { - await this.logMgr.info(`setting 'SearchInput' to '${text}'...`); + await this.reporter.info(`setting 'SearchInput' to '${text}'...`); await this._searchInput().then(i => i.addValue(text)); } async getResults(): Promise { - await this.logMgr.info("getting text from 'SearchResults' to return as 'string[]'"); + await this.reporter.info("getting text from 'SearchResults' to return as 'string[]'"); let resultsText: string[] = []; - var searchResults: ElementArray = await this._searchResults(); + var searchResults = await this._searchResults(); for (var i=0; i = searchResults[i]; + let res = searchResults[i]; let txt: string = await res.getText().catch(err => err); resultsText.push(txt); } - await this.logMgr.info(`found results of: [${resultsText.join(', ')}]`); + await this.reporter.info(`found results of: [${resultsText.join(', ')}]`); return resultsText; } } \ No newline at end of file diff --git a/packages/aft-examples/test/web-services/rest.spec.ts b/packages/aft-examples/test/web-services/rest.spec.ts index 8148fbd4..4a8939c0 100644 --- a/packages/aft-examples/test/web-services/rest.spec.ts +++ b/packages/aft-examples/test/web-services/rest.spec.ts @@ -1,82 +1,76 @@ import * as fs from "fs"; import * as path from "path"; import * as FormData from "form-data"; -import { greaterThan, havingValue, lessThan, retry, verify } from "aft-core"; -import { AftLog, AftTest } from "aft-mocha-reporter"; +import { Verifier, greaterThan, havingValue, lessThan, retry } from "aft-core"; +import { AftTest } from "aft-mocha-reporter"; import { httpData, HttpResponse, httpService } from 'aft-web-services'; import { expect } from "chai"; import { ListUsersResponse } from "./response-objects/list-users-response"; describe('REST Request', () => { it('can make GET request from JSON REST API', async function() { - const aft = new AftLog(this); + const aft = new AftTest(this); let response: HttpResponse; - await verify(async (tw) => { - await tw.logMgr.step('making request...'); + await aft.verify(async (v: Verifier) => { + await v.reporter.step('making request...'); const r = retry(() => httpService.performRequest({ url: 'https://reqres.in/api/users?page=2', - logMgr: tw.logMgr + reporter: v.reporter })).until((res: HttpResponse) => res.statusCode >= 200 && res.statusCode < 400) - .withStartDelayBetweenAttempts(100) + .withDelay(100) .withBackOff('exponential') .withMaxDuration(20000); response = await Promise.resolve(r); if (!r.isSuccessful) { - await tw.logMgr.error(r.lastError); + await v.reporter.error(r.lastError); } return r.totalDuration; - }).withLogManager(aft.logMgr) - .and.withDescription('takes less than 10sec') + }).withDescription('takes less than 10sec') .and.withTestIds('C2217763') .returns(lessThan(10000)); - await verify(async (tw) => { - await tw.logMgr.step('confirm response is not null...'); + await aft.verify(async (v: Verifier) => { + await v.reporter.step('confirm response is not null...'); expect(response).to.exist; - await tw.logMgr.info('confirmed response is not null.'); - await tw.logMgr.info('response status code: ' + response.statusCode); - await tw.logMgr.step('confirm response.data is not null...'); + await v.reporter.info('confirmed response is not null.'); + await v.reporter.info('response status code: ' + response.statusCode); + await v.reporter.step('confirm response.data is not null...'); return response.data; - }).withLogManager(aft.logMgr) - .and.withDescription('returns a valid response object') + }).withDescription('returns a valid response object') .and.withTestIds('C3131') .returns(havingValue()); - await verify(async (tw) => { - await tw.logMgr.step('confirm can deserialise response.data into typed object...'); + await aft.verify(async (v: Verifier) => { + await v.reporter.step('confirm can deserialise response.data into typed object...'); let obj: ListUsersResponse = httpData.as(response); expect(obj).to.exist; - await tw.logMgr.info('confirmed can deserialise response.data into typed object.'); - await tw.logMgr.step('confirm object data property contains more than one result...'); + await v.reporter.info('confirmed can deserialise response.data into typed object.'); + await v.reporter.step('confirm object data property contains more than one result...'); return obj.data.length; - }).withLogManager(aft.logMgr) - .and.withDescription('receives more than 0 results in the data array') + }).withDescription('receives more than 0 results in the data array') .and.withTestIds('C2217764') .returns(greaterThan(0)); }); it('can make a multipart post', async function() { const aft = new AftTest(this); - const shouldRun = await aft.shouldRun(); - if (!shouldRun) { - aft.test.skip(); - } - - let formData = new FormData(); - formData.append('file', fs.createReadStream(path.join(process.cwd(), 'LICENSE'))); - await aft.logMgr.step('about to send multipart post...'); - const resp = await httpService.performRequest({ - multipart: true, - url: 'https://httpbin.org/post', - postData: formData, - method: 'POST', - logMgr: aft.logMgr - }); + await aft.verify(async (v: Verifier) => { + let formData = new FormData(); + formData.append('file', fs.createReadStream(path.join(process.cwd(), 'LICENSE'))); + await v.reporter.step('about to send multipart post...'); + const resp = await httpService.performRequest({ + multipart: true, + url: 'https://httpbin.org/post', + postData: formData, + method: 'POST', + reporter: v.reporter + }); - if (resp) { - await aft.logMgr.info(`received response.`); - } - expect(resp.data).to.exist; + if (resp) { + await v.reporter.info(`received response.`); + } + return resp.data; + }).returns(havingValue()) }); }); \ No newline at end of file diff --git a/packages/aft-examples/tsconfig.json b/packages/aft-examples/tsconfig.json index 5822a31e..ddae5359 100644 --- a/packages/aft-examples/tsconfig.json +++ b/packages/aft-examples/tsconfig.json @@ -6,10 +6,13 @@ }, "include": ["test"], "references": [ - { "path": "../aft-ui-browsers" }, - { "path": "../aft-ui-mobile-apps" }, - { "path": "../aft-logging-awskinesis" }, - { "path": "../aft-logging-html" }, - { "path": "../aft-testrail" } + { "path": "../aft-mocha-reporter" }, + { "path": "../aft-reporting-aws-kinesis-firehose" }, + { "path": "../aft-reporting-filesystem" }, + { "path": "../aft-reporting-html" }, + { "path": "../aft-testrail" }, + { "path": "../aft-ui-selenium" }, + { "path": "../aft-ui-webdriverio" }, + { "path": "../aft-web-services" } ] } \ No newline at end of file diff --git a/packages/aft-jasmine-reporter/README.md b/packages/aft-jasmine-reporter/README.md index 985c0d23..5f4f3a48 100644 --- a/packages/aft-jasmine-reporter/README.md +++ b/packages/aft-jasmine-reporter/README.md @@ -19,42 +19,43 @@ while no configuration is required, the `aft-jasmine-reporter` supports all AFT this package comes with two helper classes that can be utilised from within your Jasmine specs to make use of AFT features. ### `AftLog` -the `AftLog` class provides access to an AFT `LogManager` instance for your currently executing spec file. you can use it like the following: +the `AftLog` class provides access to an AFT `Reporter` instance for your currently executing spec file. you can use it like the following: ```javascript describe('YourTestSuite', () => { - it('allows you to log using AFT LogManager', async () => { + it('allows you to log using AFT Reporter', async () => { const aft = new AftLog(); - await aft.logMgr.step('starting test...'); + await aft.reporter.step('starting test...'); /* do some test things here */ - await aft.logMgr.step('test is complete'); + await aft.reporter.step('test is complete'); }); }); ``` -and which would output the following to your console and any AFT `LoggingPlugin` instances referenced in your `aftconfig.json` (assuming your test expectations all pass) +and which would output the following to your console and any AFT `ReportingPlugin` instances referenced in your `aftconfig.json` (assuming your test expectations all pass) ```text -17:52:45 - [YourTestSuite allows you to log using AFT LogManager] - STEP - starting test... -17:54:02 - [YourTestSuite allows you to log using AFT LogManager] - STEP - test is complete -17:54:02 - [YourTestSuite allows you to log using AFT LogManager] - PASS - YourTestSuite allows you to log using AFT LogManager +17:52:45 - [YourTestSuite allows you to log using AFT Reporter] - STEP - starting test... +17:54:02 - [YourTestSuite allows you to log using AFT Reporter] - STEP - test is complete +17:54:02 - [YourTestSuite allows you to log using AFT Reporter] - PASS - YourTestSuite allows you to log using AFT Reporter ``` ### `AftTest` -the `AftTest` class extends from the `AftLog` adding the ability to parse the Spec name for any referenced Test or Defect IDs. each Test ID must be surrounded with square brackets `[ABC123]` and each Defect ID with less than and greater than symbols ``. additionally you can then call the `AftTest.shouldRun()` async function which will determine if your test should be run based on any AFT `TestCasePlugin` and `DefectPlugin` instances referenced in your `aftconfig.json` file. using the `AftTest` class would look like the following: +the `AftTest` class extends from the `AftLog` adding the ability to parse the Spec name for any referenced Test. each Test ID must be surrounded with square brackets `[ABC123]`. additionally you can then call the `AftTest.shouldRun()` async function or use `AftTest.verify(assertion)` which will determine if your test should be run based on any AFT `TestExecutionPolicyPlugin` instances referenced in your `aftconfig.json` file. using the `AftTest` class would look like the following: ```javascript describe('YourTestSuite', () => { - it('can check if test [C1234] with known defect should be run', async () => { + it('can check if test [C1234] should be run', async () => { const aft = new AftTest(); - const shouldRun = await aft.shouldRun(); - if (!shouldRun) { - pending(); - } - await aft.logMgr.step('we should never get here if C1234 should not be run or BUG-123 is open'); + await aft.verify(async (v: Verifier) => { + // `verify` calls `pending()` if should not be run which marks test as skipped + await aft.reporter.step('we should never get here if C1234 should not be run'); + const result = await doStuff(); + return result; + }).returns(equaling('stuff')); }); }); ``` -which would output the following to your console and any AFT `LoggingPlugin` instances referenced in your `aftconfig.json` if the test ID should not be run: +which would output the following to your console and any AFT `ReportingPlugin` instances referenced in your `aftconfig.json` if the test ID should not be run: ```text -17:52:45 - [YourTestSuite can check if test [C1234] with known defect should be run] - WARN - none of the supplied tests should be run: [C1234] -17:52:45 - [YourTestSuite can check if test [C1234] with known defect should be run] - WARN - test skipped +17:52:45 - [YourTestSuite can check if test [C1234] should be run] - WARN - none of the supplied tests should be run: [C1234] +17:52:45 - [YourTestSuite can check if test [C1234] should be run] - WARN - test skipped ``` ## NOTES @@ -62,10 +63,7 @@ which would output the following to your console and any AFT `LoggingPlugin` ins - you can use the AFT `Verifier` in combination with the `AftLog` or `AftTest` classes like follows: ```javascript const aft = new AftTest(); -await verify(() => { +await aft.verify(() => { /* perform testing here */ -}).withLogManager(aft.logMgr) -.and.withTestIds(...aft.testcases) -.and.withKnownDefectIds(...aft.defects) -.returns(expected); +}).returns(expected); ``` \ No newline at end of file diff --git a/packages/aft-jasmine-reporter/aftconfig.json b/packages/aft-jasmine-reporter/aftconfig.json deleted file mode 100644 index f2c60f67..00000000 --- a/packages/aft-jasmine-reporter/aftconfig.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "LogManager": { - "level": "info", - "plugins": [{ - "name": "html-logging-plugin", - "searchDirectory": "../", - "options": { - "level": "warn" - } - }, { - "name": "filesystem-logging-plugin", - "searchDirectory": "../", - "options": { - "level": "trace" - } - }] - } -} \ No newline at end of file diff --git a/packages/aft-jasmine-reporter/package.json b/packages/aft-jasmine-reporter/package.json index 5c482ecc..18fb5cfc 100644 --- a/packages/aft-jasmine-reporter/package.json +++ b/packages/aft-jasmine-reporter/package.json @@ -1,6 +1,6 @@ { "name": "aft-jasmine-reporter", - "version": "9.0.0", + "version": "10.0.0", "description": "Automated Functional Testing (AFT) Reporter for use with Jasmine Test Framework", "main": "./dist/src/index.js", "types": "./dist/src/index.d.ts", @@ -8,7 +8,7 @@ "clean": "rimraf ./dist && rimraf ./logs && rimraf ./FileSystemMap && rimraf ./testresults.html", "build": "npm run clean && tsc --build", "test": "npm run build && jasmine --config=./jasmine.json --reporter=./dist/src/aft-jasmine-reporter.js", - "coverage": "nyc npm run test" + "coverage": "npm run build && nyc jasmine --config=./jasmine.json --reporter=./dist/src/aft-jasmine-reporter.js" }, "repository": { "type": "git", @@ -30,14 +30,14 @@ }, "homepage": "https://github.com/bicarbon8/automated-functional-testing#readme", "dependencies": { - "aft-core": "^9.0.0", + "aft-core": "^10.0.0", "jasmine": "^4.2.1" }, "devDependencies": { "@types/jasmine": "^4.0.3", "@types/node": "^18.0.1", - "aft-logging-filesystem": "^9.0.0", - "aft-logging-html": "^9.0.0", + "aft-reporting-filesystem": "^10.0.0", + "aft-reporting-html": "^10.0.0", "nyc": "^15.1.0", "rimraf": "^3.0.2", "ts-node": "^10.8.2", diff --git a/packages/aft-jasmine-reporter/src/aft-jasmine-reporter.ts b/packages/aft-jasmine-reporter/src/aft-jasmine-reporter.ts index 10be3c1c..c657b366 100644 --- a/packages/aft-jasmine-reporter/src/aft-jasmine-reporter.ts +++ b/packages/aft-jasmine-reporter/src/aft-jasmine-reporter.ts @@ -42,7 +42,7 @@ export class AftJasmineReporter implements jasmine.CustomReporter { await t.pending(); break; default: - await t.logMgr.warn(`unknown test.status of '${t.test.status}' returned`); + await t.reporter.warn(`unknown test.status of '${t.test.status}' returned`); break; } await t.dispose(); diff --git a/packages/aft-jasmine-reporter/src/aft-log.ts b/packages/aft-jasmine-reporter/src/aft-log.ts index 48c39936..b7834d67 100644 --- a/packages/aft-jasmine-reporter/src/aft-log.ts +++ b/packages/aft-jasmine-reporter/src/aft-log.ts @@ -1,12 +1,14 @@ -import { FileSystemMap, LogManager } from "aft-core"; +import { AftConfig, FileSystemMap, Reporter, aftConfig } from "aft-core"; export class AftLog { - private _logMgr: LogManager; + private _rep: Reporter; + private readonly _aftCfg: AftConfig; private readonly _testNames: FileSystemMap; public readonly test: jasmine.SpecResult; - constructor(scope?: any) { - this._testNames = new FileSystemMap('AftJasmineReporter'); + constructor(scope?: any, aftCfg?: AftConfig) { + this._aftCfg = aftCfg ?? aftConfig; + this._testNames = new FileSystemMap('AftJasmineReporter', [], this._aftCfg); if (!scope) { const names: Array = Array.from(this._testNames.keys()); scope = (names?.length > 0) ? names[0] : undefined; @@ -25,10 +27,14 @@ export class AftLog { } } - get logMgr(): LogManager { - if (!this._logMgr) { - this._logMgr = new LogManager({logName: this.fullName}) + get aftCfg(): AftConfig { + return this._aftCfg; + } + + get reporter(): Reporter { + if (!this._rep) { + this._rep = new Reporter(this.fullName) } - return this._logMgr; + return this._rep; } } \ No newline at end of file diff --git a/packages/aft-jasmine-reporter/src/aft-test.ts b/packages/aft-jasmine-reporter/src/aft-test.ts index ccbf9505..03967919 100644 --- a/packages/aft-jasmine-reporter/src/aft-test.ts +++ b/packages/aft-jasmine-reporter/src/aft-test.ts @@ -1,6 +1,5 @@ -import { buildinfo, ProcessingResult, rand, TestResult, TestStatus } from "aft-core"; +import { rand, TestResult, TestStatus, Err, AftConfig, BuildInfoManager, Verifier, Func, Class } from "aft-core"; import { AftLog } from "./aft-log"; -import { shouldRun } from "./should-run"; import { TitleParser } from "./title-parser"; /** @@ -9,15 +8,20 @@ import { TitleParser } from "./title-parser"; */ export class AftTest extends AftLog { private _testcases: Array; - private _defects: Array; + private readonly _buildMgr: BuildInfoManager; /** * expects to be passed the scope from an executing Mocha * test (i.e. the `this` argument) * @param scope the `this` scope from within a Mocha `it` */ - constructor(scope?: any) { - super(scope); + constructor(scope?: any, aftCfg?: AftConfig) { + super(scope, aftCfg); + this._buildMgr = new BuildInfoManager(this.aftCfg); + } + + get buildInfoMgr(): BuildInfoManager { + return this._buildMgr; } get testcases(): Array { @@ -27,15 +31,8 @@ export class AftTest extends AftLog { return this._testcases; } - get defects(): Array { - if (!this._defects) { - this._defects = TitleParser.parseDefectIds(this.fullName); - } - return this._defects; - } - async pass(): Promise { - await this._logResult('Passed'); + await this._logResult('passed'); } async fail(): Promise { @@ -43,46 +40,59 @@ export class AftTest extends AftLog { if (this.test?.failedExpectations) { err = this.test.failedExpectations.map(e => `${e.message}\n${e.stack}`).join('\n'); } - await this._logResult('Failed', err); + await this._logResult('failed', err); } async pending(): Promise { - await this._logResult('Skipped', 'test skipped'); + await this._logResult('skipped', 'test skipped'); } + /** + * determines if any of the referenced Test Case ID's should be run according to the + * loaded `TestExecutionPolicyPlugin` implementations' `shouldRun` methods + * @returns `true` if test should be run, otherwise `false` + */ async shouldRun(): Promise { - let result: boolean = true; - - const should: Array = await Promise.all([ - shouldRun.tests(...this.testcases), - shouldRun.defects(...this.defects) - ]).catch(async (err) => { - await this.logMgr.warn(err); - return []; - }); - if (should?.length) { - if (!should.map(s => s.success).reduce((prev, curr) => prev && curr)) { - result = false; - await this.logMgr.warn(should.filter(s => !s.success).map(s => s.message).join('; ')); - } - } + const shouldRun = await this._getVerifier(Verifier).shouldRun(); + return shouldRun.result; + } - return result; + /** + * creates a new {Verifier} that will run the passed in `assertion` if the `shouldRun` function + * returns `true` otherwise it will bypass execution + * @param assertion a function that performs test actions and will accept a {Verifier} instance + * for use during the test actions' execution + * @param verifierType an optional {Verifier} class to use instead of the base {Verifier} type + * @returns a {Verifier} instance already configured with test cases, description, logger and config + */ + verify(assertion: Func, verifierType?: Class): T { + return this._getVerifier(verifierType) + .verify(assertion) as T; + } + + protected _getVerifier(verifierType?: Class): T { + verifierType ??= Verifier as Class; + return new verifierType() + .internals.usingReporter(this.reporter) + .internals.usingAftConfig(this.aftCfg) + .withDescription(this.fullName) + .withTestIds(...this.testcases) + .on('skipped', () => pending()) as T; } async dispose(): Promise { - await this.logMgr.dispose(); + await this.reporter.dispose(); } /** * creates `ITestResult` objects for each `testId` and sends these - * to the `LogManager.logResult` function + * to the `Reporter.logResult` function * @param result an `IProcessingResult` returned from executing the * expectation */ protected async _logResult(status: TestStatus, message?: string): Promise { try { - status = status || 'Untested'; + status = status || 'untested'; if (this.testcases.length) { this.testcases.forEach(async (testId: string) => { if (message) { @@ -99,31 +109,31 @@ export class AftTest extends AftLog { for (var i=0; i { - message = message || this.logMgr.logName; + message = message || this.reporter.reporterName; switch (status) { - case 'Blocked': - case 'Retest': - case 'Skipped': - case 'Untested': - await this.logMgr.warn(message); + case 'blocked': + case 'retest': + case 'skipped': + case 'untested': + await this.reporter.warn(message); break; - case 'Failed': - await this.logMgr.fail(message); + case 'failed': + await this.reporter.fail(message); break; - case 'Passed': + case 'passed': default: - await this.logMgr.pass(message); + await this.reporter.pass(message); break; } } @@ -144,7 +154,7 @@ export class AftTest extends AftLog { } protected async _generateTestResult(status: TestStatus, logMessage: string, testId?: string): Promise { - let result: TestResult = { + const result: TestResult = { testId: testId, created: Date.now(), resultId: rand.guid, @@ -152,8 +162,8 @@ export class AftTest extends AftLog { status: status, metadata: { durationMs: this.test.duration || 0, - buildName: await buildinfo.buildName() || 'unknown', - buildNumber: await buildinfo.buildNumber() || 'unknown' + buildName: await this.buildInfoMgr.buildName() || 'unknown', + buildNumber: await this.buildInfoMgr.buildNumber() || 'unknown' } }; return result; diff --git a/packages/aft-jasmine-reporter/src/should-run.ts b/packages/aft-jasmine-reporter/src/should-run.ts deleted file mode 100644 index f70acc0e..00000000 --- a/packages/aft-jasmine-reporter/src/should-run.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { Defect, DefectManager, defects, IHasOptions, ProcessingResult, TestCaseManager, testcases } from "aft-core"; - -export type ShouldRunOptions = { - testMgr?: TestCaseManager; - defectMgr?: DefectManager; -} - -export class ShouldRun implements IHasOptions { - private readonly _options: ShouldRunOptions; - - private _testMgr: TestCaseManager; - private _defectMgr: DefectManager; - - constructor(options?: ShouldRunOptions) { - this._options = options || {}; - } - - option(key: K, defaultVal?: V): V { - const result: V = this._options[key] as V; - return (result === undefined) ? defaultVal : result; - } - - get testMgr(): TestCaseManager { - if (!this._testMgr) { - this._testMgr = this.option('testMgr', testcases); - } - return this._testMgr; - } - - get defectMgr(): DefectManager { - if (!this._defectMgr) { - this._defectMgr = this.option('defectMgr', defects); - } - return this._defectMgr; - } - - async tests(...tests: string[]): Promise { - const shouldRunTests = new Array(); - const shouldNotRunTests = new Array(); - if (tests?.length) { - for (var i=0; i = await this.defectMgr.findDefects(testId) || new Array(); - if (defects.some((d: Defect) => d?.status == 'open')) { - let openDefects: string = defects - .filter((d: Defect) => d.status == 'open') - .map((d: Defect) => d.id) - .join(', '); - shouldNotRunTests.push(testId); - return { - success: false, - message: `the testId ${testId} has one or more open defects so test should not be run: [${openDefects}]` - }; - } else { - shouldRunTests.push(testId); - } - } else { - shouldNotRunTests.push(testId); - } - } - let shouldRun: boolean = shouldRunTests.length > 0; - if (!shouldRun) { - return {success: false, message: `none of the supplied tests should be run: [${tests.join(', ')}]`}; - } - } - return {success: true, message: 'returning the test IDs, as an array, that should be run', obj: shouldRunTests}; - } - - async defects(...defects: string[]): Promise { - // first search for any specified Defects by ID - if (defects?.length) { - for (var i=0; i with multiple ids ` where - * `['ID123', 'Another']` would be returned - * @param title the test full title to be parsed - * @returns an array of DefectId strings or empty array - */ - static parseDefectIds(title: string): Array { - return this._parseAll(title, /\<([^\<\>]+)\>/gi); - } - private static _parseAll(input: string, regex: RegExp): Array { const results = new Array(); const allMatches = [...input.matchAll(regex)]; diff --git a/packages/aft-jasmine-reporter/test/aft-jasmine-reporter.spec.ts b/packages/aft-jasmine-reporter/test/aft-jasmine-reporter.spec.ts index 81bff3df..8c2dc7a2 100644 --- a/packages/aft-jasmine-reporter/test/aft-jasmine-reporter.spec.ts +++ b/packages/aft-jasmine-reporter/test/aft-jasmine-reporter.spec.ts @@ -1,13 +1,14 @@ +import { Verifier, equaling } from "aft-core"; import { AftTest } from "../src"; import { AftLog } from "../src/aft-log"; describe('AftJasmineReporter', () => { it('can create an AftLog instance', async () => { const t = new AftLog(); - await t.logMgr.info('starting AftJasmineReporter test...'); + await t.reporter.info('starting AftJasmineReporter test...'); expect(t.test).toBeDefined(); expect(t.fullName).toEqual('AftJasmineReporter can create an AftLog instance'); - await t.logMgr.info('completed AftJasmineReporter test.'); + await t.reporter.info('completed AftJasmineReporter test.'); }); it('can check if test should be run [C1234]', async () => { @@ -30,4 +31,12 @@ describe('AftJasmineReporter', () => { expect(true).toBeFalse(); }); + + it('provides a Verifier instance for use in test control', async () => { + const t = new AftTest(this); + await t.verify(async (v: Verifier) => { + await v.reporter.warn('returning logName'); + return v.reporter.reporterName; + }).returns(equaling(t.reporter.reporterName)); + }); }); \ No newline at end of file diff --git a/packages/aft-jasmine-reporter/test/title-parser.spec.ts b/packages/aft-jasmine-reporter/test/title-parser.spec.ts index 5ae1ed62..c63b7440 100644 --- a/packages/aft-jasmine-reporter/test/title-parser.spec.ts +++ b/packages/aft-jasmine-reporter/test/title-parser.spec.ts @@ -23,27 +23,4 @@ describe('TitleParser', () => { expect(TitleParser.parseTestIds(d.title)).toEqual(d.expected); }); }); - - const ddata = [ - {title: '', expected: []}, - {title: '', expected: ['BUG-123']}, - {title: 'foo ', expected: ['BUG-123']}, - {title: ' foo', expected: ['BUG-123']}, - {title: 'foo foo', expected: ['BUG-123']}, - {title: ' ', expected: ['BUG-123', 'BUG-234']}, - {title: 'foo ', expected: ['BUG-123', 'BUG-234']}, - {title: ' foo ', expected: ['BUG-123', 'BUG-234']}, - {title: ' foo', expected: ['BUG-123', 'BUG-234']}, - {title: 'foo foo foo', expected: ['BUG-123', 'BUG-234']}, - {title: 'foo foo', expected: ['BUG-123', 'BUG-234']}, - {title: 'foo', expected: ['BUG-123', 'BUG-234']}, - {title: 'foo foo', expected: ['BUG-123', 'BUG-234']}, - {title: 'Bug name 123', expected: []}, - {title: 'foo [C1234] bar baz', expected: ['BUG-123']} - ]; - ddata.forEach((d) => { - it(`can parse defects from titles: '${d.title}'`, function () { - expect(TitleParser.parseDefectIds(d.title)).toEqual(d.expected); - }); - }); }); \ No newline at end of file diff --git a/packages/aft-jasmine-reporter/tsconfig.json b/packages/aft-jasmine-reporter/tsconfig.json index e3a0da5e..fd6f323a 100644 --- a/packages/aft-jasmine-reporter/tsconfig.json +++ b/packages/aft-jasmine-reporter/tsconfig.json @@ -4,5 +4,10 @@ "outDir": "dist", "composite": true }, - "include": ["src", "test"] + "include": ["src", "test"], + "references": [ + { "path": "../aft-core" }, + { "path": "../aft-reporting-filesystem" }, + { "path": "../aft-reporting-html" }, + ] } \ No newline at end of file diff --git a/packages/aft-logging-awskinesis/src/index.ts b/packages/aft-logging-awskinesis/src/index.ts deleted file mode 100644 index 0ea91e1e..00000000 --- a/packages/aft-logging-awskinesis/src/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './kinesis-logging-plugin'; \ No newline at end of file diff --git a/packages/aft-logging-awskinesis/test/kinesis-logging-plugin-spec.ts b/packages/aft-logging-awskinesis/test/kinesis-logging-plugin-spec.ts deleted file mode 100644 index 854f24fa..00000000 --- a/packages/aft-logging-awskinesis/test/kinesis-logging-plugin-spec.ts +++ /dev/null @@ -1,210 +0,0 @@ -import { KinesisLoggingPlugin, KinesisLoggingPluginOptions } from "../src/kinesis-logging-plugin"; -import { LogManager, LogManagerOptions, machineInfo, pluginloader, rand, TestResult } from "aft-core"; -import * as pkg from "../package.json"; -import * as Firehose from "aws-sdk/clients/firehose"; -import { KinesisLogRecord } from "../src/kinesis-log-record"; - -describe('KinesisLoggingPlugin', () => { - it('can batch messages for sending', async () => { - const config: KinesisLoggingPluginOptions = { - level: 'info', - batch: true, - batchSize: 10, - accessKeyId: rand.getString(20), - secretAccessKey: rand.getString(50) - }; - let plugin: KinesisLoggingPlugin = new KinesisLoggingPlugin(config); - let spyCheckAndSendLogs = spyOn(plugin, '_checkAndSendLogs').and.callThrough(); - let spySendBatch = spyOn(plugin, '_sendBatch').and.callFake((deliveryStream: string, records: Firehose.Record[]) => { - /* do nothing */ - }); - let spySend = spyOn(plugin, '_send').and.callFake((deliveryStream: string, record: Firehose.Record) => { - /* do nothing */ - }); - - const logName = rand.getString(10); - for (var i=0; i<20; i++) { - let logMessage: string = rand.getString(99, true, true); - await plugin.log({level: 'warn', message: logMessage, name: logName}); - } - - expect(spyCheckAndSendLogs).toHaveBeenCalledTimes(20); - expect(spySendBatch).toHaveBeenCalledTimes(2); - expect(spySend).toHaveBeenCalledTimes(0); - }); - - it('can disable batch sending of messages', async () => { - const config: KinesisLoggingPluginOptions = { - level: 'info', - batch: false, - batchSize: 10, - accessKeyId: rand.getString(20), - secretAccessKey: rand.getString(50) - }; - let plugin: KinesisLoggingPlugin = new KinesisLoggingPlugin(config); - let spyCheckAndSendLogs = spyOn(plugin, '_checkAndSendLogs').and.callThrough(); - let spySendBatch = spyOn(plugin, '_sendBatch').and.callFake((deliveryStream: string, records: Firehose.Record[]) => { - /* do nothing */ - }); - let spySend = spyOn(plugin, '_send').and.callFake((deliveryStream: string, record: Firehose.Record) => { - /* do nothing */ - }); - - for (var i=0; i<20; i++) { - let logMessage: string = rand.getString(99, true, true); - await plugin.log({level: 'warn', message: logMessage, name: rand.getString(10)}); - } - - expect(spyCheckAndSendLogs).toHaveBeenCalledTimes(20); - expect(spySendBatch).toHaveBeenCalledTimes(0); - expect(spySend).toHaveBeenCalledTimes(20); - }); - - it('sends any unsent batched logs on dispose', async () => { - const config: KinesisLoggingPluginOptions = { - level: 'info', - batch: true, - batchSize: 10, - accessKeyId: rand.getString(20), - secretAccessKey: rand.getString(50) - }; - let plugin: KinesisLoggingPlugin = new KinesisLoggingPlugin(config); - let spyCheckAndSendLogs = spyOn(plugin, '_checkAndSendLogs').and.callThrough(); - let spySendBatch = spyOn(plugin, '_sendBatch').and.callFake((deliveryStream: string, records: Firehose.Record[]) => { - /* do nothing */ - }); - let spySend = spyOn(plugin, '_send').and.callFake((deliveryStream: string, record: Firehose.Record) => { - /* do nothing */ - }); - - const logName = rand.getString(10); - for (var i=0; i<9; i++) { - let logMessage: string = rand.getString(99, true, true); - await plugin.log({level: 'warn', message: logMessage, name: logName}); - } - - expect(spyCheckAndSendLogs).toHaveBeenCalledTimes(9); - expect(spySendBatch).toHaveBeenCalledTimes(0); - expect(spySend).toHaveBeenCalledTimes(0); - - await plugin.dispose(logName); - - expect(spySendBatch).toHaveBeenCalledTimes(1); - expect(spySend).toHaveBeenCalledTimes(0); - - expect(plugin.logs(logName).length).toBe(0); - }); - - it('only sends messages of the appropriate level', async () => { - const config: KinesisLoggingPluginOptions = { - level: 'info', - batch: false, - batchSize: 10, - accessKeyId: rand.getString(20), - secretAccessKey: rand.getString(50) - }; - let plugin: KinesisLoggingPlugin = new KinesisLoggingPlugin(config); - let spyCheckAndSendLogs = spyOn(plugin, '_checkAndSendLogs').and.callThrough(); - let spySendBatch = spyOn(plugin, '_sendBatch').and.callFake((deliveryStream: string, records: Firehose.Record[]) => { - /* do nothing */ - }); - let spySend = spyOn(plugin, '_send').and.callFake((deliveryStream: string, record: Firehose.Record) => { - /* do nothing */ - }); - - await plugin.log({level: 'debug', message: rand.guid, name: rand.getString(10)}); - await plugin.log({level: 'info', message: rand.guid, name: rand.getString(10)}); - await plugin.log({level: 'warn', message: rand.guid, name: rand.getString(10)}); - - expect(spyCheckAndSendLogs).toHaveBeenCalledTimes(2); - expect(spySendBatch).toHaveBeenCalledTimes(0); - expect(spySend).toHaveBeenCalledTimes(2); - }); - - it('adds expected fields to the log record', async () => { - const config: KinesisLoggingPluginOptions = { - level: 'info', - batch: false, - batchSize: 10, - accessKeyId: rand.getString(20), - secretAccessKey: rand.getString(50) - }; - let plugin: KinesisLoggingPlugin = new KinesisLoggingPlugin(config); - const store = new Map(); - let spySend = spyOn(plugin, '_send').and.callFake((deliveryStream: string, record: Firehose.Record) => { - store.set('_send', record); - }); - - let expectedMessage: string = rand.guid; - await plugin.log({level: 'warn', message: expectedMessage, name: 'adds expected fields to the log record'}); - - let logRecord: Firehose.Record = store.get('_send'); - let data: KinesisLogRecord = JSON.parse(logRecord.Data.toString()) as KinesisLogRecord; - expect(data.level).toEqual('warn'); - expect(data.logName).toEqual('adds expected fields to the log record'); - expect(data.message).toEqual(expectedMessage); - expect(data.machineInfo).toEqual(machineInfo.data); - expect(data.result).toBeUndefined(); - expect(data.version).toEqual(pkg.version); - }); - - /** - * WARNING: this test sends an actual message to the Kinesis logMgr - * only for use in debugging issues locally - */ - xit('can send real logs and ITestResult objects', async () => { - const config: KinesisLoggingPluginOptions = { - level: 'trace', - batch: true, - batchSize: 10, - accessKeyId: '%AWS_ACCESS_KEY_ID%', - secretAccessKey: '%AWS_SECRET_ACCESS_KEY%', - sessionToken: '%AWS_SESSION_TOKEN', - deliveryStream: '%kinesis_deliverystream%', - region: '%AWS_REGION%' - }; - let plugin: KinesisLoggingPlugin = new KinesisLoggingPlugin(config); - - let result: TestResult = { - resultId: rand.guid, - created: Date.now(), - testId: 'C' + rand.getInt(100, 9999), - resultMessage: rand.getString(100), - status: 'Skipped' - }; - let message: string = rand.getString(250); - - const logName = rand.getString(10, true, true, true, true); - await plugin.log({level: 'info', message: message, name: logName}); - await plugin.logResult(logName, result); - await plugin.dispose(logName); - }); - - it('can be loaded by the LogManager', async () => { - const config: LogManagerOptions = { - logName: 'can be loaded by the LogManager', - plugins: [{ - name: 'kinesis-logging-plugin', - options: { - batch: false, - batchSize: 0, - level: 'error', - accessKeyId: rand.getString(20), - secretAccessKey: rand.getString(50), - enabled: false - } as KinesisLoggingPluginOptions - }] - }; - pluginloader.clear(); - const mgr: LogManager = new LogManager(config); - const plugins = await mgr.plugins(); - const plugin = plugins[0]; - - expect(plugin).toBeDefined(); - expect(plugin.level).toEqual('error'); - expect((plugin as KinesisLoggingPlugin).batch).toBe(false); - expect(await (plugin as KinesisLoggingPlugin).client()).toBeDefined(); - expect(plugin.constructor.name).toEqual('KinesisLoggingPlugin'); - expect(plugin.enabled).toBeFalse(); - }, 25000); -}); \ No newline at end of file diff --git a/packages/aft-logging-filesystem/src/filesystem-logging-plugin.ts b/packages/aft-logging-filesystem/src/filesystem-logging-plugin.ts deleted file mode 100644 index 854554a3..00000000 --- a/packages/aft-logging-filesystem/src/filesystem-logging-plugin.ts +++ /dev/null @@ -1,104 +0,0 @@ -import * as path from "path"; -import { convert, fileio, LoggingPlugin, LoggingPluginOptions, LogLevel, LogMessageData, Merge, Err, TestResult } from "aft-core"; -import * as date from "date-and-time"; - -export type FilesystemLoggingPluginOptions = Merge; - -export class FilesystemLoggingPlugin extends LoggingPlugin { - private _outputPath: string; - private _includeResults: boolean; - private _dateFormat: string; - - get outputPath(): string { - if (!this._outputPath) { - let dir: string = this.option('outputPath', path.join('.', 'logs')); - if (!path.isAbsolute(dir)) { - dir = path.join(process.cwd(), dir); - } - this._outputPath = dir; - } - return this._outputPath; - } - - get includeResults(): boolean { - if (this._includeResults == null) { - this._includeResults = this.option('includeResults', true); - } - return this._includeResults; - } - - get dateFormat(): string { - if (!this._dateFormat) { - this._dateFormat = this.option('dateFormat', 'YYYY-MM-DD HH:mm:ss.SSS'); - } - return this._dateFormat; - } - - async log(message: LogMessageData): Promise { - this._appendToFile(message); - } - - async logResult(logName: string, result: TestResult): Promise { - if (this.includeResults) { - let level: LogLevel; - switch(result.status) { - case 'Failed': - level = 'fail'; - break; - case 'Passed': - level = 'pass'; - break; - case 'Blocked': - case 'Skipped': - level = 'warn'; - break; - default: - level = 'info'; - break; - } - const data: LogMessageData = { - name: logName, - level: level, - message: JSON.stringify(result) - }; - this._appendToFile(data); - } - } - - async dispose(logName: string, err?: Error): Promise { - if (err) { - const data: LogMessageData = { - name: logName, - level: 'error', - message: Err.full(err) - }; - this._appendToFile(data); - } - } - - private _appendToFile(data: LogMessageData): void { - if (LogLevel.toValue(data.level) >= LogLevel.toValue(this.level) && data.level != 'none') { - const filename = convert.toSafeString(data.name); - const fullPath = path.join(this.outputPath, `${filename}.log`); - const lock = fileio.getExpiringFileLock(fullPath, 15, 10); - try { - fileio.append(fullPath, `${this._format(data)}\n`); - } finally { - lock.unlock(); - } - } - } - - private _format(data: LogMessageData): string { - data = data || {}; - if (!data.message) { data.message = ''; } - if (!data.level) { data.level = 'none' } - let d: string = date.format(new Date(), this.dateFormat); - let out: string = `[${d}] - ${data.level.toUpperCase()} - ${data.message}`; - return out; - } -} \ No newline at end of file diff --git a/packages/aft-logging-filesystem/src/index.ts b/packages/aft-logging-filesystem/src/index.ts deleted file mode 100644 index 90fd9063..00000000 --- a/packages/aft-logging-filesystem/src/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./filesystem-logging-plugin"; \ No newline at end of file diff --git a/packages/aft-logging-filesystem/test/filesystem-logging-plugin-spec.ts b/packages/aft-logging-filesystem/test/filesystem-logging-plugin-spec.ts deleted file mode 100644 index 1232199c..00000000 --- a/packages/aft-logging-filesystem/test/filesystem-logging-plugin-spec.ts +++ /dev/null @@ -1,154 +0,0 @@ -import * as fs from "fs"; -import * as path from "path"; -import { convert, rand } from "aft-core"; -import { FilesystemLoggingPlugin } from "../src/filesystem-logging-plugin"; - -describe('FilesystemLoggingPlugin', () => { - beforeEach(() => { - const logDir = path.join(process.cwd(), 'logs'); - if (fs.existsSync(logDir)) { - fs.rmSync(logDir, {recursive: true, force: true}); - } - }); - - it('can create a file on the filesystem and write logs to it', async () => { - const plugin = new FilesystemLoggingPlugin({ - level: 'trace' - }); - const logName = 'can create a file on the filesystem and write logs to it'; - await plugin.log({ - name: logName, - level: 'trace', - message: rand.getString(rand.getInt(100, 200)) - }); - await plugin.log({ - name: logName, - level: 'info', - message: rand.getString(rand.getInt(100, 200)) - }); - await plugin.log({ - name: logName, - level: 'error', - message: rand.getString(rand.getInt(100, 200)) - }); - await plugin.logResult(logName, { - resultId: rand.guid, - created: Date.now(), - status: 'Passed' - }); - await plugin.logResult(logName, { - resultId: rand.guid, - created: Date.now(), - status: 'Skipped' - }); - await plugin.logResult(logName, { - resultId: rand.guid, - created: Date.now(), - status: 'Failed' - }); - await plugin.logResult(logName, { - resultId: rand.guid, - created: Date.now(), - status: 'Untested' - }); - - const filePath = path.join(process.cwd(), 'logs', `${convert.toSafeString(logName)}.log`); - expect(fs.existsSync(filePath)).toBeTrue(); - - const lines: Array = fs.readFileSync(filePath, {encoding: 'utf-8'})?.split('\n') || []; - expect(lines.length).toBe(8); // 7 logged lines plus one empty due to newline at end of each line - expect(lines[0]).toContain('TRACE'); - expect(lines[6]).toContain('INFO'); - expect(lines[7]).toEqual(''); - }); - - it('will not write to file if level below specified value', async () => { - const plugin = new FilesystemLoggingPlugin({ - level: 'error' - }); - const logName = 'will not write to file if level below specified value'; - await plugin.log({ - name: logName, - level: 'trace', - message: rand.getString(rand.getInt(100, 200)) - }); - await plugin.log({ - name: logName, - level: 'debug', - message: rand.getString(rand.getInt(100, 200)) - }); - await plugin.log({ - name: logName, - level: 'info', - message: rand.getString(rand.getInt(100, 200)) - }); - await plugin.log({ - name: logName, - level: 'step', - message: rand.getString(rand.getInt(100, 200)) - }); - await plugin.log({ - name: logName, - level: 'pass', - message: rand.getString(rand.getInt(100, 200)) - }); - await plugin.log({ - name: logName, - level: 'fail', - message: rand.getString(rand.getInt(100, 200)) - }); - await plugin.log({ - name: logName, - level: 'warn', - message: rand.getString(rand.getInt(100, 200)) - }); - await plugin.log({ - name: logName, - level: 'error', - message: rand.getString(rand.getInt(100, 200)) - }); - - const filePath = path.join(process.cwd(), 'logs', `${convert.toSafeString(logName)}.log`); - expect(fs.existsSync(filePath)).toBeTrue(); - - const lines: Array = fs.readFileSync(filePath, {encoding: 'utf-8'})?.split('\n') || []; - expect(lines.length).toBe(2); - expect(lines[0]).toContain('ERROR'); - expect(lines[1]).toEqual(''); - }); - - it('can change the date formatting', async () => { - const logName = 'can change the date formatting'; - const plugin = new FilesystemLoggingPlugin({ - level: 'info', - dateFormat: 'SSS' - }); - - await plugin.log({name: logName, level: 'warn', message: rand.getString(rand.getInt(100, 200))}); - - const filePath = path.join(process.cwd(), 'logs', `${convert.toSafeString(logName)}.log`); - expect(fs.existsSync(filePath)).toBeTrue(); - - const lines: Array = fs.readFileSync(filePath, {encoding: 'utf-8'})?.split('\n') || []; - expect(lines.length).toBe(2); - expect(lines[0]).toMatch(/^\[[0-9]{3}\] - WARN - .+$/); - expect(lines[1]).toEqual(''); - }); - - it('can disable output of TestResult objects', async () => { - const logName = 'can disable output of TestResult objects'; - const plugin = new FilesystemLoggingPlugin({ - level: 'trace', - includeResults: false - }); - - await plugin.logResult(logName, { - resultId: rand.guid, - created: Date.now(), - status: 'Passed' - }); - - const filePath = path.join(process.cwd(), 'logs', `${convert.toSafeString(logName)}.log`); - expect(fs.existsSync(filePath)).toBeFalse(); - }); -}); \ No newline at end of file diff --git a/packages/aft-logging-html/src/html-logging-plugin.ts b/packages/aft-logging-html/src/html-logging-plugin.ts deleted file mode 100644 index 524d3be7..00000000 --- a/packages/aft-logging-html/src/html-logging-plugin.ts +++ /dev/null @@ -1,117 +0,0 @@ -import * as path from "path"; -import { LoggingPlugin, LogLevel, TestResult, fileio, ExpiringFileLock, FileSystemMap, LogMessageData, Merge, LoggingPluginOptions, convert } from "aft-core"; -import { HtmlTestResult } from "./html-test-result"; -import { HtmlResult } from "./html-result"; -import { htmlTemplate } from "./templates/html-template"; - -export type HtmlLoggingPluginOptions = Merge; - -export class HtmlLoggingPlugin extends LoggingPlugin { - private readonly _results: FileSystemMap>; - private readonly _logs: FileSystemMap>; - - constructor(options?: HtmlLoggingPluginOptions) { - super(options); - this._results = new FileSystemMap>('htmlSharedResults'); - this._logs = new FileSystemMap>('htmlSharedLogs') - } - - get fileName(): string { - return this.option('fileName', 'testresults.html'); - } - - get outputDir(): string { - let dir: string = this.option('outputDir', process.cwd()); - if (!path.isAbsolute(dir)) { - dir = path.join(process.cwd(), dir); - } - return dir; - } - - get fullPathAndFile(): string { - let fullPathAndFile: string; - let filePath: string = this.outputDir; - let fileName: string = this.fileName; - if (filePath && fileName) { - fullPathAndFile = path.join(filePath, fileName); - } else { - fullPathAndFile = path.join(process.cwd(), 'testresults.html'); - } - return fullPathAndFile; - } - - get maxLogLines(): number { - return this.option('maxLogLines', 5); - } - - logs(key: string, val?: Array): Array { - if (!this._logs.has(key)) { - this._logs.set(key, new Array()); - } - if (val) { - this._logs.set(key, val); - } - return this._logs.get(key); - } - - testResults(key: string, val?: Array): Array { - if (!this._results.has(key)) { - this._results.set(key, new Array()); - } - if (val) { - this._results.set(key, val); - } - return this._results.get(key); - } - - override async log(data: LogMessageData): Promise { - let expectedLevel: LogLevel = this.level; - if (LogLevel.toValue(data.level) >= LogLevel.toValue(expectedLevel) && data.level != 'none') { - const logs = this.logs(data.name); - logs.push(`${data.level} - ${data.message}`); - let max: number = this.maxLogLines; - while (logs.length > max) { - logs.shift(); - logs[0] = `...
    ${logs[0]}`; - } - this.logs(data.name, logs); - } - } - - override async logResult(logName: string, result: TestResult): Promise { - let htmlTestResult: HtmlTestResult = { - testId: result.testId, - status: result.status, - logs: this.logs(logName) - } - const results: Array = this.testResults(logName); - results.push(htmlTestResult); - this.testResults(logName, results); - } - - override async dispose(logName: string, error?: Error): Promise { - const htmlResults: HtmlResult[] = new Array(); - this._results.forEach((result: Array, key: string) => { - htmlResults.push({ - description: convert.toSafeString(key), - tests: result - }); - }); - await this._regenerateHtmlFile(htmlResults); - this._logs.delete(logName); - } - - private async _regenerateHtmlFile(results: HtmlResult[]): Promise { - const fullPathAndFile = this.fullPathAndFile; - const lock: ExpiringFileLock = fileio.getExpiringFileLock(fullPathAndFile, 30000, 10000); - try { - fileio.write(fullPathAndFile, htmlTemplate.emit(...results)); - } finally { - lock.unlock(); - } - } -} \ No newline at end of file diff --git a/packages/aft-logging-html/src/index.ts b/packages/aft-logging-html/src/index.ts deleted file mode 100644 index 11387982..00000000 --- a/packages/aft-logging-html/src/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './html-logging-plugin'; \ No newline at end of file diff --git a/packages/aft-logging-html/test/html-logging-plugin-spec.ts b/packages/aft-logging-html/test/html-logging-plugin-spec.ts deleted file mode 100644 index 4b489bc2..00000000 --- a/packages/aft-logging-html/test/html-logging-plugin-spec.ts +++ /dev/null @@ -1,171 +0,0 @@ -import * as fs from "fs"; -import * as path from "path"; -import { LogManager, rand, TestResult, LogManagerOptions } from "aft-core"; -import { HtmlLoggingPlugin, HtmlLoggingPluginOptions } from "../src"; -import { HtmlResult } from "../src/html-result"; - -describe('HtmlLoggingPlugin', () => { - beforeEach(() => { - let c: string = path.join(process.cwd(), 'FileSystemMap', 'htmlSharedResults.json'); - if (fs.existsSync(c)) {fs.unlinkSync(c);} - let d: string = path.join(process.cwd(), 'FileSystemMap', 'htmlSharedLogs.json'); - if (fs.existsSync(d)) {fs.unlinkSync(d);} - let e: string = path.join(process.cwd(), 'testresults.html'); - if (fs.existsSync(e)) {fs.unlinkSync(e);} - }); - - it('stores the specified number of log lines', async () => { - const config: HtmlLoggingPluginOptions = { - level: 'info', - maxLogLines: 14 - }; - let plugin: HtmlLoggingPlugin = new HtmlLoggingPlugin(config); - const logName = rand.getString(50); - for (var i=0; i<25; i++) { - await plugin.log({level: 'info', message: rand.getString(100), name: logName}); - } - - let actual: string[] = plugin.logs(logName); - expect(actual.length).toBe(14); - }); - - it('adds an ellipsis to the oldest log line only when exceeded maxLogLines', async () => { - const config: HtmlLoggingPluginOptions = { - level: 'info', - maxLogLines: 3 - }; - let plugin: HtmlLoggingPlugin = new HtmlLoggingPlugin(config); - const logName = rand.getString(50); - for (var i=0; i<3; i++) { - await plugin.log({level: 'info', message: rand.getString(100), name: logName}); - } - - let actual: string[] = plugin.logs(logName); - expect(actual.length).toBe(3); - expect(actual[0]).not.toContain('...'); - - await plugin.log({level: 'info', message: rand.getString(100), name: logName}); - - actual = plugin.logs(logName); - expect(actual.length).toBe(3); - expect(actual[0]).toContain('...'); - }); - - it('stores logs only when at or above the specified level', async () => { - const config: HtmlLoggingPluginOptions = { - level: 'step', - maxLogLines: 14 - }; - let plugin: HtmlLoggingPlugin = new HtmlLoggingPlugin(config); - const logName = 'stores logs only when at or above the specified level'; - await plugin.log({level: 'none', message: 'level none', name: logName}); - await plugin.log({level: 'trace', message: 'level trace', name: logName}); - await plugin.log({level: 'debug', message: 'level debug', name: logName}); - await plugin.log({level: 'info', message: 'level info', name: logName}); - await plugin.log({level: 'step', message: 'level step', name: logName}); - await plugin.log({level: 'warn', message: 'level warn', name: logName}); - await plugin.log({level: 'pass', message: 'level pass', name: logName}); - await plugin.log({level: 'fail', message: 'level fail', name: logName}); - await plugin.log({level: 'error', message: 'level error', name: logName}); - - let actual: string[] = plugin.logs(logName); - expect(actual.length).toBe(5); - expect(actual).not.toContain('level none'); - expect(actual).not.toContain('level trace'); - expect(actual).not.toContain('level debug'); - expect(actual).not.toContain('level info'); - }); - - it('can be loaded successfully from the LogManager', async () => { - const config: LogManagerOptions = { - logName: 'can be loaded successfully from the LogManager', - plugins: ['html-logging-plugin'] - }; - let logMgr: LogManager = new LogManager(config); - let plugin = await logMgr.first(); - - expect(plugin).toBeDefined(); - expect(plugin.constructor.name).toEqual('HtmlLoggingPlugin'); - }); - - it('only attempts to write to HTML file on call to dispose', async () => { - const config: HtmlLoggingPluginOptions = { - outputDir: './', - fileName: 'testresults.html' - }; - let plugin: HtmlLoggingPlugin = new HtmlLoggingPlugin(config); - const readSpy = spyOn(plugin, 'logs').and.returnValue(['foo', 'bar', 'baz']); - const testResults: Map> = new Map>([ - ['Fake Test One', [ - {testId: 'C123', status: 'Failed', resultId: rand.guid, created: Date.now()}, - {testId: 'C234', status: 'Passed', resultId: rand.guid, created: Date.now()} - ]], - ["Fake 'Test' Two", [ - {testId: 'C345', status: 'Passed', resultId: rand.guid, created: Date.now()}, - {testId: 'C456', status: 'Passed', resultId: rand.guid, created: Date.now()} - ]], - ["Fake [Test] ", [ - {status: 'Passed', resultId: rand.guid, created: Date.now()} - ]] - ]); - testResults.forEach(async (val: Array, key: string) => { - for (var i=0; i(plugin, '_regenerateHtmlFile').and.callFake((results: HtmlResult[]) => { - actualResults = results; - }); - - const logName = 'only attempts to write to sharedCache and HTML file on call to dispose'; - await plugin.log({level: 'info', message: 'fake log message', name: logName}); - const expectedResult: TestResult = {testId: 'C567', resultId: rand.guid, status: 'Passed', created: Date.now()}; - await plugin.logResult(logName, expectedResult); - - expect(regenSpy).not.toHaveBeenCalled(); - - await plugin.dispose(logName); - - expect(regenSpy).toHaveBeenCalledTimes(1); - expect(actualResults).toHaveSize(4); - }); - - it('can generate HTML result file', async () => { - const config: HtmlLoggingPluginOptions = { - outputDir: './', - fileName: 'testresults.html' - }; - let plugin: HtmlLoggingPlugin = new HtmlLoggingPlugin(config); - const readSpy = spyOn(plugin, 'logs').and.returnValue(['foo', 'bar', 'baz']); - const testResults: Map> = new Map>([ - ['Fake Test One', [ - {testId: 'C123', status: 'Failed', resultId: rand.guid, created: Date.now()}, - {testId: 'C234', status: 'Passed', resultId: rand.guid, created: Date.now()} - ]], - ["Fake 'Test' Two", [ - {testId: 'C345', status: 'Passed', resultId: rand.guid, created: Date.now()}, - {testId: 'C456', status: 'Passed', resultId: rand.guid, created: Date.now()} - ]], - ["Fake [Test] ", [ - {status: 'Passed', resultId: rand.guid, created: Date.now()} - ]] - ]); - testResults.forEach(async (val: Array, key: string) => { - for (var i=0; i **!!WARNING!!** using arrow functions in your Spec definition **IS NOT SUPPORTED** if using `AftLog` because it removes the `this` scope ```javascript describe('YourTestSuite', () => { - it('allows you to log using AFT LogManager', async function() { + it('allows you to log using AFT Reporter', async function() { const aft = new AftLog(this); - await aft.logMgr.step('starting test...'); + await aft.reporter.step('starting test...'); /* do some test things here */ - await aft.logMgr.step('test is complete'); + await aft.reporter.step('test is complete'); }); }); ``` -and which would output the following to your console and any AFT `LoggingPlugin` instances referenced in your `aftconfig.json` (assuming your test expectations all pass) +and which would output the following to your console and any AFT `ReportingPlugin` instances referenced in your `aftconfig.json` (assuming your test expectations all pass) ```text -17:52:45 - [YourTestSuite allows you to log using AFT LogManager] - STEP - starting test... -17:54:02 - [YourTestSuite allows you to log using AFT LogManager] - STEP - test is complete -17:54:02 - [YourTestSuite allows you to log using AFT LogManager] - PASS - YourTestSuite allows you to log using AFT LogManager +17:52:45 - [YourTestSuite allows you to log using AFT Reporter] - STEP - starting test... +17:54:02 - [YourTestSuite allows you to log using AFT Reporter] - STEP - test is complete +17:54:02 - [YourTestSuite allows you to log using AFT Reporter] - PASS - YourTestSuite allows you to log using AFT Reporter ``` ### `AftTest` -the `AftTest` class extends from the `AftLog` adding the ability to parse the Spec name for any referenced Test or Defect IDs. each Test ID must be surrounded with square brackets `[ABC123]` and each Defect ID with less than and greater than symbols ``. additionally you can then call the `AftTest.shouldRun()` async function which will determine if your test should be run based on any AFT `TestCasePlugin` and `DefectPlugin` instances referenced in your `aftconfig.json` file. using the `AftTest` class would look like the following: +the `AftTest` class extends from the `AftLog` adding the ability to parse the Spec name for any referenced Test. each Test ID must be surrounded with square brackets `[ABC123]`. you can then either directly call the `AftTest.shouldRun()` async function which will determine if your test should be run based on any AFT `TestExecutionPolicyPlugin` instances referenced in your `aftconfig.json` file or you can call `AftTest.verify(assertion)` which will perform the `AftTest.shouldRun()` call and mark the test as skipped if it should not be run. using the `AftTest` class would look like the following: > **!!WARNING!!** using arrow functions in your Spec definition **IS NOT SUPPORTED** if using `AftTest` because it removes the `this` scope ```javascript describe('YourTestSuite', () => { - it('can check if test [C1234] with known defect should be run', async function() { + it('can check if test [C1234] should be run', async function() { const aft = new AftTest(this); - const shouldRun = await aft.shouldRun(); - if (!shouldRun) { - aft.test.skip(); - } - await aft.logMgr.error('we should never get here if C1234 should not be run or BUG-123 is open'); + await aft.verify(async (v: Verifier) => { + // `verify` calls `v.test.skip()` if should not be run + await v.reporter.error('we should never get here if C1234 should not be run'); + const result = await doStuff(); + return result; + }).returns(equaling('expected')); }); }); ``` -which would output the following to your console and any AFT `LoggingPlugin` instances referenced in your `aftconfig.json` if the test ID should not be run: +which would output the following to your console and any AFT `ReportingPlugin` instances referenced in your `aftconfig.json` if the test ID should not be run: ```text -17:52:45 - [YourTestSuite can check if test [C1234] with known defect should be run] - WARN - none of the supplied tests should be run: [C1234] -17:52:45 - [YourTestSuite can check if test [C1234] with known defect should be run] - WARN - test skipped +17:52:45 - [YourTestSuite can check if test [C1234] should be run] - WARN - none of the supplied tests should be run: [C1234] +17:52:45 - [YourTestSuite can check if test [C1234] should be run] - WARN - test skipped ``` ## NOTES @@ -67,10 +69,7 @@ which would output the following to your console and any AFT `LoggingPlugin` ins - you can use the AFT `Verifier` in combination with the `AftLog` or `AftTest` classes like follows: ```javascript const aft = new AftTest(); -await verify(() => { +await aft.verify((v: Verifier) => { /* perform testing here */ -}).withLogManager(aft.logMgr) -.and.withTestIds(...aft.testcases) -.and.withKnownDefectIds(...aft.defects) -.returns(expected); +}).returns(expected); ``` \ No newline at end of file diff --git a/packages/aft-mocha-reporter/aftconfig.json b/packages/aft-mocha-reporter/aftconfig.json index 91454232..6a5f08ac 100644 --- a/packages/aft-mocha-reporter/aftconfig.json +++ b/packages/aft-mocha-reporter/aftconfig.json @@ -1,19 +1,8 @@ { - "LogManager": { - "level": "info", - "plugins": [{ - "name": "html-logging-plugin", - "searchDirectory": "../", - "options": { - "level": "warn" - } - }, { - "name": "filesystem-logging-plugin", - "searchDirectory": "../", - "options": { - "includeResults": false, - "level": "trace" - } - }] - } + "pluginNames": [ + "html-reporting-plugin", + "filesystem-reporting-plugin" + ], + "pluginsSearchDir": "../", + "logLevel": "debug" } \ No newline at end of file diff --git a/packages/aft-mocha-reporter/package.json b/packages/aft-mocha-reporter/package.json index eb55e019..20c20f77 100644 --- a/packages/aft-mocha-reporter/package.json +++ b/packages/aft-mocha-reporter/package.json @@ -1,14 +1,14 @@ { "name": "aft-mocha-reporter", - "version": "9.0.0", + "version": "10.0.0", "description": "Automated Functional Testing (AFT) Reporter for use with Mocha Test Framework", "main": "./dist/src/index.js", "types": "./dist/src/index.d.ts", "scripts": { "clean": "rimraf ./dist && rimraf ./logs && rimraf ./FileSystemMap && rimraf ./testresults.html", "build": "npm run clean && tsc --build", - "test": "npm run build && mocha", - "coverage": "nyc npm run test" + "test": "npm run build && npx mocha", + "coverage": "npm run build && nyc npx mocha" }, "repository": { "type": "git", @@ -30,15 +30,15 @@ }, "homepage": "https://github.com/bicarbon8/automated-functional-testing#readme", "dependencies": { - "aft-core": "^9.0.0", + "aft-core": "^10.0.0", "mocha": "^10.0.0" }, "devDependencies": { "@types/mocha": "^9.1.1", "@types/node": "^18.0.0", "@types/sinon": "^10.0.12", - "aft-logging-filesystem": "^9.0.0", - "aft-logging-html": "^9.0.0", + "aft-reporting-filesystem": "^10.0.0", + "aft-reporting-html": "^10.0.0", "chai": "^4.3.6", "nyc": "^15.1.0", "rimraf": "^3.0.2", diff --git a/packages/aft-mocha-reporter/src/aft-log.ts b/packages/aft-mocha-reporter/src/aft-log.ts index 4b0a99fd..9a131e92 100644 --- a/packages/aft-mocha-reporter/src/aft-log.ts +++ b/packages/aft-mocha-reporter/src/aft-log.ts @@ -1,12 +1,14 @@ -import { FileSystemMap, LogManager } from "aft-core"; +import { AftConfig, Reporter, aftConfig } from "aft-core"; export class AftLog { - private _logMgr: LogManager; + private _rep: Reporter; public readonly test: Mocha.Test; + public readonly aftCfg: AftConfig; - constructor(scope?: any) { + constructor(scope?: any, aftCfg?: AftConfig) { this.test = scope?.test || {}; + this.aftCfg = aftCfg ?? aftConfig; } get fullTitle(): string { @@ -17,14 +19,14 @@ export class AftLog { } } - get logMgr(): LogManager { - if (!this._logMgr) { - this._logMgr = new LogManager({logName: this.fullTitle}) + get reporter(): Reporter { + if (!this._rep) { + this._rep = new Reporter(this.fullTitle, this.aftCfg); } - return this._logMgr; + return this._rep; } async dispose(): Promise { - await this.logMgr.dispose(); + await this.reporter.dispose(); } } \ No newline at end of file diff --git a/packages/aft-mocha-reporter/src/aft-test.ts b/packages/aft-mocha-reporter/src/aft-test.ts index 633d90cb..6538b332 100644 --- a/packages/aft-mocha-reporter/src/aft-test.ts +++ b/packages/aft-mocha-reporter/src/aft-test.ts @@ -1,6 +1,5 @@ -import { buildinfo, ProcessingResult, rand, TestResult, TestStatus } from "aft-core"; +import { rand, TestResult, TestStatus, Err, AftConfig, BuildInfoManager, Func, Verifier, Class } from "aft-core"; import { AftLog } from "./aft-log"; -import { shouldRun } from "./should-run"; import { TitleParser } from "./title-parser"; /** @@ -8,75 +7,84 @@ import { TitleParser } from "./title-parser"; * from the Mocha test context */ export class AftTest extends AftLog { - private _testcases: Array; - private _defects: Array; + private readonly _testcases: Array; + private readonly _buildMgr: BuildInfoManager; /** * expects to be passed the scope from an executing Mocha * test (i.e. the `this` argument) * @param scope the `this` scope from within a Mocha `it` */ - constructor(scope?: any) { - super(scope); + constructor(scope?: any, aftCfg?: AftConfig) { + super(scope, aftCfg); + this._buildMgr = new BuildInfoManager(this.aftCfg); + this._testcases = TitleParser.parseTestIds(this.fullTitle); } + /** + * an array of test ID's parsed from the test title where test ID's + * are expected to be in the surrounded by `[` and `]` like: `"[TESTID]"` + */ get testcases(): Array { - if (!this._testcases) { - this._testcases = TitleParser.parseTestIds(this.fullTitle); - } return this._testcases; } - get defects(): Array { - if (!this._defects) { - this._defects = TitleParser.parseDefectIds(this.fullTitle); - } - return this._defects; - } - async pass(): Promise { - await this._logResult('Passed'); + await this._logResult('passed'); } async fail(err: any): Promise { const message: string = (err.message) ? err.message : String(err); const stack: string = (err.stack) ? `\n${err.stack}` : ''; - await this._logResult('Failed', `${message}${stack}`); + await this._logResult('failed', `${message}${stack}`); } async pending(): Promise { - await this._logResult('Skipped', 'test skipped'); + await this._logResult('skipped', 'test skipped'); } + /** + * determines if any of the referenced Test Case ID's should be run according to the + * loaded `TestExecutionPolicyPlugin` implementations' `shouldRun` methods + * @returns `true` if test should be run, otherwise `false` + */ async shouldRun(): Promise { - let result: boolean = true; + const shouldRun = await this._getVerifier(Verifier).shouldRun(); + return shouldRun.result; + } - const should: Array = await Promise.all([ - shouldRun.tests(...this.testcases), - shouldRun.defects(...this.defects) - ]).catch(async (err) => { - await this.logMgr.warn(err); - return []; - }); - if (should?.length) { - if (!should.map(s => s.success).reduce((prev, curr) => prev && curr)) { - result = false; - await this.logMgr.warn(should.filter(s => !s.success).map(s => s.message).join('; ')); - } - } + /** + * creates a new {Verifier} that will run the passed in `assertion` if the `shouldRun` function + * returns `true` otherwise it will bypass execution + * @param assertion a function that performs test actions and will accept a {Verifier} instance + * for use during the test actions' execution + * @param verifierType an optional {Verifier} class to use instead of the base {Verifier} type + * @returns a {Verifier} instance already configured with test cases, description, logger and config + */ + verify(assertion: Func, verifierType?: Class): T { + return this._getVerifier(verifierType) + .verify(assertion) as T; + } - return result; + protected _getVerifier(verifierType?: Class): T { + verifierType ??= Verifier as Class; + return new verifierType() + .internals.usingReporter(this.reporter) + .internals.usingAftConfig(this.aftCfg) + .withDescription(this.fullTitle) + .withTestIds(...this.testcases) + .on('skipped', () => this.test.skip()) as T; } /** * creates `ITestResult` objects for each `testId` and sends these - * to the `LogManager.logResult` function + * to the `Reporter.logResult` function * @param result an `IProcessingResult` returned from executing the * expectation */ - protected async _logResult(status: TestStatus, message?: string): Promise { + protected async _logResult(status: TestStatus, message?: string): Promise { try { - status = status || 'Untested'; + status = status || 'untested'; if (this.testcases.length) { this.testcases.forEach(async (testId: string) => { if (message) { @@ -93,31 +101,31 @@ export class AftTest extends AftLog { for (var i=0; i { - message = message || this.logMgr.logName; + message = message || this.reporter.reporterName; switch (status) { - case 'Blocked': - case 'Retest': - case 'Skipped': - case 'Untested': - await this.logMgr.warn(message); + case 'blocked': + case 'retest': + case 'skipped': + case 'untested': + await this.reporter.warn(message); break; - case 'Failed': - await this.logMgr.fail(message); + case 'failed': + await this.reporter.fail(message); break; - case 'Passed': + case 'passed': default: - await this.logMgr.pass(message); + await this.reporter.pass(message); break; } } @@ -139,6 +147,7 @@ export class AftTest extends AftLog { protected async _generateTestResult(status: TestStatus, logMessage: string, testId?: string): Promise { let result: TestResult = { + testName: this.fullTitle, testId: testId, created: Date.now(), resultId: rand.guid, @@ -146,8 +155,8 @@ export class AftTest extends AftLog { status: status, metadata: { durationMs: this.test.duration, - buildName: await buildinfo.buildName() || 'unknown', - buildNumber: await buildinfo.buildNumber() || 'unknown' + buildName: await this._buildMgr.buildName() || 'unknown', + buildNumber: await this._buildMgr.buildNumber() || 'unknown' } }; return result; diff --git a/packages/aft-mocha-reporter/src/should-run.ts b/packages/aft-mocha-reporter/src/should-run.ts deleted file mode 100644 index f70acc0e..00000000 --- a/packages/aft-mocha-reporter/src/should-run.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { Defect, DefectManager, defects, IHasOptions, ProcessingResult, TestCaseManager, testcases } from "aft-core"; - -export type ShouldRunOptions = { - testMgr?: TestCaseManager; - defectMgr?: DefectManager; -} - -export class ShouldRun implements IHasOptions { - private readonly _options: ShouldRunOptions; - - private _testMgr: TestCaseManager; - private _defectMgr: DefectManager; - - constructor(options?: ShouldRunOptions) { - this._options = options || {}; - } - - option(key: K, defaultVal?: V): V { - const result: V = this._options[key] as V; - return (result === undefined) ? defaultVal : result; - } - - get testMgr(): TestCaseManager { - if (!this._testMgr) { - this._testMgr = this.option('testMgr', testcases); - } - return this._testMgr; - } - - get defectMgr(): DefectManager { - if (!this._defectMgr) { - this._defectMgr = this.option('defectMgr', defects); - } - return this._defectMgr; - } - - async tests(...tests: string[]): Promise { - const shouldRunTests = new Array(); - const shouldNotRunTests = new Array(); - if (tests?.length) { - for (var i=0; i = await this.defectMgr.findDefects(testId) || new Array(); - if (defects.some((d: Defect) => d?.status == 'open')) { - let openDefects: string = defects - .filter((d: Defect) => d.status == 'open') - .map((d: Defect) => d.id) - .join(', '); - shouldNotRunTests.push(testId); - return { - success: false, - message: `the testId ${testId} has one or more open defects so test should not be run: [${openDefects}]` - }; - } else { - shouldRunTests.push(testId); - } - } else { - shouldNotRunTests.push(testId); - } - } - let shouldRun: boolean = shouldRunTests.length > 0; - if (!shouldRun) { - return {success: false, message: `none of the supplied tests should be run: [${tests.join(', ')}]`}; - } - } - return {success: true, message: 'returning the test IDs, as an array, that should be run', obj: shouldRunTests}; - } - - async defects(...defects: string[]): Promise { - // first search for any specified Defects by ID - if (defects?.length) { - for (var i=0; i with multiple ids ` where - * `['ID123', 'Another']` would be returned - * @param title the test full title to be parsed - * @returns an array of DefectId strings or empty array - */ - static parseDefectIds(title: string): Array { - return this._parseAll(title, /\<([^\<\>]+)\>/gi); - } - private static _parseAll(input: string, regex: RegExp): Array { const results = new Array(); const allMatches = [...input.matchAll(regex)]; diff --git a/packages/aft-mocha-reporter/test/aft-mocha-reporter.spec.ts b/packages/aft-mocha-reporter/test/aft-mocha-reporter.spec.ts index 01b8e2b1..c37a6b0f 100644 --- a/packages/aft-mocha-reporter/test/aft-mocha-reporter.spec.ts +++ b/packages/aft-mocha-reporter/test/aft-mocha-reporter.spec.ts @@ -1,6 +1,7 @@ import { expect } from "chai"; import { AftLog, AftTest } from "../src"; import * as sinon from "sinon"; +import { Verifier, equaling } from "aft-core"; describe('AftMochaReporter', () => { it('passes a Mocha Test to the test that can be used by AftLog', async function () { @@ -11,10 +12,10 @@ describe('AftMochaReporter', () => { t.test.skip(); } expect(t).to.exist; - expect(t.logMgr).to.exist; - expect(t.logMgr.logName).to.equal(t.fullTitle); + expect(t.reporter).to.exist; + expect(t.reporter.reporterName).to.equal(t.fullTitle); - await t.logMgr.trace('sample log message'); + await t.reporter.trace('sample log message'); }); it('can skip a test during execution', async function() { @@ -33,12 +34,21 @@ describe('AftMochaReporter', () => { const t = new AftLog(this); expect(t).to.exist; - expect(t.logMgr).to.exist; - expect(t.logMgr.logName).to.eql('AFT'); + expect(t.reporter).to.exist; + expect(t.reporter.reporterName).to.eql('AFT'); // NOTE: arrow functions have no `this` so `this.test.fullTitle` doesn't exist - // expect(t.logMgr.logName).to.equal(t.fullTitle); + // expect(t.reporter.logName).to.equal(t.fullTitle); - await t.logMgr.trace('sample log message from aft-mocha-reporter.spec with arrow function'); + await t.reporter.trace('sample log message from aft-mocha-reporter.spec with arrow function'); + }); + + it('provides a Verifier instance for use in test control', async function() { + this.timeout(10000); + const t = new AftTest(this); + await t.verify(async (v: Verifier) => { + await v.reporter.warn('returning logName'); + return v.reporter.reporterName; + }).returns(equaling(t.reporter.reporterName)); }); }); \ No newline at end of file diff --git a/packages/aft-mocha-reporter/test/title-parser.spec.ts b/packages/aft-mocha-reporter/test/title-parser.spec.ts index 22150c42..68267f0f 100644 --- a/packages/aft-mocha-reporter/test/title-parser.spec.ts +++ b/packages/aft-mocha-reporter/test/title-parser.spec.ts @@ -25,27 +25,4 @@ describe('TitleParser', () => { expect(TitleParser.parseTestIds(d.title)).to.eql(d.expected); }); }); - - const ddata = [ - {title: '', expected: []}, - {title: '', expected: ['BUG-123']}, - {title: 'foo ', expected: ['BUG-123']}, - {title: ' foo', expected: ['BUG-123']}, - {title: 'foo foo', expected: ['BUG-123']}, - {title: ' ', expected: ['BUG-123', 'BUG-234']}, - {title: 'foo ', expected: ['BUG-123', 'BUG-234']}, - {title: ' foo ', expected: ['BUG-123', 'BUG-234']}, - {title: ' foo', expected: ['BUG-123', 'BUG-234']}, - {title: 'foo foo foo', expected: ['BUG-123', 'BUG-234']}, - {title: 'foo foo', expected: ['BUG-123', 'BUG-234']}, - {title: 'foo', expected: ['BUG-123', 'BUG-234']}, - {title: 'foo foo', expected: ['BUG-123', 'BUG-234']}, - {title: 'Bug name 123', expected: []}, - {title: 'foo [C1234] bar baz', expected: ['BUG-123']} - ]; - ddata.forEach((d) => { - it(`can parse defects from titles: '${d.title}'`, function () { - expect(TitleParser.parseDefectIds(d.title)).to.eql(d.expected); - }); - }); }); \ No newline at end of file diff --git a/packages/aft-mocha-reporter/tsconfig.json b/packages/aft-mocha-reporter/tsconfig.json index e3a0da5e..44218d5f 100644 --- a/packages/aft-mocha-reporter/tsconfig.json +++ b/packages/aft-mocha-reporter/tsconfig.json @@ -4,5 +4,10 @@ "outDir": "dist", "composite": true }, - "include": ["src", "test"] + "include": ["src", "test"], + "references": [ + { "path": "../aft-core" }, + { "path": "../aft-reporting-html" }, + { "path": "../aft-reporting-filesystem" } + ] } \ No newline at end of file diff --git a/packages/aft-logging-awskinesis/.nycrc b/packages/aft-reporting-aws-kinesis-firehose/.nycrc similarity index 100% rename from packages/aft-logging-awskinesis/.nycrc rename to packages/aft-reporting-aws-kinesis-firehose/.nycrc diff --git a/packages/aft-logging-awskinesis/LICENSE b/packages/aft-reporting-aws-kinesis-firehose/LICENSE similarity index 100% rename from packages/aft-logging-awskinesis/LICENSE rename to packages/aft-reporting-aws-kinesis-firehose/LICENSE diff --git a/packages/aft-logging-awskinesis/README.md b/packages/aft-reporting-aws-kinesis-firehose/README.md similarity index 85% rename from packages/aft-logging-awskinesis/README.md rename to packages/aft-reporting-aws-kinesis-firehose/README.md index c1d7c4eb..8e998f12 100644 --- a/packages/aft-logging-awskinesis/README.md +++ b/packages/aft-reporting-aws-kinesis-firehose/README.md @@ -1,17 +1,17 @@ -# AFT-Logging-AWSKinesis -an Automated Functional Testing (AFT) library providing logging to an AWS Kinesis Firehose endpoint for any `TestResult` objects logged via the `aft-core.LogManager` +# AFT-reporting-AWSKinesis +an Automated Functional Testing (AFT) library providing logging to an AWS Kinesis Firehose endpoint for any `TestResult` objects logged via the `aft-core.Reporter` ## Installation -`> npm i aft-logging-awskinesis` +`> npm i aft-reporting-awskinesis` ## Configuration to send values to AWS Kinesis Firehose endpoints you must specify the AWS Credentials, the AWS Region Endpoint and the AWS Kinesis Delivery Stream. These take the following form in your `aftconfig.json`: ```json { - "logmanager": { + "Reporter": { "level": "none", "plugins": [{ - "name": "kinesis-logging-plugin", + "name": "kinesis-reporting-plugin", "searchDirectory": "../", "options": { "enabled": true, @@ -28,11 +28,11 @@ to send values to AWS Kinesis Firehose endpoints you must specify the AWS Creden } } ``` -- **name** - a `string` containing `kinesis-logging-plugin` instructing the `pluginloader` to load this plugin +- **name** - a `string` containing `kinesis-reporting-plugin` instructing the `pluginloader` to load this plugin - **searchDirectory** - an optional `string` containing the root directory to begin searching for this plugin when first attempting to load it _(defaults to current working directory)_ - **options** - an optional `object` containing options for the plugin when it is first loaded. accepted values are as follows: - **enabled** - an optional `boolean` indicating if this plugin should be used or not _(defaults to `true`)_ - - **level** - an optional `LogLevel` to be used by this plugin _(defaults to value set in `LogManager`)_ + - **level** - an optional `LogLevel` to be used by this plugin _(defaults to value set in `Reporter`)_ - **accessKeyId** - a `string` containing your AWS IAM user's Access Key ID. if not specified the value will attempt to be read from environment variables, EC2 metadata, shared ini file, ECS credentials and process credentials in that order - **secretAccessKey** - a `string` containing your AWS IAM user's Secret Access Key. if not specified the value will attempt to be read like `accessKeyId` - **sessionToken** - a `string` containing your AWS IAM user's Session Token. only required if you are using a temporary session. if not specified the value will attempt to be read like `accessKeyId` @@ -47,7 +47,7 @@ to send values to AWS Kinesis Firehose endpoints you must specify the AWS Creden - Shared Ini File: read from the host system - ECS Credentials: similar to the EC2 Metadata, but on ECS - Process Credentials: any credentials set on the current process -- Options: read from passed in `KinesisLoggingPluginOptions` +- Options: read from passed in `KinesisReportingPluginOptions` ## Format of log records the log record that is sent to your AWS Kinesis Firehose endpoint will have the following format: @@ -67,10 +67,10 @@ the log record that is sent to your AWS Kinesis Firehose endpoint will have the } } ``` -- **logName** - the `logName` passed to this plugin when loaded from the `LogManager` +- **logName** - the `logName` passed to this plugin when loaded from the `Reporter` - **message** - the `string` being logged by some component - **level** - a `string` value from one of the `aft-core.LoggingLevel` values based on the level of the message being logged -- **version** - the current version of the `KinesisLoggingPlugin` +- **version** - the current version of the `KinesisReportingPlugin` - **buildName** - a `string` retrieved from the `BuildInfoManager.getBuildName` function - **buildNumber** - a `string` retrieved from the `BuildInfoManager.getBuildNumber` function - **machineInfo** - an `aft-core.MachineInfoData` object containing the following: @@ -85,17 +85,9 @@ the log record that is sent to your AWS Kinesis Firehose endpoint will have the "result": { "testId": "1234", "resultMessage": "the final result was a SUCCESS!", - "status": "Passed", + "status": "passed", "resultId": "dbbf6fce-14db-4bd2-ba31-e3fa68d719e4", "created": 1655289028279, - "defects": [ - { - "id": "3344", - "title": "a defect that has now been closed", - "description": "this defect used to affect this test, but now it doesn't :)", - "status": "closed" - } - ], "metadata": {} }, "buildName": "Jenkins or Team City Job Name", @@ -107,16 +99,15 @@ the log record that is sent to your AWS Kinesis Firehose endpoint will have the } } ``` -- **logName** - the `logName` passed to this plugin when loaded from the `LogManager` +- **logName** - the `logName` passed to this plugin when loaded from the `Reporter` - **result** - an `TestResult` object containing the following: - **testId** - a `string` containing any unique ID for the test result being recorded - **resultMessage** - a `string` message of the final result - **status** - a `string` representing the `aft-core.TestStatus` value - **resultId** - a `string` containing a unique identifier for the `TestResult` - **created** - a `number` containing the date and time the `TestResult` was created as milliseconds since the epoch - - **defects** - an array of `aft-core.Defect` objects - **metadata** - an `object` that can contain additional data for the `TestResult` -- **version** - the current version of the `KinesisLoggingPlugin` +- **version** - the current version of the `KinesisReportingPlugin` - **buildName** - a `string` retrieved from the `BuildInfoManager.getBuildName` function - **buildNumber** - a `string` retrieved from the `BuildInfoManager.getBuildNumber` function - **machineInfo** - an `aft-core.MachineInfoData` object containing the following: diff --git a/packages/aft-logging-awskinesis/package.json b/packages/aft-reporting-aws-kinesis-firehose/package.json similarity index 74% rename from packages/aft-logging-awskinesis/package.json rename to packages/aft-reporting-aws-kinesis-firehose/package.json index 0cff4572..872eb0f5 100644 --- a/packages/aft-logging-awskinesis/package.json +++ b/packages/aft-reporting-aws-kinesis-firehose/package.json @@ -1,7 +1,7 @@ { - "name": "aft-logging-awskinesis", - "version": "9.0.0", - "description": "Automated Functional Testing (AFT) logging plugin package supporting test reporting to AWS Kinesis Firehose", + "name": "aft-reporting-aws-kinesis-firehose", + "version": "10.0.0", + "description": "Automated Functional Testing (AFT) reporting plugin package supporting test reporting to AWS Kinesis Firehose", "repository": { "type": "git", "url": "https://github.com/bicarbon8/automated-functional-testing.git" @@ -11,8 +11,8 @@ "scripts": { "clean": "rimraf ./dist && rimraf ./.nyc_output && rimraf ./coverage", "build": "npm run clean && tsc --build", - "test": "jasmine-ts ./test/**/*-spec.ts", - "coverage": "nyc npm run test" + "test": "npm run build && jasmine-ts ./test/**/*-spec.ts", + "coverage": "npm run build && nyc jasmine-ts ./test/**/*-spec.ts" }, "keywords": [ "aft", @@ -30,7 +30,7 @@ }, "homepage": "https://github.com/bicarbon8/automated-functional-testing#readme", "dependencies": { - "aft-core": "^9.0.0", + "aft-core": "^10.0.0", "aws-sdk": "^2.1151.0" }, "devDependencies": { diff --git a/packages/aft-reporting-aws-kinesis-firehose/src/index.ts b/packages/aft-reporting-aws-kinesis-firehose/src/index.ts new file mode 100644 index 00000000..2cde47ee --- /dev/null +++ b/packages/aft-reporting-aws-kinesis-firehose/src/index.ts @@ -0,0 +1 @@ +export * from './kinesis-reporting-plugin'; \ No newline at end of file diff --git a/packages/aft-logging-awskinesis/src/kinesis-log-record.ts b/packages/aft-reporting-aws-kinesis-firehose/src/kinesis-log-record.ts similarity index 84% rename from packages/aft-logging-awskinesis/src/kinesis-log-record.ts rename to packages/aft-reporting-aws-kinesis-firehose/src/kinesis-log-record.ts index ee389743..56e0d5c1 100644 --- a/packages/aft-logging-awskinesis/src/kinesis-log-record.ts +++ b/packages/aft-reporting-aws-kinesis-firehose/src/kinesis-log-record.ts @@ -1,6 +1,6 @@ import { TestResult, MachineInfoData } from "aft-core"; -export interface KinesisLogRecord { +export type KinesisLogRecord = { logName?: string; message?: string; level?: string; diff --git a/packages/aft-logging-awskinesis/src/kinesis-logging-plugin.ts b/packages/aft-reporting-aws-kinesis-firehose/src/kinesis-reporting-plugin.ts similarity index 54% rename from packages/aft-logging-awskinesis/src/kinesis-logging-plugin.ts rename to packages/aft-reporting-aws-kinesis-firehose/src/kinesis-reporting-plugin.ts index 68bd0cc8..7db6fb4c 100644 --- a/packages/aft-logging-awskinesis/src/kinesis-logging-plugin.ts +++ b/packages/aft-reporting-aws-kinesis-firehose/src/kinesis-reporting-plugin.ts @@ -1,38 +1,32 @@ -import { LoggingPlugin, LogLevel, TestResult, machineInfo, BuildInfoManager, buildinfo, LogManager, LogMessageData, Err, Merge, LoggingPluginOptions } from "aft-core"; +import { ReportingPlugin, LogLevel, TestResult, machineInfo, AftConfig, BuildInfoManager, ReportingPluginConfig } from "aft-core"; import * as AWS from "aws-sdk"; import * as pkg from "../package.json"; import { KinesisLogRecord } from "./kinesis-log-record"; -export type KinesisLoggingPluginOptions = Merge; - type CheckAndSendOptions = { override?: boolean; logName: string; }; +export class KinesisReportingPluginConfig extends ReportingPluginConfig { + region: string; + deliveryStream: string; + batch: boolean = true; + batchSize: number = 10; +}; + /** * NOTE: this plugin accepts the following options: * ```json + * // aftconfig.json * { - * "level": "info", - * "accessKeyId": "your-aws-access-key-id", - * "secretAccessKey": "your-aws-secret-access-key", - * "sessionToken": "your-aws-session-token", - * "region": "us-west-1", - * "deliveryStream": "your-frehose-delivery-stream", - * "batch": true, - * "batchSize": 10 + * "KinesisReportingPluginConfig": { + * "logLevel": "info", + * "region": "us-west-1", + * "deliveryStream": "your-frehose-delivery-stream", + * "batch": true, + * "batchSize": 10 + * } * } * ``` * NOTE: @@ -42,24 +36,33 @@ type CheckAndSendOptions = { * - Shared Ini File: read from the host system * - ECS Credentials: similar to the EC2 Metadata, but on ECS * - Process Credentials: any credentials set on the current process - * - Options: read from passed in `KinesisLoggingPluginOptions` + * - Options: read from passed in `KinesisReportingPluginOptions` */ -export class KinesisLoggingPlugin extends LoggingPlugin { +export class KinesisReportingPlugin extends ReportingPlugin { private readonly _logs: Map; - private readonly _buildInfoMgr: BuildInfoManager; + private readonly _buildInfo: BuildInfoManager; + private readonly _level: LogLevel; private _client: AWS.Firehose; + + public override get logLevel(): LogLevel { + return this._level; + } - constructor(options?: KinesisLoggingPluginOptions) { - super(options); + constructor(aftCfg?: AftConfig, client?: AWS.Firehose) { + super(aftCfg); + this._client = client; this._logs = new Map(); - this._buildInfoMgr = this.option('buildInfoMgr', buildinfo); - this._client = this.option('client'); // new client created if not passed in + this._level = this.aftCfg.getSection(KinesisReportingPluginConfig).logLevel + ?? this.aftCfg.logLevel ?? 'warn'; + if (this.enabled) { + this._buildInfo = new BuildInfoManager(this.aftCfg); + } } async client(): Promise { if (!this._client) { - this._client = this.option('client') || new AWS.Firehose({ + this._client = new AWS.Firehose({ region: this.region, credentials: await this.credentials() }); @@ -67,38 +70,26 @@ export class KinesisLoggingPlugin extends LoggingPlugin { let creds: AWS.Credentials; - if (this.accessKeyId && this.secretAccessKey) { - creds = new AWS.Credentials({ - accessKeyId: this.accessKeyId, - secretAccessKey: this.secretAccessKey, - sessionToken: this.sessionToken - }); - } - if (!creds) { + try { creds = await new AWS.CredentialProviderChain([ () => new AWS.EnvironmentCredentials('AWS'), () => new AWS.EC2MetadataCredentials(), () => new AWS.SharedIniFileCredentials(), () => new AWS.ECSCredentials(), () => new AWS.ProcessCredentials() - ]).resolvePromise() - .catch((err) => { - LogManager.toConsole({name: this.constructor.name, message: err, level: 'warn'}); - return null; - }); + ]).resolvePromise(); + } catch (e) { + this.aftLogger.log({name: this.constructor.name, message: e, level: 'warn'}); + return null; } return creds; } logs(key: string, val?: AWS.Firehose.Record[]): AWS.Firehose.Record[] { - if (!this._logs.has(key)) { - this._logs.set(key, new Array()); - } if (val) { this._logs.set(key, val); } return this._logs.get(key); } - override async log(data: LogMessageData): Promise { - if (LogLevel.toValue(data.level) >= LogLevel.toValue(this.level) && data.level != 'none') { - let record: AWS.Firehose.Record = this._createKinesisLogRecord({ - logName: data.name, - level: data.level, - message: data.message, - version: pkg.version, - buildName: await this._buildInfoMgr.buildName().catch((err) => 'unknown'), - machineInfo: machineInfo.data - }); - const logs = this.logs(data.name); - logs.push(record); - this.logs(data.name, logs); - await this._checkAndSendLogs({logName: data.name}); + override initialise = async (logName: string): Promise => { + if (this.enabled) { + if (!this._logs.has(logName)) { + this._logs.set(logName, new Array()); + } } } - override async logResult(name: string, result: TestResult): Promise { - let record: AWS.Firehose.Record = this._createKinesisLogRecord({ - logName: name, - result: result, - version: pkg.version, - buildName: await this._buildInfoMgr.buildName().catch((err) => 'unknown'), - machineInfo: machineInfo.data - }); - const logs = this.logs(name); - logs.push(record); - this.logs(name, logs); - await this._checkAndSendLogs({logName: name}); + override log = async (name: string, level: LogLevel, message: string, ...data: Array): Promise => { + if (this.enabled) { + if (LogLevel.toValue(level) >= LogLevel.toValue(this.logLevel) && level != 'none') { + let record: AWS.Firehose.Record = this._createKinesisLogRecord({ + logName: name, + level: level, + message: message, + version: pkg.version, + buildName: await this._buildInfo.buildName().catch((err) => 'unknown'), + machineInfo: machineInfo.data + }); + const logs = this.logs(name); + logs.push(record); + this.logs(name, logs); + await this._checkAndSendLogs({logName: name}); + } + } + } + + /** + * implementation of the {ResultsPlugin} class used to submit results + * @param result a {TestResult} to send to Kinesis Firehose + */ + override submitResult = async (name: string, result: TestResult): Promise => { + if (this.enabled) { + name ??= result?.testName; + if (name) { + let record: AWS.Firehose.Record = this._createKinesisLogRecord({ + logName: name, + result: result, + version: pkg.version, + buildName: await this._buildInfo.buildName().catch((err) => 'unknown'), + machineInfo: machineInfo.data + }); + const logs = this.logs(name); + logs.push(record); + this.logs(name, logs); + await this._checkAndSendLogs({logName: name}); + } + } } - override async dispose(name: string, error?: Error): Promise { - if (error) { - await this.log({name: name, level: 'error', message: Err.short(error)}); + override finalise = async (name: string): Promise => { + if (this.enabled) { + // ensure all remaining logs are sent + await this._checkAndSendLogs({override: true, logName: name}); } - // ensure all remaining logs are sent - await this._checkAndSendLogs({override: true, logName: name}); - this._logs.delete(name); } private _createKinesisLogRecord(logRecord: KinesisLogRecord): AWS.Firehose.Record { diff --git a/packages/aft-reporting-aws-kinesis-firehose/test/kinesis-reporting-plugin-spec.ts b/packages/aft-reporting-aws-kinesis-firehose/test/kinesis-reporting-plugin-spec.ts new file mode 100644 index 00000000..d45552e5 --- /dev/null +++ b/packages/aft-reporting-aws-kinesis-firehose/test/kinesis-reporting-plugin-spec.ts @@ -0,0 +1,233 @@ +import { KinesisReportingPlugin, KinesisReportingPluginConfig } from "../src/kinesis-reporting-plugin"; +import { AftConfig, Reporter, machineInfo, pluginLoader, rand, TestResult } from "aft-core"; +import * as pkg from "../package.json"; +import * as Firehose from "aws-sdk/clients/firehose"; +import { KinesisLogRecord } from "../src/kinesis-log-record"; +import AWS = require("aws-sdk"); + +describe('KinesisReportingPlugin', () => { + beforeEach(() => { + pluginLoader.reset(); + }); + afterEach(() => { + pluginLoader.reset(); + }); + + it('can batch messages for sending', async () => { + const aftCfg = new AftConfig(); + const config = aftCfg.getSection(KinesisReportingPluginConfig); + config.logLevel = 'info'; + config.batch = true; + config.batchSize = 10; + let plugin: KinesisReportingPlugin = new KinesisReportingPlugin(aftCfg); + spyOn(plugin, 'credentials').and.returnValue(Promise.resolve(new AWS.Credentials( + rand.getString(25, true, true), + rand.getString(35, true, true, true), + rand.getString(150, true, true, true) + ))); + let spyCheckAndSendLogs = spyOn(plugin, '_checkAndSendLogs').and.callThrough(); + let spySendBatch = spyOn(plugin, '_sendBatch').and.callFake((deliveryStream: string, records: Firehose.Record[]) => { + /* do nothing */ + }); + let spySend = spyOn(plugin, '_send').and.callFake((deliveryStream: string, record: Firehose.Record) => { + /* do nothing */ + }); + + const logName = rand.getString(10); + plugin.initialise(logName); + for (var i=0; i<20; i++) { + let logMessage: string = rand.getString(99, true, true); + await plugin.log(logName, 'warn', logMessage); + } + + expect(spyCheckAndSendLogs).toHaveBeenCalledTimes(20); + expect(spySendBatch).toHaveBeenCalledTimes(2); + expect(spySend).toHaveBeenCalledTimes(0); + }); + + it('can disable batch sending of messages', async () => { + const aftCfg = new AftConfig(); + const config = aftCfg.getSection(KinesisReportingPluginConfig); + config.logLevel = 'info'; + config.batch = false + config.batchSize = 10; + let plugin: KinesisReportingPlugin = new KinesisReportingPlugin(aftCfg); + spyOn(plugin, 'credentials').and.returnValue(Promise.resolve(new AWS.Credentials( + rand.getString(25, true, true), + rand.getString(35, true, true, true), + rand.getString(150, true, true, true) + ))); + let spyCheckAndSendLogs = spyOn(plugin, '_checkAndSendLogs').and.callThrough(); + let spySendBatch = spyOn(plugin, '_sendBatch').and.callFake((deliveryStream: string, records: Firehose.Record[]) => { + /* do nothing */ + }); + let spySend = spyOn(plugin, '_send').and.callFake((deliveryStream: string, record: Firehose.Record) => { + /* do nothing */ + }); + + const logName = rand.getString(10); + plugin.initialise(logName); + for (var i=0; i<20; i++) { + let logMessage: string = rand.getString(99, true, true); + await plugin.log(logName, 'warn', logMessage); + } + + expect(spyCheckAndSendLogs).toHaveBeenCalledTimes(20); + expect(spySendBatch).toHaveBeenCalledTimes(0); + expect(spySend).toHaveBeenCalledTimes(20); + }); + + it('sends any unsent batched logs on dispose', async () => { + const aftCfg = new AftConfig(); + const config = aftCfg.getSection(KinesisReportingPluginConfig); + config.logLevel = 'info'; + config.batch = true; + config.batchSize = 10; + let plugin: KinesisReportingPlugin = new KinesisReportingPlugin(aftCfg); + spyOn(plugin, 'credentials').and.returnValue(Promise.resolve(new AWS.Credentials( + rand.getString(25, true, true), + rand.getString(35, true, true, true), + rand.getString(150, true, true, true) + ))); + let spyCheckAndSendLogs = spyOn(plugin, '_checkAndSendLogs').and.callThrough(); + let spySendBatch = spyOn(plugin, '_sendBatch').and.callFake((deliveryStream: string, records: Firehose.Record[]) => { + /* do nothing */ + }); + let spySend = spyOn(plugin, '_send').and.callFake((deliveryStream: string, record: Firehose.Record) => { + /* do nothing */ + }); + + const logName = rand.getString(10); + plugin.initialise(logName); + for (var i=0; i<9; i++) { + let logMessage: string = rand.getString(99, true, true); + await plugin.log(logName, 'warn', logMessage); + } + + expect(spyCheckAndSendLogs).toHaveBeenCalledTimes(9); + expect(spySendBatch).toHaveBeenCalledTimes(0); + expect(spySend).toHaveBeenCalledTimes(0); + + await plugin.finalise(logName); + + expect(spySendBatch).toHaveBeenCalledTimes(1); + expect(spySend).toHaveBeenCalledTimes(0); + + expect(plugin.logs(logName).length).toBe(0); + }); + + it('only sends messages of the appropriate level', async () => { + const aftCfg = new AftConfig(); + const config = aftCfg.getSection(KinesisReportingPluginConfig); + config.logLevel = 'info'; + config.batch = false; + config.batchSize = 10; + let plugin: KinesisReportingPlugin = new KinesisReportingPlugin(aftCfg); + spyOn(plugin, 'credentials').and.returnValue(Promise.resolve(new AWS.Credentials( + rand.getString(25, true, true), + rand.getString(35, true, true, true), + rand.getString(150, true, true, true) + ))); + let spyCheckAndSendLogs = spyOn(plugin, '_checkAndSendLogs').and.callThrough(); + let spySendBatch = spyOn(plugin, '_sendBatch').and.callFake((deliveryStream: string, records: Firehose.Record[]) => { + /* do nothing */ + }); + let spySend = spyOn(plugin, '_send').and.callFake((deliveryStream: string, record: Firehose.Record) => { + /* do nothing */ + }); + + const logName = rand.getString(10); + plugin.initialise(logName); + await plugin.log(logName, 'debug', rand.guid); + await plugin.log(logName, 'info', rand.guid); + await plugin.log(logName, 'warn', rand.guid); + + expect(spyCheckAndSendLogs).toHaveBeenCalledTimes(2); + expect(spySendBatch).toHaveBeenCalledTimes(0); + expect(spySend).toHaveBeenCalledTimes(2); + }); + + it('adds expected fields to the log record', async () => { + const aftCfg = new AftConfig(); + const config = aftCfg.getSection(KinesisReportingPluginConfig); + config.logLevel = 'info'; + config.batch = false; + config.batchSize = 10; + let plugin: KinesisReportingPlugin = new KinesisReportingPlugin(aftCfg); + spyOn(plugin, 'credentials').and.returnValue(Promise.resolve(new AWS.Credentials( + rand.getString(25, true, true), + rand.getString(35, true, true, true), + rand.getString(150, true, true, true) + ))); + const store = new Map(); + let spySend = spyOn(plugin, '_send').and.callFake((deliveryStream: string, record: Firehose.Record) => { + store.set('_send', record); + }); + + let expectedMessage: string = rand.guid; + const logName = 'adds expected fields to the log record'; + plugin.initialise(logName); + await plugin.log(logName, 'warn', expectedMessage); + + let logRecord: Firehose.Record = store.get('_send'); + let data: KinesisLogRecord = JSON.parse(logRecord.Data.toString()) as KinesisLogRecord; + expect(data.level).toEqual('warn'); + expect(data.logName).toEqual('adds expected fields to the log record'); + expect(data.message).toEqual(expectedMessage); + expect(data.machineInfo).toEqual(machineInfo.data); + expect(data.result).toBeUndefined(); + expect(data.version).toEqual(pkg.version); + }); + + /** + * WARNING: this test sends an actual message to the Kinesis reporter + * only for use in debugging issues locally + */ + xit('can send real logs and ITestResult objects', async () => { + const aftCfg = new AftConfig(); + const config = aftCfg.getSection(KinesisReportingPluginConfig); + config.logLevel = 'trace'; + config.batch = true; + config.batchSize = 10; + config.deliveryStream = '%kinesis_deliverystream%'; + config.region = '%AWS_REGION%'; + const plugin: KinesisReportingPlugin = new KinesisReportingPlugin(aftCfg); + const logName = rand.getString(10, true, true, true, true); + const result: TestResult = { + resultId: rand.guid, + created: Date.now(), + testId: 'C' + rand.getInt(100, 9999), + resultMessage: rand.getString(100), + status: 'skipped', + testName: logName + }; + const message: string = rand.getString(250); + plugin.initialise(logName); + await plugin.log(logName, 'info', message); + await plugin.submitResult(logName, result); + await plugin.finalise(logName); + }); + + it('can be loaded by the Reporter', async () => { + const config = { + pluginNames: [ + 'kinesis-reporting-plugin' + ], + KinesisReportingPluginConfig: { + logLevel: 'none', + batch: false + } + }; + const aftCfg = new AftConfig(config); + pluginLoader.reset(); + const mgr: Reporter = new Reporter(rand.getString(20), aftCfg); + const plugins = mgr.plugins; + const plugin = plugins[0]; + + expect(plugin).toBeDefined(); + expect(plugin.logLevel).toEqual('none'); + expect((plugin as KinesisReportingPlugin).batch).toBe(false); + expect(plugin.constructor.name).toEqual('KinesisReportingPlugin'); + expect(plugin.enabled).toBeFalse(); + }); +}); \ No newline at end of file diff --git a/packages/aft-logging-awskinesis/tsconfig.json b/packages/aft-reporting-aws-kinesis-firehose/tsconfig.json similarity index 100% rename from packages/aft-logging-awskinesis/tsconfig.json rename to packages/aft-reporting-aws-kinesis-firehose/tsconfig.json diff --git a/packages/aft-logging-filesystem/.nycrc b/packages/aft-reporting-filesystem/.nycrc similarity index 100% rename from packages/aft-logging-filesystem/.nycrc rename to packages/aft-reporting-filesystem/.nycrc diff --git a/packages/aft-logging-filesystem/LICENSE b/packages/aft-reporting-filesystem/LICENSE similarity index 100% rename from packages/aft-logging-filesystem/LICENSE rename to packages/aft-reporting-filesystem/LICENSE diff --git a/packages/aft-logging-filesystem/README.md b/packages/aft-reporting-filesystem/README.md similarity index 86% rename from packages/aft-logging-filesystem/README.md rename to packages/aft-reporting-filesystem/README.md index 0488d7f4..b95e27e8 100644 --- a/packages/aft-logging-filesystem/README.md +++ b/packages/aft-reporting-filesystem/README.md @@ -1,8 +1,8 @@ -# AFT-Logging-Filesystem -Automated Functional Testing (AFT) package providing a Filesystem Logging Plugin that generates .log files based on the `LogManager.logName` and appends log lines using a customisable date format +# AFT-reporting-Filesystem +Automated Functional Testing (AFT) package providing a Filesystem Logging Plugin that generates .log files based on the `Reporter.logName` and appends log lines using a customisable date format ## Installation -`> npm i aft-logging-filesystem` +`> npm i aft-reporting-filesystem` ## Configuration this plugin accepts configuration options in the following format: @@ -11,10 +11,10 @@ this plugin accepts configuration options in the following format: ```json { ... - "LogManager": { + "Reporter": { "level": "info", "plugins": [{ - "name": "filesystem-logging-plugin", + "name": "filesystem-reporting-plugin", "options": { "level": "trace", "enabled": true, @@ -27,10 +27,10 @@ this plugin accepts configuration options in the following format: ... } ``` -- **level** - a `string` containing a valid `LogLevel` _(defaults to value set in `LogManager.level` or `"none"` if not set)_ +- **level** - a `string` containing a valid `LogLevel` _(defaults to value set in `Reporter.level` or `"none"` if not set)_ - **enabled** - a `boolean` indicating if this plugin should be used _(defaults to `true`)_ - **outputPath** - a `string` with either an absolute path or a relative path from the `process.cwd()` where .log files will be created _(defaults to `./logs`)_ -- **includeResults** - a `boolean` indicating whether calls to any `LogManager.logResult` function will output the `TestResult` to the .log file _(defaults to `true`)_ +- **includeResults** - a `boolean` indicating whether calls to any `Reporter.logResult` function will output the `TestResult` to the .log file _(defaults to `true`)_ - **dateFormat** - a `string` that can include Date Formatting as outlined at the [date-and-time](https://github.com/knowledgecode/date-and-time#formatdateobj-arg-utc) npm package ## Log Format diff --git a/packages/aft-logging-filesystem/package.json b/packages/aft-reporting-filesystem/package.json similarity index 75% rename from packages/aft-logging-filesystem/package.json rename to packages/aft-reporting-filesystem/package.json index 21e70e74..c434c4b8 100644 --- a/packages/aft-logging-filesystem/package.json +++ b/packages/aft-reporting-filesystem/package.json @@ -1,14 +1,14 @@ { - "name": "aft-logging-filesystem", - "version": "9.0.0", - "description": "Automated Functional Testing (AFT) logging plugin package supporting logging to files", + "name": "aft-reporting-filesystem", + "version": "10.0.0", + "description": "Automated Functional Testing (AFT) reporting plugin package supporting logging to files", "main": "./dist/src/index.js", "types": "./dist/src/index.d.ts", "scripts": { "clean": "rimraf ./dist && rimraf ./.nyc_output && rimraf ./coverage", "build": "npm run clean && tsc --build", - "test": "jasmine-ts ./test/**/*-spec.ts", - "coverage": "nyc npm run test" + "test": "npm run build && jasmine-ts ./test/**/*-spec.ts", + "coverage": "npm run build && nyc jasmine-ts ./test/**/*-spec.ts" }, "repository": { "type": "git", @@ -30,7 +30,7 @@ }, "homepage": "https://github.com/bicarbon8/automated-functional-testing#readme", "dependencies": { - "aft-core": "^9.0.0", + "aft-core": "^10.0.0", "date-and-time": "^2.4.0" }, "devDependencies": { diff --git a/packages/aft-reporting-filesystem/src/filesystem-reporting-plugin.ts b/packages/aft-reporting-filesystem/src/filesystem-reporting-plugin.ts new file mode 100644 index 00000000..bd43636d --- /dev/null +++ b/packages/aft-reporting-filesystem/src/filesystem-reporting-plugin.ts @@ -0,0 +1,103 @@ +import * as path from "path"; +import { AftConfig, convert, Err, ExpiringFileLock, fileio, ReportingPlugin, ReportingPluginConfig, LogLevel, LogMessageData, TestResult } from "aft-core"; +import * as date from "date-and-time"; + +export class FilesystemReportingPluginConfig extends ReportingPluginConfig { + override logLevel: LogLevel = 'trace'; + outputPath: string = path.join(process.cwd(), 'logs'); + includeResults: boolean = true; + dateFormat: string = 'YYYY-MM-DD HH:mm:ss.SSS'; +}; + +export class FilesystemReportingPlugin extends ReportingPlugin { + public override get logLevel(): LogLevel { + return this._level; + } + + private readonly _outputPath: string; + private readonly _includeResults: boolean; + private readonly _dateFormat: string; + private readonly _level: LogLevel; + + constructor(aftCfg?: AftConfig) { + super(aftCfg); + const fslpc = this.aftCfg.getSection(FilesystemReportingPluginConfig); + this._level = fslpc.logLevel ?? this.aftCfg.logLevel + ?? 'trace'; + if (this.enabled) { + if (!path.isAbsolute(fslpc.outputPath)) { + this._outputPath = path.join(process.cwd(), fslpc.outputPath); + } else { + this._outputPath = fslpc.outputPath; + } + this._includeResults = fslpc.includeResults ?? true; + this._dateFormat = fslpc.dateFormat ?? 'YYYY-MM-DD HH:mm:ss.SSS'; + } + } + + override initialise = async (logName: string): Promise => { + /* do nothing */ + } + + override log = async (name: string, level: LogLevel, message: string, ...data: any[]): Promise => { + if (this.enabled) { + if (data?.length > 0) { + message = `${message} ${data?.map(d => Err.handle(() => d?.toString())).join(', ')}`; + } + this._appendToFile({name, level, message}); + } + } + + override submitResult = async (name: string, result: TestResult): Promise => { + if (this.enabled && this._includeResults) { + let level: LogLevel; + switch(result.status) { + case 'failed': + level = 'fail'; + break; + case 'passed': + level = 'pass'; + break; + case 'blocked': + case 'skipped': + level = 'warn'; + break; + default: + level = 'info'; + break; + } + const data: LogMessageData = { + name: name ?? result.testName, + level: level, + message: JSON.stringify(result) + }; + this._appendToFile(data); + } + } + + override finalise = async (logName: string): Promise => { + /* do nothing */ + } + + private _appendToFile(data: LogMessageData): void { + if (LogLevel.toValue(data.level) >= LogLevel.toValue(this.logLevel) && data.level != 'none') { + const filename = convert.toSafeString(data.name); + const fullPath = path.join(this._outputPath, `${filename}.log`); + const lock = new ExpiringFileLock(fullPath, this.aftCfg); + try { + fileio.append(fullPath, `${this._format(data)}\n`); + } finally { + lock.unlock(); + } + } + } + + private _format(data: LogMessageData): string { + data = data || {} as LogMessageData; + data.message ??= ''; + data.level ??= 'none'; + let d: string = date.format(new Date(), this._dateFormat); + let out: string = `[${d}] - ${data.level.toUpperCase()} - ${data.message}`; + return out; + } +} \ No newline at end of file diff --git a/packages/aft-reporting-filesystem/src/index.ts b/packages/aft-reporting-filesystem/src/index.ts new file mode 100644 index 00000000..d93d43e5 --- /dev/null +++ b/packages/aft-reporting-filesystem/src/index.ts @@ -0,0 +1 @@ +export * from "./filesystem-reporting-plugin"; \ No newline at end of file diff --git a/packages/aft-reporting-filesystem/test/filesystem-reporting-plugin-spec.ts b/packages/aft-reporting-filesystem/test/filesystem-reporting-plugin-spec.ts new file mode 100644 index 00000000..0462f5d6 --- /dev/null +++ b/packages/aft-reporting-filesystem/test/filesystem-reporting-plugin-spec.ts @@ -0,0 +1,121 @@ +import * as fs from "fs"; +import * as path from "path"; +import { AftConfig, convert, rand } from "aft-core"; +import { FilesystemReportingPlugin, FilesystemReportingPluginConfig } from "../src/filesystem-reporting-plugin"; + +describe('FilesystemReportingPlugin', () => { + beforeEach(() => { + const logDir = path.join(process.cwd(), 'logs'); + if (fs.existsSync(logDir)) { + fs.rmSync(logDir, {recursive: true, force: true}); + } + }); + + it('can create a file on the filesystem and write logs to it', async () => { + const aftCfg = new AftConfig(); + const plugin = new FilesystemReportingPlugin(aftCfg); + const logName = 'can create a file on the filesystem and write logs to it'; + await plugin.log(logName, 'trace', rand.getString(rand.getInt(100, 200))); + await plugin.log(logName, 'info', rand.getString(rand.getInt(100, 200))); + await plugin.log(logName, 'error', rand.getString(rand.getInt(100, 200))); + await plugin.submitResult(logName, { + testName: logName, + resultId: rand.guid, + created: Date.now(), + status: 'passed' + }); + await plugin.submitResult(logName, { + testName: logName, + resultId: rand.guid, + created: Date.now(), + status: 'skipped' + }); + await plugin.submitResult(logName, { + testName: logName, + resultId: rand.guid, + created: Date.now(), + status: 'failed' + }); + await plugin.submitResult(logName, { + testName: logName, + resultId: rand.guid, + created: Date.now(), + status: 'untested' + }); + + const filePath = path.join(process.cwd(), 'logs', `${convert.toSafeString(logName)}.log`); + expect(fs.existsSync(filePath)).toBeTrue(); + + const lines: Array = fs.readFileSync(filePath, {encoding: 'utf-8'})?.split('\n') || []; + expect(lines.length).toBe(8); // 7 logged lines plus one empty due to newline at end of each line + expect(lines[0]).toContain('TRACE'); + expect(lines[6]).toContain('INFO'); + expect(lines[7]).toEqual(''); + }); + + it('will not write to file if level below specified value', async () => { + const aftCfg = new AftConfig({ + FilesystemReportingPluginConfig: { + logLevel: 'error' + } + }); + const plugin = new FilesystemReportingPlugin(aftCfg); + const logName = 'will not write to file if level below specified value'; + await plugin.log(logName, 'trace', rand.getString(rand.getInt(100, 200))); + await plugin.log(logName, 'debug', rand.getString(rand.getInt(100, 200))); + await plugin.log(logName, 'info', rand.getString(rand.getInt(100, 200))); + await plugin.log(logName, 'step', rand.getString(rand.getInt(100, 200))); + await plugin.log(logName, 'pass', rand.getString(rand.getInt(100, 200))); + await plugin.log(logName, 'fail', rand.getString(rand.getInt(100, 200))); + await plugin.log(logName, 'warn', rand.getString(rand.getInt(100, 200))); + await plugin.log(logName, 'error', rand.getString(rand.getInt(100, 200))); + + const filePath = path.join(process.cwd(), 'logs', `${convert.toSafeString(logName)}.log`); + expect(fs.existsSync(filePath)).toBeTrue(); + + const lines: Array = fs.readFileSync(filePath, {encoding: 'utf-8'})?.split('\n') || []; + expect(lines.length).toBe(2); + expect(lines[0]).toContain('ERROR'); + expect(lines[1]).toEqual(''); + }); + + it('can change the date formatting', async () => { + const logName = 'can change the date formatting'; + const aftCfg = new AftConfig(); + const config = aftCfg.getSection(FilesystemReportingPluginConfig); + config.logLevel = 'info'; + config.dateFormat = 'SSS'; + const plugin = new FilesystemReportingPlugin(aftCfg); + + await plugin.log(logName, 'warn', rand.getString(rand.getInt(100, 200))); + + const filePath = path.join(process.cwd(), 'logs', `${convert.toSafeString(logName)}.log`); + expect(fs.existsSync(filePath)).toBeTrue(); + + const lines: Array = fs.readFileSync(filePath, {encoding: 'utf-8'})?.split('\n') || []; + expect(lines.length).toBe(2); + expect(lines[0]).toMatch(/^\[[0-9]{3}\] - WARN - .+$/); + expect(lines[1]).toEqual(''); + }); + + it('can disable output of TestResult objects', async () => { + const logName = 'can disable output of TestResult objects'; + const aftCfg = new AftConfig({ + FilesystemReportingPluginConfig: { + logLevel: 'trace', + includeResults: false + } + }); + const plugin = new FilesystemReportingPlugin(aftCfg); + + await plugin.submitResult(logName, { + testName: logName, + resultId: rand.guid, + created: Date.now(), + status: 'passed' + }); + + const filePath = path.join(process.cwd(), 'logs', `${convert.toSafeString(logName)}.log`); + expect(fs.existsSync(filePath)).toBeFalse(); + }); +}); \ No newline at end of file diff --git a/packages/aft-logging-filesystem/tsconfig.json b/packages/aft-reporting-filesystem/tsconfig.json similarity index 100% rename from packages/aft-logging-filesystem/tsconfig.json rename to packages/aft-reporting-filesystem/tsconfig.json diff --git a/packages/aft-logging-html/.nycrc b/packages/aft-reporting-html/.nycrc similarity index 100% rename from packages/aft-logging-html/.nycrc rename to packages/aft-reporting-html/.nycrc diff --git a/packages/aft-logging-html/ExampleReport.png b/packages/aft-reporting-html/ExampleReport.png similarity index 100% rename from packages/aft-logging-html/ExampleReport.png rename to packages/aft-reporting-html/ExampleReport.png diff --git a/packages/aft-logging-html/LICENSE b/packages/aft-reporting-html/LICENSE similarity index 100% rename from packages/aft-logging-html/LICENSE rename to packages/aft-reporting-html/LICENSE diff --git a/packages/aft-logging-html/README.md b/packages/aft-reporting-html/README.md similarity index 88% rename from packages/aft-logging-html/README.md rename to packages/aft-reporting-html/README.md index 48667297..2e8f2d7a 100644 --- a/packages/aft-logging-html/README.md +++ b/packages/aft-reporting-html/README.md @@ -1,18 +1,18 @@ -# AFT-Logging-HTML -an Automated Functional Testing (AFT) library providing logging to an HTML file for any `TestResult` objects logged via the `aft-core.LogManager` +# AFT-reporting-HTML +an Automated Functional Testing (AFT) library providing logging to an HTML file for any `TestResult` objects logged via the `aft-core.Reporter` ## Installation -`> npm i aft-logging-html` +`> npm i aft-reporting-html` ## Configuration to specify the filename and output directory for the generated HTML results add the following to your `aftconfig.json`: ```json { - "LogManager": { + "Reporter": { "level": "info", "plugins": [ { - "name": "html-logging-plugin", + "name": "html-reporting-plugin", "searchDirectory": "./node_modules/", "options": { "enabled": true, @@ -26,7 +26,7 @@ to specify the filename and output directory for the generated HTML results add } } ``` -- **level** - an optional `string` containing the `LogLevel` to be used in capturing logs _(defaults to value set for `LogManager`)_ +- **level** - an optional `string` containing the `LogLevel` to be used in capturing logs _(defaults to value set for `Reporter`)_ - **fileName** - a `string` containing the full file name to write results into _(defaults to `testresults.html`)_ - **outputDir** - a `string` containing either a relative path from the current execution directory or an absolute path to where the results file will be written _(defaults to `process.cwd()`)_ - **maxLogLines** - a `number` indicating how many previous calls to the `log` method will be tracked. numbers greater than this will be discarded from the results _(defaults to `5`)_ diff --git a/packages/aft-logging-html/aftconfig.json b/packages/aft-reporting-html/aftconfig.json similarity index 63% rename from packages/aft-logging-html/aftconfig.json rename to packages/aft-reporting-html/aftconfig.json index 09ace0c0..79c4670c 100644 --- a/packages/aft-logging-html/aftconfig.json +++ b/packages/aft-reporting-html/aftconfig.json @@ -1,9 +1,9 @@ { - "logmanager": { - "pluginNames": ["html-logging-plugin"], + "Reporter": { + "pluginNames": ["html-reporting-plugin"], "searchDir": "../" }, - "htmlloggingplugin": { + "htmlReportingPlugin": { "fileName": "TestSummary.html", "outputDir": "./dist", "maxLogLines": 4, diff --git a/packages/aft-logging-html/package.json b/packages/aft-reporting-html/package.json similarity index 79% rename from packages/aft-logging-html/package.json rename to packages/aft-reporting-html/package.json index ce279b3c..ad4323f7 100644 --- a/packages/aft-logging-html/package.json +++ b/packages/aft-reporting-html/package.json @@ -1,14 +1,14 @@ { - "name": "aft-logging-html", - "version": "9.0.0", - "description": "Automated Functional Testing (AFT) package that creates a HTML results file as a Logging Plugin", + "name": "aft-reporting-html", + "version": "10.0.0", + "description": "Automated Functional Testing (AFT) package that creates a HTML results file as a Reporting Plugin", "main": "./dist/src/index.js", "types": "./dist/src/index.d.ts", "scripts": { "clean": "rimraf ./dist && rimraf ./.nyc_output && rimraf ./coverage", "build": "npm run clean && tsc --build", - "test": "jasmine-ts ./test/**/*-spec.ts", - "coverage": "nyc npm run test" + "test": "npm run build && jasmine-ts ./test/**/*-spec.ts", + "coverage": "npm run build && nyc jasmine-ts ./test/**/*-spec.ts" }, "repository": { "type": "git", @@ -41,6 +41,6 @@ "typescript": "^4.3.2" }, "dependencies": { - "aft-core": "^9.0.0" + "aft-core": "^10.0.0" } } diff --git a/packages/aft-reporting-html/src/html-reporting-plugin.ts b/packages/aft-reporting-html/src/html-reporting-plugin.ts new file mode 100644 index 00000000..8b94daca --- /dev/null +++ b/packages/aft-reporting-html/src/html-reporting-plugin.ts @@ -0,0 +1,144 @@ +import * as path from "path"; +import { ReportingPlugin, LogLevel, TestResult, fileio, ExpiringFileLock, FileSystemMap, convert, AftConfig, ReportingPluginConfig } from "aft-core"; +import { HtmlTestResult } from "./html-test-result"; +import { HtmlResult } from "./html-result"; +import { htmlTemplate } from "./templates/html-template"; + +export class HtmlReportingPluginConfig extends ReportingPluginConfig { + fileName: string = 'testresults.html'; + outputDir: string = path.join(process.cwd(), 'logs'); + maxLogLines: number; + override logLevel: LogLevel = 'warn'; +} + +export class HtmlReportingPlugin extends ReportingPlugin { + public override get logLevel(): LogLevel { + return this._level; + } + + private readonly _results: FileSystemMap>; + private readonly _logs: FileSystemMap>; + private readonly _fileName: string; + private readonly _outputDir: string; + private readonly _maxLogLines: number; + private readonly _level: LogLevel; + + constructor(aftCfg?: AftConfig) { + super(aftCfg); + const cfg = this.aftCfg.getSection(HtmlReportingPluginConfig); + this._level = cfg.logLevel ?? this.aftCfg.logLevel ?? 'warn'; + if (this.enabled) { + this._results = new FileSystemMap>('htmlSharedResults'); + this._logs = new FileSystemMap>('htmlSharedLogs'); + this._fileName = cfg.fileName ?? 'testresults.html'; + let dir = cfg.outputDir ?? path.join(process.cwd(), 'logs'); + if (path.isAbsolute(dir)) { + this._outputDir = dir; + } else { + this._outputDir = path.join(process.cwd(), dir); + } + this._maxLogLines = cfg.maxLogLines ?? 5; + } + } + + get fullPathAndFile(): string { + if (!this.enabled) { + return null; + } + let fullPathAndFile: string; + let filePath: string = this._outputDir; + let fileName: string = this._fileName; + if (filePath && fileName) { + fullPathAndFile = path.join(filePath, fileName); + } else { + fullPathAndFile = path.join(process.cwd(), 'testresults.html'); + } + return fullPathAndFile; + } + + logs(key: string, val?: Array): Array { + if (!this.enabled) { + return null; + } + if (!this._logs.has(key)) { + this._logs.set(key, new Array()); + } + if (val) { + this._logs.set(key, val); + } + return this._logs.get(key); + } + + testResults(key: string, val?: Array): Array { + if (!this.enabled) { + return null; + } + if (!this._results.has(key)) { + this._results.set(key, new Array()); + } + if (val) { + this._results.set(key, val); + } + return this._results.get(key); + } + + override initialise = async (logName: string): Promise => { + /* do nothing */ + } + + override log = async (name: string, level: LogLevel, message: string, ...data: any[]): Promise => { + if (!this.enabled) { + return; + } + let expectedLevel: LogLevel = this.logLevel; + if (LogLevel.toValue(level) >= LogLevel.toValue(expectedLevel) && level != 'none') { + const logs = this.logs(name); + logs.push(`${level} - ${message}`); + let max: number = this._maxLogLines; + while (logs.length > max) { + logs.shift(); + logs[0] = `...
    ${logs[0]}`; + } + this.logs(name, logs); + } + } + + override submitResult = async (name: string, result: TestResult): Promise => { + if (!this.enabled) { + return; + } + let htmlTestResult: HtmlTestResult = { + testId: result.testId, + status: result.status, + logs: this.logs(name ?? result.testName) + } + const results: Array = this.testResults(result.testName); + results.push(htmlTestResult); + this.testResults(result.testName, results); + } + + override finalise = async (logName: string): Promise => { + if (!this.enabled) { + return; + } + const htmlResults: HtmlResult[] = new Array(); + this._results.forEach((result: Array, key: string) => { + htmlResults.push({ + description: convert.toSafeString(key), + tests: result + }); + }); + await this._regenerateHtmlFile(htmlResults); + this._logs.delete(logName); + } + + private async _regenerateHtmlFile(results: HtmlResult[]): Promise { + const fullPathAndFile = this.fullPathAndFile; + const lock: ExpiringFileLock = new ExpiringFileLock(fullPathAndFile, this.aftCfg); + try { + fileio.write(fullPathAndFile, htmlTemplate.emit(...results)); + } finally { + lock.unlock(); + } + } +} \ No newline at end of file diff --git a/packages/aft-logging-html/src/html-result.ts b/packages/aft-reporting-html/src/html-result.ts similarity index 100% rename from packages/aft-logging-html/src/html-result.ts rename to packages/aft-reporting-html/src/html-result.ts diff --git a/packages/aft-logging-html/src/html-test-result.ts b/packages/aft-reporting-html/src/html-test-result.ts similarity index 100% rename from packages/aft-logging-html/src/html-test-result.ts rename to packages/aft-reporting-html/src/html-test-result.ts diff --git a/packages/aft-reporting-html/src/index.ts b/packages/aft-reporting-html/src/index.ts new file mode 100644 index 00000000..509560b2 --- /dev/null +++ b/packages/aft-reporting-html/src/index.ts @@ -0,0 +1 @@ +export * from './html-reporting-plugin'; \ No newline at end of file diff --git a/packages/aft-logging-html/src/templates/html-template.ts b/packages/aft-reporting-html/src/templates/html-template.ts similarity index 95% rename from packages/aft-logging-html/src/templates/html-template.ts rename to packages/aft-reporting-html/src/templates/html-template.ts index a6f3546a..a26182ef 100644 --- a/packages/aft-logging-html/src/templates/html-template.ts +++ b/packages/aft-reporting-html/src/templates/html-template.ts @@ -190,9 +190,9 @@ function initialise(results) { } function addResult(result) { - var passing = getTestsWithStatus(/(Passed)/gi, result).length; - var failing = getTestsWithStatus(/(Failed|Retest)/gi, result).length; - var notRun = getTestsWithStatus(/(Untested|Blocked|Skipped)/gi, result).length; + var passing = getTestsWithStatus(/(passed)/gi, result).length; + var failing = getTestsWithStatus(/(failed|retest)/gi, result).length; + var notRun = getTestsWithStatus(/(untested|blocked|skipped)/gi, result).length; var container = document.querySelector('#resultsContainer'); var section = \`
    @@ -237,12 +237,12 @@ function addTests(container, tests) { var result = tests[i]; var statusClass, trClass; switch (result.status) { - case "Passed": + case "passed": statusClass = "success"; trClass = "passing"; break; - case "Failed": - case "Retest": + case "failed": + case "retest": statusClass = "danger"; trClass = "failing"; break; diff --git a/packages/aft-logging-html/src/templates/tmp.html b/packages/aft-reporting-html/src/templates/tmp.html similarity index 100% rename from packages/aft-logging-html/src/templates/tmp.html rename to packages/aft-reporting-html/src/templates/tmp.html diff --git a/packages/aft-reporting-html/test/html-reporting-plugin-spec.ts b/packages/aft-reporting-html/test/html-reporting-plugin-spec.ts new file mode 100644 index 00000000..d2010ed9 --- /dev/null +++ b/packages/aft-reporting-html/test/html-reporting-plugin-spec.ts @@ -0,0 +1,174 @@ +import * as fs from "fs"; +import * as path from "path"; +import { AftConfig, Reporter, rand, TestResult } from "aft-core"; +import { HtmlReportingPlugin } from "../src"; +import { HtmlResult } from "../src/html-result"; + +describe('HtmlReportingPlugin', () => { + beforeEach(() => { + let c: string = path.join(process.cwd(), 'FileSystemMap', 'htmlSharedResults.json'); + if (fs.existsSync(c)) {fs.unlinkSync(c);} + let d: string = path.join(process.cwd(), 'FileSystemMap', 'htmlSharedLogs.json'); + if (fs.existsSync(d)) {fs.unlinkSync(d);} + let e: string = path.join(process.cwd(), 'testresults.html'); + if (fs.existsSync(e)) {fs.unlinkSync(e);} + }); + + it('stores the specified number of log lines', async () => { + const config = { + logLevel: 'info', + maxLogLines: 14 + }; + let plugin: HtmlReportingPlugin = new HtmlReportingPlugin(new AftConfig({ + HtmlReportingPluginConfig: config + })); + const logName = rand.getString(50); + for (var i=0; i<25; i++) { + await plugin.log(logName, 'info', rand.getString(100)); + } + + let actual: string[] = plugin.logs(logName); + expect(actual.length).toBe(14); + }); + + it('adds an ellipsis to the oldest log line only when exceeded maxLogLines', async () => { + const config = { + logLevel: 'info', + maxLogLines: 3 + }; + let plugin: HtmlReportingPlugin = new HtmlReportingPlugin(new AftConfig({ + HtmlReportingPluginConfig: config + })); + const logName = rand.getString(50); + for (var i=0; i<3; i++) { + await plugin.log(logName, 'info', rand.getString(100)); + } + + let actual: string[] = plugin.logs(logName); + expect(actual.length).toBe(3); + expect(actual[0]).not.toContain('...'); + + await plugin.log(logName, 'info', rand.getString(100)); + + actual = plugin.logs(logName); + expect(actual.length).toBe(3); + expect(actual[0]).toContain('...'); + }); + + it('stores logs only when at or above the specified level', async () => { + const config = { + logLevel: 'step', + maxLogLines: 14 + }; + let plugin: HtmlReportingPlugin = new HtmlReportingPlugin(new AftConfig({ + HtmlReportingPluginConfig: config + })); + const logName = 'stores logs only when at or above the specified level'; + await plugin.log(logName, 'none', 'level none'); + await plugin.log(logName, 'trace', 'level trace'); + await plugin.log(logName, 'debug', 'level debug'); + await plugin.log(logName, 'info', 'level info'); + await plugin.log(logName, 'step', 'level step'); + await plugin.log(logName, 'warn', 'level warn'); + await plugin.log(logName, 'pass', 'level pass'); + await plugin.log(logName, 'fail', 'level fail'); + await plugin.log(logName, 'error', 'level error'); + + let actual: string[] = plugin.logs(logName); + expect(actual.length).toBe(5); + expect(actual).not.toContain('level none'); + expect(actual).not.toContain('level trace'); + expect(actual).not.toContain('level debug'); + expect(actual).not.toContain('level info'); + }); + + it('can be loaded successfully from the Reporter', async () => { + const aftCfg = new AftConfig({ + pluginNames: ['html-reporting-plugin'] + }); + let reporter: Reporter = new Reporter('can be loaded successfully from the Reporter', aftCfg); + let plugin = reporter.plugins[0]; + + expect(plugin).toBeDefined(); + expect(plugin.constructor.name).toEqual('HtmlReportingPlugin'); + }); + + it('only attempts to write to HTML file on call to dispose', async () => { + const config = { + outputDir: './', + fileName: 'testresults.html' + }; + let plugin: HtmlReportingPlugin = new HtmlReportingPlugin(new AftConfig({ + HtmlReportingPluginConfig: config + })); + const readSpy = spyOn(plugin, 'logs').and.returnValue(['foo', 'bar', 'baz']); + const testResults: Array = new Array( + {testName: 'Fake Test One', testId: 'C123', status: 'failed', resultId: rand.guid, created: Date.now()}, + {testName: 'Fake Test One', testId: 'C234', status: 'passed', resultId: rand.guid, created: Date.now()}, + {testName: "Fake 'Test' Two", testId: 'C345', status: 'passed', resultId: rand.guid, created: Date.now()}, + {testName: "Fake 'Test' Two", testId: 'C456', status: 'passed', resultId: rand.guid, created: Date.now()}, + {testName: "Fake [Test] ", testId: 'Test', status: 'passed', resultId: rand.guid, created: Date.now()} + ); + for (var res of testResults) { + await plugin.submitResult(res.testName, res); + }; + let actualResults: HtmlResult[]; + const regenSpy = spyOn(plugin, '_regenerateHtmlFile').and.callFake((results: HtmlResult[]) => { + actualResults = results; + }); + + const logName = 'only attempts to write to sharedCache and HTML file on call to dispose'; + await plugin.log(logName, 'info', 'fake log message'); + const expectedResult: TestResult = { + testName: logName, + testId: 'C567', + resultId: rand.guid, + status: 'passed', + created: Date.now() + }; + await plugin.submitResult(expectedResult.testName, expectedResult); + + expect(regenSpy).not.toHaveBeenCalled(); + + await plugin.finalise(logName); + + expect(regenSpy).toHaveBeenCalledTimes(1); + expect(actualResults).toHaveSize(4); + }); + + it('can generate HTML result file', async () => { + const config = { + outputDir: './', + fileName: 'testresults.html' + }; + let plugin: HtmlReportingPlugin = new HtmlReportingPlugin(new AftConfig({ + HtmlReportingPluginConfig: config + })); + const readSpy = spyOn(plugin, 'logs').and.returnValue(['foo', 'bar', 'baz']); + const testResults: Array = new Array( + {testName: 'Fake Test One', testId: 'C123', status: 'failed', resultId: rand.guid, created: Date.now()}, + {testName: 'Fake Test One', testId: 'C234', status: 'passed', resultId: rand.guid, created: Date.now()}, + {testName: "Fake 'Test' Two", testId: 'C345', status: 'passed', resultId: rand.guid, created: Date.now()}, + {testName: "Fake 'Test' Two", testId: 'C456', status: 'passed', resultId: rand.guid, created: Date.now()}, + {testName: "Fake [Test] ", status: 'passed', resultId: rand.guid, created: Date.now()} + ); + for (var res of testResults) { + await plugin.submitResult(res.testName, res); + }; + + const logName = 'can generate HTML result file'; + await plugin.log(logName, 'info', 'fake log message'); + const expectedResult: TestResult = { + testName: logName, + testId: 'C567', + resultId: rand.guid, + status: 'passed', + created: Date.now() + }; + await plugin.submitResult(expectedResult.testName, expectedResult); + + await plugin.finalise(logName); + + expect(fs.existsSync(plugin.fullPathAndFile)).toBeTrue(); + }); +}); \ No newline at end of file diff --git a/packages/aft-logging-html/tsconfig.json b/packages/aft-reporting-html/tsconfig.json similarity index 60% rename from packages/aft-logging-html/tsconfig.json rename to packages/aft-reporting-html/tsconfig.json index e3a0da5e..80c5ec34 100644 --- a/packages/aft-logging-html/tsconfig.json +++ b/packages/aft-reporting-html/tsconfig.json @@ -4,5 +4,6 @@ "outDir": "dist", "composite": true }, - "include": ["src", "test"] + "include": ["src", "test"], + "references": [{ "path": "../aft-core" }] } \ No newline at end of file diff --git a/packages/aft-testrail/README.md b/packages/aft-testrail/README.md index 2f6ee982..14849148 100644 --- a/packages/aft-testrail/README.md +++ b/packages/aft-testrail/README.md @@ -1,54 +1,42 @@ # AFT-TestRail -provides TestRail result logging as well as test execution filtering for users of `aft-core` by implementing plugins for the `AbstractLoggingPlugin` and `AbstractTestCasePlugin` plugin base classes. +provides TestRail result logging as well as test execution filtering for users of `aft-core` by implementing plugins for the `ReportingPlugin` and `TestExecutionPolicyPlugin` plugin base classes. -## TestRailLoggingPlugin -the `TestRailLoggingPlugin` extends from `LoggingPlugin` in `aft-core`. if enabled, this plugin will log test results to test cases in a TestRail Plan (if no plan is specified a new one is created the first time one is attempted to be accessed by the plugin). it can be enabled by including the following in your `aftconfig.json` file: +## TestRailReportingPlugin +the `TestRailReportingPlugin` extends from `ReportingPlugin` in `aft-core`. if enabled, this plugin will log test results to test cases in a TestRail Plan (if no plan is specified a new one is created the first time one is attempted to be accessed by the plugin). it can be enabled by including the following in your `aftconfig.json` file: ```json { - "LogManager": { - "level": "info", - "plugins": [ - { - "name": "testrail-logging-plugin", - "options": { - "enabled": true, - "level": "error", - "maxLogCharacters": 100 - } - } - ] - }, + "logLevel": "info", + "pluginNames": [ + "testrail-reporting-plugin" + ], "TestRailConfig": { "url": "https://your.testrail.instance/", "user": "valid.user@testrail.instance", "accesskey": "your_access_key", - "planid": 12345 + "planid": 12345, + "logLevel": "warn", + "maxLogCharacters": 250 } } ``` -**PluginConfig**: -- **level** - [OPTIONAL] `string` value of `none`, `error`, `warn`, `step`, `info`, `debug`, or `trace` _(defaults to value set on `LogManager`)_ +**TestRailConfig**: +- **logLevel** - [OPTIONAL] `string` value of `none`, `error`, `warn`, `step`, `info`, `debug`, or `trace` _(defaults to value set on `aftConfig.logLevel`)_ - **maxLogCharacters** - [OPTIONAL] `number` for the maximum number of additional log characters to send to TestRail when logging a `TestResult` _(defaults to 250)_ -## TestRailTestCasePlugin -the `TestRailTestCasePlugin` extends from `TestCasePlugin` interface in `aft-core`. if enabled this plugin will lookup the status of TestRail tests based on their case ID from the set of IDs passed in to a `Verifier.withTestId` function. it can be enabled by including the following in your `aftconfig.json` file: +## TestRailTestExecutionPolicyPlugin +the `TestRailTestExecutionPolicyPlugin` extends from `TestExecutionPolicyPlugin` interface in `aft-core`. if enabled this plugin will lookup the status of TestRail tests based on their case ID from the set of IDs passed in to a `Verifier.withTestId` function. it can be enabled by including the following in your `aftconfig.json` file: ```json { - "TestCaseManager": { - "pluginNames": [ - { - "name": "testrail-test-case-plugin", - "options": { - "enabled": true - } - } - ] - }, + "logLevel": "info", + "pluginNames": [ + "testrail-test-execution-policy-plugin" + ], "TestRailConfig": { "url": "https://your.testrail.instance/", "user": "valid.user@testrail.instance", "accesskey": "your_access_key", - "planid": 12345 + "planid": 12345, + "policyEngineEnabled": true } } ``` @@ -56,14 +44,17 @@ the `TestRailTestCasePlugin` extends from `TestCasePlugin` interface in `aft-cor to submit results to or filter test execution based on existence and status of tests in TestRail, you will need to have an account with write permissions in TestRail. These values can be specified in your `aftconfig.json` as follows: ```json { - "testrailconfig": { + "TestRailConfig": { "url": "http://fake.testrail.io", "user": "your.email@your.domain.com", "accesskey": "your_testrail_api_key_or_password", "projectid": 3, "suiteids": [1219, 744], "planid": 12345, - "cacheDurationMs": 1000000 + "cacheDurationMs": 1000000, + "logLevel": "trace", + "maxLogCharacters": 250, + "policyEngineEnabled": true } } ``` @@ -72,19 +63,19 @@ to submit results to or filter test execution based on existence and status of t - **accesskey** - [REQUIRED] the access key (or password) for the above user - **projectid** - the TestRail project containing test suites to be used in test execution. _(Required only if `planid` is not set)_ - **suiteids** - an array of TestRail suites containing test cases to be used in test execution. _(Required only if `planid` is not set)_ -- **planid** - an existing TestRail Plan to be used for logging test results if `testrail-logging-plugin` is referenced and enabled and used for controlling execution of tests. _(NOTE: if no value is specified for `planid` and `testrail-logging-plugin` is enabled, a new TestRail Plan will be created using the suites specified in `suiteids` and the `projectid`)_ +- **planid** - an existing TestRail Plan to be used for logging test results if `testrail-reporting-plugin` is referenced and enabled and used for controlling execution of tests. _(NOTE: if no value is specified for `planid` and `testrail-reporting-plugin` is enabled, a new TestRail Plan will be created using the suites specified in `suiteids` and the `projectid`)_ - **cacheDurationMs** - the maximum number of milliseconds to cache responses from TestRail's API _(defaults to 300000)_ ## Usage -you can submit results directly by calling the `aft-core.LogManager.logResult(result: TestResult)` function or results will automatically be submitted if using the `aft-core.verify(assertion)` with valid `testCases` specified in the `options` object. +you can submit results directly by calling the `aft-core.Reporter.submitResult(result: TestResult)` function or results will automatically be submitted if using the `aft-core.verify(assertion)` with valid `testCases` specified in the `options` object. > NOTE: sending a `TestResult` with a `TestStatus` of `Failed` will be converted to a status of `Retest` before submitting to TestRail -### via `aft-core.LogManager`: +### via `aft-core.Reporter`: ```typescript -let logMgr = new LogManager({logName: 'example'}); -await logMgr.logResult({ - testId: 'C3190', // must be an existing TestRail Case ID contained in your referenced TestRail Plan ID +let reporter = new Reporter({logName: 'example'}); +await reporter.submitResult({ + testId: 'C3190', // must exist in TestRail plan or project and suites status: TestStatus.Failed, resultMessage: 'there was an error when running this test' }); @@ -92,12 +83,10 @@ await logMgr.logResult({ ### via `aft-core.verify` (`aft-core.Verifier`): ```typescript /** - * `TestStatus.Retest` result for `C3190`, `C2217763`, and `C3131` sent to TestRail + * `TestStatus.retest` result for `C3190`, `C2217763`, and `C3131` sent to TestRail * following execution because expectation fails */ await verify(() => (1 + 1)).returns(3) -.withTestId('C3190') -.and.withTestId('C2217763') -.and.withTestId('C3131') +.withTestIds('C3190', 'C2217763', 'C3131') .and.withDescription('expected to fail because 1+1 != 3'); ``` diff --git a/packages/aft-testrail/aftconfig.json b/packages/aft-testrail/aftconfig.json index 7756381c..28d264e6 100644 --- a/packages/aft-testrail/aftconfig.json +++ b/packages/aft-testrail/aftconfig.json @@ -1,10 +1,10 @@ { - "logmanager": { - "pluginNames": ["testrail-logging-plugin"], + "Reporter": { + "pluginNames": ["testrail-reporting-plugin"], "level": "info" }, "testcasemanager": { - "pluginNames": ["testrail-test-case-plugin"] + "pluginNames": ["testrail-test-execution-policy-plugin"] }, "testrailconfig": { "url": "%testrail_url%", @@ -13,7 +13,7 @@ "projectid": 3, "suiteids": [1219] }, - "testrailloggingplugin": { + "testrailReportingPlugin": { "maxLogCharacters": 100 } } \ No newline at end of file diff --git a/packages/aft-testrail/package.json b/packages/aft-testrail/package.json index 1eee76f1..0f85526e 100644 --- a/packages/aft-testrail/package.json +++ b/packages/aft-testrail/package.json @@ -1,6 +1,6 @@ { "name": "aft-testrail", - "version": "9.0.0", + "version": "10.0.0", "description": "Automated Functional Testing (AFT) package supporting TestRail integration for test execution control and logging", "repository": { "type": "git", @@ -11,8 +11,8 @@ "scripts": { "clean": "rimraf ./dist && rimraf ./.nyc_output && rimraf ./coverage", "build": "npm run clean && tsc --build", - "test": "jasmine-ts ./test/**/*-spec.ts", - "coverage": "nyc npm run test" + "test": "npm run build && jasmine-ts ./test/**/*-spec.ts", + "coverage": "npm run build && nyc jasmine-ts ./test/**/*-spec.ts" }, "keywords": [ "aft", @@ -29,7 +29,7 @@ }, "homepage": "https://github.com/bicarbon8/automated-functional-testing#readme", "dependencies": { - "aft-web-services": "^9.0.0" + "aft-web-services": "^10.0.0" }, "devDependencies": { "@types/jasmine": "^3.6.10", diff --git a/packages/aft-testrail/src/api/testrail-api.ts b/packages/aft-testrail/src/api/testrail-api.ts index adccb4b6..db2a77f1 100644 --- a/packages/aft-testrail/src/api/testrail-api.ts +++ b/packages/aft-testrail/src/api/testrail-api.ts @@ -1,41 +1,19 @@ import { httpData, HttpRequest, HttpResponse, httpService } from "aft-web-services"; -import { CacheMap, convert, IHasOptions, JsonObject, optmgr, wait } from "aft-core"; -import { TestRailConfig, trconfig } from "../configuration/testrail-config"; +import { aftConfig, AftConfig, CacheMap, convert, ExpiringFileLock, fileio, JsonObject, wait } from "aft-core"; +import { TestRailConfig } from "../configuration/testrail-config"; import { AddPlanRequest, ICanHaveError, TestRailCase, TestRailGetCasesResponse, TestRailGetTestsResponse, TestRailPlan, TestRailPlanEntry, TestRailResult, TestRailResultRequest, TestRailResultResponse, TestRailRun, TestRailTest } from "./testrail-custom-types"; -export type TestRailApiOptions = { - config?: TestRailConfig; -}; - -export class TestRailApi implements IHasOptions { - private _cache: CacheMap; - private _config: TestRailConfig; - - private readonly _options: TestRailApiOptions; +export class TestRailApi { + private readonly _aftCfg: AftConfig; + private readonly _cache: CacheMap; - constructor(options?: TestRailApiOptions) { - options = options || {} as TestRailApiOptions; - this._options = optmgr.process(options); - } - - option(key: K, defaultVal?: V): V { - const result: V = this._options[key] as V; - return (result === undefined) ? defaultVal : result; + constructor(aftCfg?: AftConfig) { + this._aftCfg = aftCfg ?? aftConfig; + this._cache = new CacheMap(this.config.cacheDuration, true, this.constructor.name); } get config(): TestRailConfig { - if (!this._config) { - this._config = this.option('config', trconfig); - } - return this._config; - } - - async cache(): Promise> { - if (!this._cache) { - const duration: number = await this.config.cacheDuration(); - this._cache = new CacheMap(duration, true, this.constructor.name); - } - return this._cache; + return this._aftCfg.getSection(TestRailConfig); } /** @@ -200,13 +178,12 @@ export class TestRailApi implements IHasOptions { method: 'GET', headers: {} }; - const cache = await this.cache(); - let data: T = cache.get(request.url); + let data: T = this._cache.get(request.url); if (!data) { let response: HttpResponse = await this._performRequestWithRateLimitHandling(request); data = httpData.as(response); if (cacheResponse && response.statusCode >= 200 && response.statusCode <= 299) { - cache.set(request.url, data); + this._cache.set(request.url, data); } } @@ -228,7 +205,7 @@ export class TestRailApi implements IHasOptions { } private async _getApiUrl(): Promise { - let url = await this.config.url(); + let url = this.config.url; if (url && !url.endsWith('/')) { url += '/'; } @@ -264,8 +241,8 @@ export class TestRailApi implements IHasOptions { } private async _getAuth(): Promise { - let username: string = await this.config.user(); - let accessKey: string = await this.config.accessKey(); + let username: string = this.config.user; + let accessKey: string = this.config.accessKey; return convert.toBase64Encoded(`${username}:${accessKey}`); } } \ No newline at end of file diff --git a/packages/aft-testrail/src/configuration/testrail-config.ts b/packages/aft-testrail/src/configuration/testrail-config.ts index fe9188df..3493da0e 100644 --- a/packages/aft-testrail/src/configuration/testrail-config.ts +++ b/packages/aft-testrail/src/configuration/testrail-config.ts @@ -1,14 +1,4 @@ -import { cfgmgr, IConfigProvider, FileSystemMap, IHasConfig, optmgr } from 'aft-core'; - -export type TestRailConfigOptions = { - url?: string; - user?: string; - accesskey?: string; - projectid?: number; - suiteids?: number[]; - planid?: number; - cacheDurationMs?: number; -} +import { LogLevel, ReportingPluginConfig } from "aft-core"; /** * reads configuration from either the passed in `TestRailConfigOptions` @@ -27,87 +17,19 @@ export type TestRailConfigOptions = { * ``` * NOTE: * - `projectid` and `suiteids` are only used if no `planid` is specified - * - if 'TestRailLoggingPlugin` is in use and no `planid` is specified a new + * - if 'TestRailReportingPlugin` is in use and no `planid` is specified a new * TestRail plan will be created and the value stored in a shared file for access * by other processes and subsequent test executions */ -export class TestRailConfig implements IHasConfig { - private _url: string; - private _user: string; - private _accessKey: string; - private _projectId: number; - private _suiteIds: number[]; - private _planId: number; - private _cacheDuration: number; - - private readonly _shared: FileSystemMap; - - private readonly _config: IConfigProvider; - - constructor(options?: TestRailConfigOptions) { - options = options || {} as TestRailConfigOptions; - this._config = cfgmgr.get(this.constructor.name, optmgr.process(options)); - this._shared = new FileSystemMap(this.constructor.name); - } - - config(key: K, defaultVal?: V): Promise { - return this._config.get(key, defaultVal); - } - - async url(): Promise { - if (!this._url) { - this._url = await this.config('url'); - } - return this._url; - } - - async user(): Promise { - if (!this._user) { - this._user = await this.config('user'); - } - return this._user; - } - - async accessKey(): Promise { - if (!this._accessKey) { - this._accessKey = await this.config('accesskey'); - } - return this._accessKey; - } - - async projectId(): Promise { - if (this._projectId === undefined) { - this._projectId = await this.config('projectid', -1); - } - return this._projectId; - } - - async suiteIds(): Promise { - if (this._suiteIds === undefined) { - this._suiteIds = await this.config('suiteids', []); - } - return this._suiteIds; - } - - async planId(): Promise { - if (this._planId === undefined) { - this._planId = this._shared.get('planid') || await this.config('planid', -1); - } - return this._planId; - } - - setPlanId(id: number): this { - this._shared.set('planid', id); - this._planId = id; - return this; - } - - async cacheDuration(): Promise { - if (this._cacheDuration === undefined) { - this._cacheDuration = await this.config('cacheDurationMs', 300000); - } - return this._cacheDuration; - } -} - -export const trconfig = new TestRailConfig(); \ No newline at end of file +export class TestRailConfig extends ReportingPluginConfig { + public url: string; + public user: string; + public accessKey: string; + public projectId: number; + public suiteIds: number[] = []; + public planId: number; + public cacheDuration: number = 300000; + public override logLevel: LogLevel = 'warn'; + public maxLogCharacters: number = 250; + public policyEngineEnabled: boolean = true; +} \ No newline at end of file diff --git a/packages/aft-testrail/src/helpers/plan-id.ts b/packages/aft-testrail/src/helpers/plan-id.ts new file mode 100644 index 00000000..54079dda --- /dev/null +++ b/packages/aft-testrail/src/helpers/plan-id.ts @@ -0,0 +1,38 @@ +import { AftConfig, ExpiringFileLock, FileSystemMap, aftConfig } from "aft-core"; +import { TestRailApi } from "../api/testrail-api"; +import { TestRailConfig } from "../configuration/testrail-config"; +import { TestRailPlan } from "../api/testrail-custom-types"; + +export module PlanId { + /** + * looks for an existing TestRail plan id + * @param aftCfg an instance of {AftConfig} + * @param api an instance of {TestRailApi} + * @returns either an existing TestRail plan id or a newly created plan id + */ + export async function get(aftCfg?: AftConfig, api?: TestRailApi): Promise { + aftCfg ??= aftConfig; + api ??= new TestRailApi(aftCfg); + const trc = aftCfg.getSection(TestRailConfig); + let planId: number = trc.planId; + if (planId == null || planId <= 0) { + const key = TestRailConfig.name; + const lock: ExpiringFileLock = new ExpiringFileLock(key, aftCfg); + try { + const fsm = new FileSystemMap(key, [], aftCfg); + planId = fsm.get('planId'); + if (planId == null || planId <= 0) { + // create new Test Plan if one doesn't already exist + const projectId: number = trc.projectId; + const suiteIds: number[] = trc.suiteIds; + const plan: TestRailPlan = await api.createPlan(projectId, suiteIds); + trc.planId = plan.id; + fsm.set('planId', trc.planId); // sets value in FileSystemMap for key 'planId' + } + } finally { + lock.unlock(); + } + } + return planId; + } +} \ No newline at end of file diff --git a/packages/aft-testrail/src/helpers/status-converter.ts b/packages/aft-testrail/src/helpers/status-converter.ts index e6c816a0..8c46a4e5 100644 --- a/packages/aft-testrail/src/helpers/status-converter.ts +++ b/packages/aft-testrail/src/helpers/status-converter.ts @@ -8,16 +8,16 @@ class StatusConverter { */ toTestRailStatus(status: TestStatus): number { switch (status) { - case 'Skipped': + case 'skipped': return 9; - case 'Untested': + case 'untested': return 3; - case 'Blocked': + case 'blocked': return 2; - case 'Passed': + case 'passed': return 1; - case 'Failed': - case 'Retest': + case 'failed': + case 'retest': default: return 4; } @@ -31,16 +31,16 @@ class StatusConverter { fromTestRailStatus(trStatus: number): TestStatus { switch (trStatus) { case 1: - return 'Passed'; + return 'passed'; case 2: - return 'Blocked'; + return 'blocked'; case 3: - return 'Untested'; + return 'untested'; case 5: - return 'Failed'; + return 'failed'; case 4: default: - return 'Retest'; + return 'retest'; } } } diff --git a/packages/aft-testrail/src/index.ts b/packages/aft-testrail/src/index.ts index 1ccbd05f..1259f59f 100644 --- a/packages/aft-testrail/src/index.ts +++ b/packages/aft-testrail/src/index.ts @@ -1,6 +1,6 @@ /** configuration */ export * from './configuration/testrail-config'; -/** test-cases */ -export * from './test-cases/testrail-test-case-plugin'; -/** logging */ -export * from './logging/testrail-logging-plugin'; \ No newline at end of file +/** test-execution-policy */ +export * from './test-execution-policy/testrail-test-execution-policy-plugin'; +/** reporting */ +export * from './reporting/testrail-reporting-plugin'; \ No newline at end of file diff --git a/packages/aft-testrail/src/logging/testrail-logging-plugin.ts b/packages/aft-testrail/src/logging/testrail-logging-plugin.ts deleted file mode 100644 index dcec6be4..00000000 --- a/packages/aft-testrail/src/logging/testrail-logging-plugin.ts +++ /dev/null @@ -1,121 +0,0 @@ -import { LoggingPlugin, LogLevel, TestResult, ellide, ExpiringFileLock, fileio, LogMessageData, Merge, LoggingPluginOptions } from "aft-core"; -import { TestRailApi } from "../api/testrail-api"; -import { TestRailPlan, TestRailResultRequest } from "../api/testrail-custom-types"; -import { TestRailConfig, trconfig } from "../configuration/testrail-config"; -import { statusConverter } from "../helpers/status-converter"; - -export type TestRailLoggingPluginOptions = Merge; - -/** - * NOTE: this plugin can accept the following options from the `LogManager` via - * `aftconfig.json` - * ```json - * { - * "level": "warn", - * "maxLogCharacters": 300, - * "enabled": true - * } - * ``` - */ -export class TestRailLoggingPlugin extends LoggingPlugin { - private _logs: Map; - private _trConfig: TestRailConfig; - private _api: TestRailApi; - - constructor(options?: TestRailLoggingPluginOptions) { - super(options); - this._logs = new Map(); - } - - get config(): TestRailConfig { - if (!this._trConfig) { - this._trConfig = this.option('config') || trconfig; - } - return this._trConfig; - } - - get api(): TestRailApi { - if (!this._api) { - this._api = this.option('api') || new TestRailApi({config: this.config}); - } - return this._api; - } - - get maxLogCharacters(): number { - return this.option('maxLogCharacters', 250); - } - - logs(key: string, val?: string): string { - if (!this._logs.has(key)) { - this._logs.set(key, ''); - } - if (val) { - this._logs.set(key, val); - } - return this._logs.get(key); - } - - override async log(data: LogMessageData): Promise { - if (LogLevel.toValue(data.level) >= LogLevel.toValue(this.level) && data.level != 'none') { - let logs = this.logs(data.name); - if (logs.length > 0) { - logs += '\n'; // separate new logs from previous - } - logs += data.message; - logs = ellide(logs, this.maxLogCharacters, 'beginning'); - this.logs(data.name, logs); - } - } - - override async logResult(logName: string, result: TestResult): Promise { - if (result) { - await this._createTestPlanIfNone(); - const trResult: TestRailResultRequest = await this._getTestRailResultForExternalResult(logName, result); - const planId = await this.config.planId(); - await this.api.addResult(result.testId, planId, trResult); - } - } - - override async dispose(logName: string, error?: Error): Promise { - this._logs.delete(logName); - } - - private async _getTestRailResultForExternalResult(logName: string, result: TestResult): Promise { - let maxChars: number = this.maxLogCharacters; - let elapsed: number = 0; - if (result.metadata) { - let millis: number = result.metadata['durationMs'] || 0; - elapsed = Math.floor(millis / 60000); // elapsed is in minutes - } - const logs = this.logs(logName); - let trResult: TestRailResultRequest = { - comment: ellide(`${logs}\n${result.resultMessage}`, maxChars, 'beginning'), - defects: result.defects?.join(','), - elapsed: elapsed.toString(), - status_id: statusConverter.toTestRailStatus(result.status) - }; - - return trResult; - } - - private async _createTestPlanIfNone(): Promise { - const lock: ExpiringFileLock = fileio.getExpiringFileLock(this.constructor.name, 60000, 60000); - try { - // create new Test Plan if one doesn't already exist - const planId: number = await this.config.planId(); - if (planId <= 0) { - let projectId: number = await this.config.projectId(); - let suiteIds: number[] = await this.config.suiteIds(); - let plan: TestRailPlan = await this.api.createPlan(projectId, suiteIds); - this.config.setPlanId(plan.id); // sets value in FileSystemMap that is read by `this.trConfig.planId()` - } - } finally { - lock.unlock(); - } - } -} \ No newline at end of file diff --git a/packages/aft-testrail/src/reporting/testrail-reporting-plugin.ts b/packages/aft-testrail/src/reporting/testrail-reporting-plugin.ts new file mode 100644 index 00000000..44e658a7 --- /dev/null +++ b/packages/aft-testrail/src/reporting/testrail-reporting-plugin.ts @@ -0,0 +1,101 @@ +import { ReportingPlugin, LogLevel, TestResult, ellide, AftConfig, FileSystemMap } from "aft-core"; +import { TestRailApi } from "../api/testrail-api"; +import { TestRailResultRequest } from "../api/testrail-custom-types"; +import { TestRailConfig } from "../configuration/testrail-config"; +import { statusConverter } from "../helpers/status-converter"; +import { PlanId } from "../helpers/plan-id"; + + +/** + * this plugin uses the following configuration to control its operation via + * `aftconfig.json` and if the `logLevel` is unset it will be set from the value + * in `ReporterConfig` before falling back to a value of `warn` + * ```json + * { + * "TestRailConfig": { + * "logLevel": "warn", + * "maxLogCharacters": 300, + * "planId": 1234, + * "projectId": 12, + * "suiteIds": [34, 567] + * } + * } + * ``` + * > NOTE: if no value is set for `planId` and a `logLevel` value other than `none` is used + * then a new TestRail Plan will be created from the specified `projectId` and `suiteIds` + * configuration keys + */ +export class TestRailReportingPlugin extends ReportingPlugin { + private readonly _level: LogLevel; + public override get logLevel(): LogLevel { + return this._level; + } + + private readonly _logs: Map; + private readonly _api: TestRailApi; + private readonly _maxLogChars: number; + + constructor(aftCfg?: AftConfig, api?: TestRailApi) { + super(aftCfg); + const cfg = this.aftCfg.getSection(TestRailConfig); + this._level = cfg.logLevel ?? this.aftCfg.logLevel ?? 'warn'; + if (this.enabled) { + this._logs = new Map(); + this._api = api ?? new TestRailApi(this.aftCfg); + this._maxLogChars = cfg.maxLogCharacters ?? 250; + } + } + + logs(key: string, val?: string): string { + if (!this._logs.has(key)) { + this._logs.set(key, ''); + } + if (val) { + this._logs.set(key, val); + } + return this._logs.get(key); + } + + override log = async (name: string, level: LogLevel, message: string, ...data: any[]): Promise => { + if (this.enabled) { + if (LogLevel.toValue(level) >= LogLevel.toValue(this.logLevel) && level != 'none') { + let logs = this.logs(name); + if (logs.length > 0) { + logs += '\n'; // separate new logs from previous + } + logs += message; + logs = ellide(logs, this._maxLogChars, 'beginning'); + this.logs(name, logs); + } + } + } + + override submitResult = async (name: string, result: TestResult): Promise => { + if (this.enabled && result && name) { + const trResult: TestRailResultRequest = await this._getTestRailResultForTestResult(name ?? result.testName, result); + const planId = await PlanId.get(this.aftCfg, this._api); + await this._api.addResult(result.testId, planId, trResult); + } + } + + override finalise = async (logName: string): Promise => { + /* do nothing */ + } + + private async _getTestRailResultForTestResult(logName: string, result: TestResult): Promise { + let maxChars: number = this._maxLogChars; + let elapsed: number = 0; + if (result.metadata) { + let millis: number = result.metadata['durationMs'] || 0; + elapsed = Math.floor(millis / 60000); // elapsed is in minutes + } + const logs = this.logs(logName); + let trResult: TestRailResultRequest = { + comment: ellide(`${logs}\n${result.resultMessage}`, maxChars, 'beginning'), + elapsed: elapsed.toString(), + status_id: statusConverter.toTestRailStatus(result.status) + }; + + return trResult; + } +} \ No newline at end of file diff --git a/packages/aft-testrail/src/test-cases/testrail-test-case-plugin.ts b/packages/aft-testrail/src/test-cases/testrail-test-case-plugin.ts deleted file mode 100644 index ebf6a549..00000000 --- a/packages/aft-testrail/src/test-cases/testrail-test-case-plugin.ts +++ /dev/null @@ -1,150 +0,0 @@ -import { TestCase, TestCasePlugin, LogManager, Merge, TestCasePluginOptions } from 'aft-core'; -import { TestRailApi } from '../api/testrail-api'; -import { TestRailCase, TestRailRun, TestRailTest } from '../api/testrail-custom-types'; -import { TestRailConfig, trconfig } from '../configuration/testrail-config'; -import { statusConverter } from '../helpers/status-converter'; - -export type TestRailTestCasePluginOptions = Merge; - -/** - * NOTE: this plugin has no configuration options as they are - * all retrieved from `TestRailConfig` under the `TestRailConfig` - * section of your `aftconfig.json` file - */ -export class TestRailTestCasePlugin extends TestCasePlugin { - private _trConfig: TestRailConfig; - private _api: TestRailApi; - private _logMgr: LogManager; - - get config(): TestRailConfig { - if (!this._trConfig) { - this._trConfig = this.option('config') || trconfig; - } - return this._trConfig; - } - - get api(): TestRailApi { - if (!this._api) { - this._api = this.option('api') || new TestRailApi({config: this.config}); - } - return this._api; - } - - get logMgr(): LogManager { - if (!this._logMgr) { - this._logMgr = this.option('logMgr') || new LogManager({logName: this.constructor.name}); - } - return this._logMgr; - } - - override async getTestCase(caseId: string): Promise { - if (caseId && caseId.startsWith('C')) { - caseId = caseId.replace('C', ''); - } - let planId: number = await this.config.planId(); - let searchTerm: string = `case_id=${caseId}`; - if (planId <= 0) { - searchTerm = `id=${caseId}`; - } - let tests: TestCase[] = await this.findTestCases(searchTerm); - if (tests && tests.length > 0) { - return tests[0]; - } - return null; - } - - /** - * the `searchTerm` must take the format of `key=value` where the `key` is a valid - * field on a `TestRailTest` or `TestRailCase` object and the `value` is the expected - * value to be found for said `key` - * @param searchTerm a string containing a key and a value to be used to locate tests - */ - override async findTestCases(searchTerm: string): Promise { - if (searchTerm) { - let keyVal: string[] = searchTerm.split('='); - if (keyVal && keyVal.length > 1) { - let key: string = keyVal[0]; - let val: string = keyVal[1]; - return await this._findTestsByField(key, val); - } - } - return []; - } - - /** - * function will find a TestRail test or case by case id and if found - * will return true if the test is not already marked as passed. if - * no test is found then false is returned - * @param caseId the TestRail case id used to lookup either a test in an - * existing plan or a case in an existing suite - */ - override async shouldRun(caseId: string): Promise { - let test: TestCase = await this.getTestCase(caseId); - if (test) { - if (test.status != 'Passed') { - return true; - } - await this.logMgr.trace(`test '${caseId}' already marked as passed so do not run again`); - return false; - } - await this.logMgr.trace(`no test with case id: '${caseId}' could be found in the supplied Plan or Suites`); - return false; - } - - async dispose(error?: Error): Promise { - /* do nothing */ - } - - private async _findTestsByField(field: string, val: string): Promise { - let planId: number = await this.config.planId(); - let tests: TestCase[] = []; - if (planId > 0) { - // look for test in plan - let trRuns: TestRailRun[] = await this.api.getRunsInPlan(planId); - let runIds: number[] = []; - trRuns.forEach((r) => { - runIds.push(r.id); - }); - let trTests: TestRailTest[] = await this.api.getTestsInRuns(runIds); - for (var i=0; i { + if (caseId && caseId.startsWith('C')) { + caseId = caseId.replace('C', ''); + } + let searchTerm: string; + // if logging enabled then use TestRail Plan + if (this.aftCfg.getSection(TestRailConfig).logLevel != 'none') { + searchTerm = `case_id=${caseId}`; + } else { + // use Project and Suite IDs + searchTerm = `id=${caseId}`; + } + const tests: Array = await this.findTestCases(searchTerm); + if (tests && tests.length > 0) { + return tests[0]; + } + return null; + } + + /** + * the `searchTerm` must take the format of `key=value` where the `key` is a valid + * field on a `TestRailTest` or `TestRailCase` object and the `value` is the expected + * value to be found for said `key` + * @param searchTerm a string containing a key and a value to be used to locate tests + */ + async findTestCases(searchTerm: string): Promise> { + if (searchTerm) { + let keyVal: string[] = searchTerm.split('='); + if (keyVal && keyVal.length > 1) { + let key: string = keyVal[0]; + let val: string = keyVal[1]; + return await this._findTestsByField(key, val); + } + } + return []; + } + + /** + * function will find a TestRail test or case by case id and if found + * will return true if the test is not already marked as passed. if + * no test is found then false is returned + * @param caseId the TestRail case id used to lookup either a test in an + * existing plan or a case in an existing suite + */ + override shouldRun = async (caseId: string): Promise> => { + if (this.enabled) { + const cfg = this.aftCfg.getSection(TestRailConfig); + let test: TestRailCase = await this.getTestCase(caseId); + if (test) { + if (test['status_id']) { + if (statusConverter.fromTestRailStatus(test['status_id']) != 'passed') { + return {result: true, message: `'${caseId}' results found, but none of them were passing so re-run`}; + } + return {result: false, message: `'${caseId}' results found and already marked as passing`}; + } + return {result: true, message: `'${caseId}' exists in project: '${cfg.projectId}', suites: [${cfg.suiteIds.join(', ')}]`}; + } + return {result: false, message: `'${caseId}' not found in project: '${cfg.projectId}', suites: [${cfg.suiteIds.join(', ')}]`}; + } + return {result: true}; + } + + private async _findTestsByField(field: string, val: string): Promise> { + const cfg = this.aftCfg.getSection(TestRailConfig); + let tests = new Array(); + if ((cfg.logLevel ?? this.aftCfg.logLevel ?? 'warn') !== 'none') { + // look for TestRailTests in TestRail Plan + let planId: number = await PlanId.get(this.aftCfg, this._api); + let trRuns: TestRailRun[] = await this._api.getRunsInPlan(planId); + let runIds: number[] = []; + trRuns.forEach((r) => { + runIds.push(r.id); + }); + let trTests: TestRailTest[] = await this._api.getTestsInRuns(runIds); + for (var i=0; i { beforeEach(() => { @@ -32,13 +33,14 @@ describe('TestRailApi', () => { return response; }); - const opts: TestRailConfigOptions = { - url: 'http://127.0.0.1/', - user: 'fake@fake.fake', - accesskey: 'fake_key' - }; - let config: TestRailConfig = new TestRailConfig(opts); - let api: TestRailApi = new TestRailApi({config: config}); + const aftCfg = new AftConfig({ + TestRailConfig: { + url: 'http://127.0.0.1/', + user: 'fake@fake.fake', + accesskey: 'fake_key' + } + }); + let api: TestRailApi = new TestRailApi(aftCfg); try { await api.addResult('C1234', 1234, {}); @@ -68,13 +70,14 @@ describe('TestRailApi', () => { return response; }); - const opts: TestRailConfigOptions = { - url: 'http://127.0.0.1/', - user: 'fake@fake.fake', - accesskey: 'fake_key' - }; - let config: TestRailConfig = new TestRailConfig(opts); - let api: TestRailApi = new TestRailApi({config: config}); + const aftCfg = new AftConfig({ + TestRailConfig: { + url: 'http://127.0.0.1/', + user: 'fake@fake.fake', + accesskey: 'fake_key' + } + }); + let api: TestRailApi = new TestRailApi(aftCfg); let plan: TestRailPlan = await api.getPlan(123); expect(plan).toBeDefined(); @@ -102,13 +105,14 @@ describe('TestRailApi', () => { return response; }); - const opts: TestRailConfigOptions = { - url: 'http://127.0.0.1/', - user: 'fake@fake.fake', - accesskey: 'fake_key' - }; - let config: TestRailConfig = new TestRailConfig(opts); - let api: TestRailApi = new TestRailApi({config: config}); + const aftCfg = new AftConfig({ + TestRailConfig: { + url: 'http://127.0.0.1/', + user: 'fake@fake.fake', + accesskey: 'fake_key' + } + }); + let api: TestRailApi = new TestRailApi(aftCfg); let test: any = await api.getPlan(123); expect(test).not.toBeNull(); @@ -139,13 +143,14 @@ describe('TestRailApi', () => { return response; }); - const opts: TestRailConfigOptions = { - url: 'http://127.0.0.1/', - user: 'fake@fake.fake', - accesskey: 'fake_key' - }; - let config: TestRailConfig = new TestRailConfig(opts); - let api: TestRailApi = new TestRailApi({config: config}); + const aftCfg = new AftConfig({ + TestRailConfig: { + url: 'http://127.0.0.1/', + user: 'fake@fake.fake', + accesskey: 'fake_key' + } + }); + let api: TestRailApi = new TestRailApi(aftCfg); let plan: TestRailPlan = await api.createPlan(1, [2, 3]); expect(plan).toBeDefined(); diff --git a/packages/aft-testrail/test/configuration/testrail-config-spec.ts b/packages/aft-testrail/test/configuration/testrail-config-spec.ts deleted file mode 100644 index 013803f6..00000000 --- a/packages/aft-testrail/test/configuration/testrail-config-spec.ts +++ /dev/null @@ -1,61 +0,0 @@ -import * as fs from "fs"; -import * as path from "path"; -import { TestRailConfig, TestRailConfigOptions } from "../../src/configuration/testrail-config"; - -describe('TestRailConfig', () => { - beforeEach(() => { - const cachePath: string = path.join(process.cwd(), 'FileSystemMap'); - if (fs.existsSync(cachePath)) { - fs.rmSync(cachePath, {recursive: true, force: true}); - } - }); - - it('can get the url from config options', async () => { - let expectedUrl: string = 'http://fake.testrail.ie'; - const opts: TestRailConfigOptions = { - user: null, - accesskey: null, - url: expectedUrl - }; - let trConfig: TestRailConfig = new TestRailConfig(opts); - let url: string = await trConfig.url(); - - expect(url).toEqual(expectedUrl); - }); - - it('project_id defaults to -1', async () => { - const opts: TestRailConfigOptions = { - user: null, - accesskey: null, - url: null - }; - let trConfig: TestRailConfig = new TestRailConfig(opts); - const projectId: number = await trConfig.projectId(); - - expect(projectId).toBe(-1); - }); - - it('suite_ids defaults to empty array', async () => { - const opts: TestRailConfigOptions = { - user: null, - accesskey: null, - url: null - }; - let trConfig: TestRailConfig = new TestRailConfig(opts); - let suiteIds: number[] = await trConfig.suiteIds(); - - expect(suiteIds.length).toBe(0); - }); - - it('plan_id defaults to -1', async () => { - const opts: TestRailConfigOptions = { - user: null, - accesskey: null, - url: null - }; - let trConfig: TestRailConfig = new TestRailConfig(opts); - let planId: number = await trConfig.planId(); - - expect(planId).toBe(-1); - }); -}); \ No newline at end of file diff --git a/packages/aft-testrail/test/logging/testrail-logging-plugin-spec.ts b/packages/aft-testrail/test/reporting/testrail-reporting-plugin-spec.ts similarity index 50% rename from packages/aft-testrail/test/logging/testrail-logging-plugin-spec.ts rename to packages/aft-testrail/test/reporting/testrail-reporting-plugin-spec.ts index 73887e3a..037c8a97 100644 --- a/packages/aft-testrail/test/logging/testrail-logging-plugin-spec.ts +++ b/packages/aft-testrail/test/reporting/testrail-reporting-plugin-spec.ts @@ -1,13 +1,12 @@ import * as fs from "fs"; import * as path from "path"; -import { TestRailLoggingPlugin, TestRailLoggingPluginOptions } from "../../src/logging/testrail-logging-plugin"; -import { rand, TestResult, ellide, LogManager } from "aft-core"; +import { rand, TestResult, ellide, Reporter, AftConfig, pluginLoader } from "aft-core"; import { TestRailApi } from "../../src/api/testrail-api"; -import { TestRailConfig } from "../../src/configuration/testrail-config"; import { httpService } from "aft-web-services"; import { TestRailPlan, TestRailResult, TestRailResultRequest, TestRailTest } from "../../src/api/testrail-custom-types"; +import { TestRailReportingPlugin } from "../../src"; -describe('TestRailLoggingPlugin', () => { +describe('TestRailReportingPlugin', () => { beforeEach(() => { spyOn(httpService, 'performRequest').and.returnValue(Promise.resolve({ headers: {'content-type': 'application/json'}, @@ -18,161 +17,140 @@ describe('TestRailLoggingPlugin', () => { if (fs.existsSync(cachePath)) { fs.rmSync(cachePath, {recursive: true, force: true}); } + pluginLoader.reset(); }); afterEach(() => { TestStore.caseId = undefined; TestStore.planId = undefined; TestStore.request = undefined; + pluginLoader.reset(); }); it('keeps the last 250 characters logged', async () => { - const opts: TestRailLoggingPluginOptions = { - level: 'info', - maxLogCharacters: 250, - config: new TestRailConfig({ + const aftCfg = new AftConfig({ + TestRailConfig: { url: 'https://127.0.0.1/', user: 'fake@fake.fake', - accesskey: 'fake-key' - }) - }; - let plugin: TestRailLoggingPlugin = new TestRailLoggingPlugin(opts); + accesskey: 'fake-key', + logLevel: 'info', + maxLogCharacters: 250 + } + }); + let plugin: TestRailReportingPlugin = new TestRailReportingPlugin(aftCfg); let expected: string = rand.getString(250, true, true); const logName = 'keeps the last 250 characters logged'; - await plugin.log({level: 'info', message: expected, name: logName}); + await plugin.log(logName, 'info', expected); let actual: string = plugin.logs(logName); expect(actual).toEqual(expected); }); - it('removes logs for a given logName on call to dispose', async () => { - const opts: TestRailLoggingPluginOptions = { - level: 'info', - maxLogCharacters: 250, - config: new TestRailConfig({ - url: 'https://127.0.0.1/', - user: 'fake@fake.fake', - accesskey: 'fake-key' - }) - }; - let plugin: TestRailLoggingPlugin = new TestRailLoggingPlugin(opts); - - let expected: string = rand.getString(250, true, true); - const logName = rand.getString(15); - - await plugin.log({level: 'info', message: expected, name: logName}); - - let actual: string = plugin.logs(logName); - expect(actual).toEqual(expected); - - await plugin.dispose(logName); - actual = plugin.logs(logName); - expect(actual).toEqual(''); - }); - it('logging over 250 characters is ellided from beginning of string', async () => { - const opts: TestRailLoggingPluginOptions = { - level: 'info', - maxLogCharacters: 250, - config: new TestRailConfig({ + const aftCfg = new AftConfig({ + TestRailConfig: { url: 'https://127.0.0.1/', user: 'fake@fake.fake', - accesskey: 'fake-key' - }) - }; - let plugin: TestRailLoggingPlugin = new TestRailLoggingPlugin(opts); + accesskey: 'fake-key', + logLevel: 'info', + maxLogCharacters: 250 + } + }); + let plugin: TestRailReportingPlugin = new TestRailReportingPlugin(aftCfg); let notExpected: string = rand.getString(200, true, true); let expected: string = rand.getString(250, true, true); const logName = rand.getString(60); - await plugin.log({level: 'info', message: notExpected, name: logName}); - await plugin.log({level: 'info', message: expected, name: logName}); + await plugin.log(logName, 'info', notExpected); + await plugin.log(logName, 'info', expected); let actual: string = plugin.logs(logName); expect(actual).toEqual(ellide(`${notExpected}${expected}`, 250, 'beginning')); }); it('converts a Failed result to Retry', async () => { - const opts: TestRailLoggingPluginOptions = { - level: 'info', - config: new TestRailConfig({ + const aftCfg = new AftConfig({ + TestRailConfig: { url: 'https://127.0.0.1/', user: 'fake@fake.fake', - accesskey: 'fake-key' - }) - }; - opts.api = new TestRailApi({config: opts.config}); - spyOn(opts.api, 'addResult').and.callFake(async (caseId: string, planId: number, request: TestRailResultRequest): Promise => { + accesskey: 'fake-key', + logLevel: 'info', + planId: rand.getInt(999, 9999) + } + }); + const api = new TestRailApi(aftCfg); + spyOn(api, 'addResult').and.callFake(async (caseId: string, planId: number, request: TestRailResultRequest): Promise => { TestStore.caseId = caseId; TestStore.request = request; TestStore.planId = planId; return []; }); - let plugin: TestRailLoggingPlugin = new TestRailLoggingPlugin(opts); + let plugin: TestRailReportingPlugin = new TestRailReportingPlugin(aftCfg, api); let result: TestResult = { + testName: 'converts a Failed result to Retry', testId: 'C' + rand.getInt(99, 999), - status: 'Failed', + status: 'failed', resultId: rand.guid, created: Date.now(), metadata: {"durationMs": 1000} }; - await plugin.logResult('converts a Failed result to Retry', result); + await plugin.submitResult(result.testName, result); - expect(opts.api.addResult).toHaveBeenCalledTimes(1); + expect(api.addResult).toHaveBeenCalledTimes(1); expect(TestStore.request.status_id).toEqual(4); // 4 is Retest expect(TestStore.caseId).toEqual(result.testId); expect(TestStore.planId).toBeDefined(); }); it('creates a new TestRail plan in a shared FileSystemMap if none exists', async () => { - const opts: TestRailLoggingPluginOptions = { - level: 'info', - config: new TestRailConfig({ + const aftCfg = new AftConfig({ + TestRailConfig: { url: 'https://127.0.0.1/', user: 'fake@fake.fake', accesskey: 'fake-key', projectid: 3, - suiteids: [12, 15] - }) - }; - opts.api = new TestRailApi({config: opts.config}); + suiteids: [12, 15], + logLevel: 'info' + } + }); + const api = new TestRailApi(aftCfg); const planId: number = rand.getInt(1000, 10000); - spyOn(opts.api, 'createPlan').and.callFake(async (projectId: number, suiteIds: number[], name?: string): Promise => { + spyOn(api, 'createPlan').and.callFake(async (projectId: number, suiteIds: number[], name?: string): Promise => { return {id: planId}; }); - spyOn(opts.api, 'getTestByCaseId').and.callFake(async (caseId: string, planId: number): Promise => { + spyOn(api, 'getTestByCaseId').and.callFake(async (caseId: string, planId: number): Promise => { return { id: rand.getInt(1000, 10000) }; }); - let plugin: TestRailLoggingPlugin = new TestRailLoggingPlugin(opts); + let plugin: TestRailReportingPlugin = new TestRailReportingPlugin(aftCfg, api); let result: TestResult = { + testName: 'creates a new TestRail plan in a shared FileSystemMap if none exists', testId: 'C' + rand.getInt(99, 999), - status: 'Failed', + status: 'failed', resultId: rand.guid, created: Date.now(), metadata: {"durationMs": 1000} }; - await plugin.logResult('creates a new TestRail plan in a shared FileSystemMap if none exists', result); + await plugin.submitResult(result.testName, result); - expect(opts.api.createPlan).toHaveBeenCalledTimes(1); + expect(api.createPlan).toHaveBeenCalledTimes(1); const sharedCacheFile: string = path.join(process.cwd(), 'FileSystemMap', 'TestRailConfig.json'); expect(fs.existsSync(sharedCacheFile)).toBeTrue(); }); - it('can be loaded by the LogManager', async () => { - const conf = { - logName: 'can be loaded by the LogManager', - plugins: ['testrail-logging-plugin'] - }; - let mgr: LogManager = new LogManager(conf); - let plugin = await mgr.first(); + it('can be loaded by the Reporter', async () => { + const aftCfg = new AftConfig({ + pluginNames: ['testrail-reporting-plugin'] + }); + const mgr: Reporter = new Reporter('can be loaded by the Reporter', aftCfg); + const plugin = mgr.plugins[0]; expect(plugin).toBeDefined(); - expect(plugin.constructor.name).toEqual('TestRailLoggingPlugin'); + expect(plugin.constructor.name).toEqual('TestRailReportingPlugin'); }); /** @@ -183,31 +161,32 @@ describe('TestRailLoggingPlugin', () => { * `suite_ids` and `ITestResult.testId` should be updated to value values */ xit('sends actual TestResult to TestRail', async () => { - const opts: TestRailLoggingPluginOptions = { - config: new TestRailConfig({ + const aftCfg = new AftConfig({ + TestRailConfig: { url: '%testrail_url%', user: '%testrail_user%', accesskey: '%testrail_pass%', projectid: 3, - suiteids: [1219] - }), - level: 'trace' - }; - let plugin: TestRailLoggingPlugin = new TestRailLoggingPlugin(opts); + suiteids: [1219], + logLevel: 'trace' + } + }); + let plugin: TestRailReportingPlugin = new TestRailReportingPlugin(aftCfg); const logName = 'sends actual TestResult to TestRail'; - await plugin.log({level: 'error', message: rand.getString(100), name: logName}); + await plugin.log(logName, 'error', rand.getString(100)); let testResult: TestResult = { + testName: logName, testId: 'C4663085', // must be an existing TestRail Case ID - status: 'Failed', + status: 'failed', resultMessage: rand.getString(100), created: Date.now(), resultId: rand.guid, metadata: {"durationMs": 300000} }; - await plugin.logResult(logName, testResult); + await plugin.submitResult(testResult.testName, testResult); }, 300000); }); diff --git a/packages/aft-testrail/test/test-cases/testrail-test-case-plugin-spec.ts b/packages/aft-testrail/test/test-execution-policy/testrail-test-execution-policy-plugin-spec.ts similarity index 51% rename from packages/aft-testrail/test/test-cases/testrail-test-case-plugin-spec.ts rename to packages/aft-testrail/test/test-execution-policy/testrail-test-execution-policy-plugin-spec.ts index a3826835..5c3a931d 100644 --- a/packages/aft-testrail/test/test-cases/testrail-test-case-plugin-spec.ts +++ b/packages/aft-testrail/test/test-execution-policy/testrail-test-execution-policy-plugin-spec.ts @@ -1,13 +1,13 @@ import * as fs from 'fs'; import * as path from 'path'; -import { TestCase, TestCaseManager } from 'aft-core'; +import { TestExecutionPolicyManager, AftConfig } from 'aft-core'; import { httpService } from 'aft-web-services'; -import { TestRailConfig, TestRailTestCasePlugin, TestRailTestCasePluginOptions } from "../../src"; +import { TestRailTestExecutionPolicyPlugin } from "../../src"; import { TestRailApi } from '../../src/api/testrail-api'; import { TestRailCase, TestRailTest } from '../../src/api/testrail-custom-types'; import { statusConverter } from '../../src/helpers/status-converter'; -describe('TestRailTestCasePlugin', () => { +describe('TestRailTestExecutionPolicyPlugin', () => { beforeEach(() => { spyOn(httpService, 'performRequest').and.returnValue(Promise.resolve({ headers: {'content-type': 'application/json'}, @@ -21,46 +21,47 @@ describe('TestRailTestCasePlugin', () => { }); it('can lookup a test case in an existing plan by case id', async () => { - const opts: TestRailTestCasePluginOptions = { - config: new TestRailConfig({ + const aftCfg = new AftConfig({ + TestRailConfig: { url: 'http://127.0.0.1', user: 'fake@fake.fake', accesskey: 'fake_key', planid: 1234 - }) - }; - opts.api = new TestRailApi({config: opts.config}); + } + }); + const api = new TestRailApi(aftCfg); let expected: TestRailTest = { id: 1, case_id: 1234, priority_id: 2, title: 'fake test title', run_id: 2, - status_id: statusConverter.toTestRailStatus('Passed') + status_id: statusConverter.toTestRailStatus('passed') }; - spyOn(opts.api, 'getTestsInRuns').and.returnValue(Promise.resolve([expected])); - const plugin: TestRailTestCasePlugin = new TestRailTestCasePlugin(opts); + spyOn(api, 'getTestsInRuns').and.returnValue(Promise.resolve([expected])); + const plugin: TestRailTestExecutionPolicyPlugin = new TestRailTestExecutionPolicyPlugin(aftCfg, api); - const actual: TestCase = await plugin.getTestCase('C1234'); + const actual: TestRailTest = await plugin.getTestCase('C1234'); expect(actual).toBeDefined(); - expect(actual.id).toBe('1'); - expect(actual.status).toBe(statusConverter.fromTestRailStatus(expected.status_id)); + expect(actual.id).toBe(1); + expect(actual.status_id).toBe(expected.status_id); expect(actual.title).toBe(expected.title); - expect(opts.api.getTestsInRuns).toHaveBeenCalledTimes(1); + expect(api.getTestsInRuns).toHaveBeenCalledTimes(1); }); it('can lookup a test case in a supplied project and suite by case id', async () => { - const opts: TestRailTestCasePluginOptions = { - config: new TestRailConfig({ + const aftCfg = new AftConfig({ + TestRailConfig: { url: 'http://127.0.0.1', user: 'fake@fake.fake', accesskey: 'fake_key', projectid: 4, - suiteids: [12, 15] - }) - }; - opts.api = new TestRailApi({config: opts.config}); + suiteids: [12, 15], + logLevel: 'none' + } + }); + const api = new TestRailApi(aftCfg); let expected: TestRailCase = { id: 1234, priority_id: 2, @@ -68,27 +69,26 @@ describe('TestRailTestCasePlugin', () => { suite_id: 1122, created_on: Date.now() } as TestRailCase; - spyOn(opts.api, 'getCasesInSuites').and.returnValue(Promise.resolve([expected])); - let plugin: TestRailTestCasePlugin = new TestRailTestCasePlugin(opts); + spyOn(api, 'getCasesInSuites').and.returnValue(Promise.resolve([expected])); + let plugin: TestRailTestExecutionPolicyPlugin = new TestRailTestExecutionPolicyPlugin(aftCfg, api); - let actual: TestCase = await plugin.getTestCase('C1234'); + let actual: TestRailCase = await plugin.getTestCase('C1234'); expect(actual).toBeDefined(); - expect(actual.id).toBe(`C${expected.id}`); - expect(actual.status.valueOf()).toBe('Untested'); + expect(actual.id).toBe(expected.id); expect(actual.title).toBe(expected.title); - expect(actual.created).toEqual(expected.created_on); - expect(opts.api.getCasesInSuites).toHaveBeenCalledTimes(1); + expect(actual.created_on).toEqual(expected.created_on); + expect(api.getCasesInSuites).toHaveBeenCalledTimes(1); }); it('can be loaded by the testcasemanager', async () => { - const config = { - plugins: ['testrail-test-case-plugin'] - }; - let mgr: TestCaseManager = new TestCaseManager(config); - let plugin = await mgr.first(); + const aftCfg = new AftConfig({ + pluginNames: ['testrail-test-execution-policy-plugin'] + }); + let mgr: TestExecutionPolicyManager = new TestExecutionPolicyManager(aftCfg); + let plugin = await mgr.plugins[0]; expect(plugin).toBeDefined(); - expect(plugin.constructor.name).toEqual('TestRailTestCasePlugin'); + expect(plugin.constructor.name).toEqual('TestRailTestExecutionPolicyPlugin'); }); }); \ No newline at end of file diff --git a/packages/aft-ui-browsers/src/facets/browser-facet.ts b/packages/aft-ui-browsers/src/facets/browser-facet.ts deleted file mode 100644 index 7063cef4..00000000 --- a/packages/aft-ui-browsers/src/facets/browser-facet.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { Class, Merge, retry, wait } from "aft-core"; -import { UiFacet, UiElementOptions, UiFacetOptions } from "aft-ui"; -import { Locator, WebElement } from "selenium-webdriver"; -import { BrowserSession } from "../sessions/browser-session"; - -export type WebElementOptions = Merge; - -export type BrowserFacetOptions = Merge; - parent?: BrowserFacet; -}>; - -export class BrowserFacet extends UiFacet { - override get locator(): Locator { - return super.locator as Locator; - } - - override get session(): BrowserSession { - return super.session as BrowserSession; - } - - override get parent(): BrowserFacet { - return super.parent as BrowserFacet; - } - - override async getElements(options: WebElementOptions): Promise { - const maxWait = options.maxWaitMs ?? this.maxWaitMs; - const delay = options.retryDelayMs ?? this.retryDelayMs; - const delayType = options.retryDelayBackOff ?? this.retryDelayBackOff; - return retry(() => this.getRoot() - .then(r => r.findElements(options.locator))) - .withStartDelayBetweenAttempts(delay) - .withBackOff(delayType) - .withMaxDuration(maxWait); - } - - override async getElement(options: WebElementOptions): Promise { - const maxWait = options.maxWaitMs ?? this.maxWaitMs; - const delay = options.retryDelayMs ?? this.retryDelayMs; - const delayType = options.retryDelayBackOff ?? this.retryDelayBackOff; - const element: WebElement = await retry(() => this.getRoot() - .then(r => r.findElement(options.locator))) - .withStartDelayBetweenAttempts(delay) - .withBackOff(delayType) - .withMaxDuration(maxWait); - return element; - } - - override async getFacet>(facetType: Class, options?: BrowserFacetOptions): Promise { - options = options || {} as BrowserFacetOptions; - options.parent = options.parent || this; - options.session = options.session || this.session; - options.logMgr = options.logMgr || this.logMgr; - options.maxWaitMs = options.maxWaitMs ?? this.maxWaitMs; - options.retryDelayMs = options.retryDelayMs ?? this.retryDelayMs; - options.retryDelayBackOff = options.retryDelayBackOff ?? this.retryDelayBackOff; - const facet: T = new facetType(options); - return facet; - } - - override async getRoot(): Promise { - return retry(() => { - if (this.parent) { - return this.parent.getRoot() - .then(r => r.findElements(this.locator)) - .then(els => els[this.index]); - } else { - return this.session.driver.findElements(this.locator) - .then(els => els[this.index]); - } - }).withStartDelayBetweenAttempts(this.retryDelayMs) - .withBackOff(this.retryDelayBackOff) - .withMaxDuration(this.maxWaitMs); - } -} \ No newline at end of file diff --git a/packages/aft-ui-browsers/src/helpers/browser-verifier.ts b/packages/aft-ui-browsers/src/helpers/browser-verifier.ts deleted file mode 100644 index f6337129..00000000 --- a/packages/aft-ui-browsers/src/helpers/browser-verifier.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { Func, using, Verifier } from "aft-core"; -import { BrowserSession, BrowserSessionOptions } from "../sessions/browser-session"; -import { BrowserSessionGeneratorManager, browserSessionGeneratorMgr } from "../sessions/browser-session-generator-manager"; - -export class BrowserVerifier extends Verifier { - protected override _assertion: Func; - protected _sessionMgr: BrowserSessionGeneratorManager; - protected _session: BrowserSession; - protected _sessionOptions: BrowserSessionOptions; - - /** - * a `BrowserSessionGeneratorManager` instance used to generate new - * Browser sessions - */ - get sessionGeneratorManager(): BrowserSessionGeneratorManager { - if (!this._sessionMgr) { - this._sessionMgr = browserSessionGeneratorMgr; - } - return this._sessionMgr; - } - - /** - * after a new `BrowserSession` is created, this holds the instance - * so it can be referenced from within the executing `assertion` - */ - get session(): BrowserSession { - return this._session; - } - - /** - * the `BrowserSessionOptions` that will be used when creating a - * new `BrowserSession` - */ - get sessionOptions(): BrowserSessionOptions { - if (!this._sessionOptions) { - this._sessionOptions = {logMgr: this.logMgr}; - } - return this._sessionOptions; - } - - /** - * allows for specifying custom `BrowserSessionOptions` to be used when creating - * a new `BrowserSession` prior to executing the `assertion`. - * NOTE: if not set then only the `BrowserVerifier.logMgr` will be included in - * the `BrowserSessionOptions` - * @param options the `BrowserSessionOptions` to be used to create a new `BrowserSession` - * @returns this `BrowserVerifier` instance - */ - withBrowserSessionOptions(options: BrowserSessionOptions): this { - this._sessionOptions = options; - return this; - } - - /** - * allows for passing in an instance of `BrowserSessionGeneratorManager` to be - * used in locating a `BrowserSessionGeneratorPlugin` instance to use in - * generating a `BrowserSession`. - * NOTE: if not set then the global const `browserSessionGeneratorMgr` will be used - * @param sessionMgr a `BrowserSessionGeneratorManager` to be used instead of the Global instance - * @returns this `BrowserVerifier` instance - */ - withBrowserSessionGeneratorManager(sessionMgr: BrowserSessionGeneratorManager): this { - this._sessionMgr = sessionMgr; - return this; - } - - protected override async _resolveAssertion(): Promise { - let opts: BrowserSessionOptions = this.sessionOptions; - opts.logMgr = opts.logMgr || this.logMgr; - await using(await this.sessionGeneratorManager.newUiSession(opts), async (session) => { - this._session = session; - await super._resolveAssertion(); - }); - } -} - -/** - * creates a new `BrowserVerifier` instace to be used for executing some Functional - * Test Assertion. - * ex: - * ``` - * await verifyWithBrowser(async (v: BrowserVerifier) => { - * let facet: MyFacet = await v.session.getFacet(MyFacet); - * return await facet.returnExpectedValue(); - * }).withDescription('example usage for BrowserVerifier') - * .and.withTestId('C1234') - * .returns('expected value'); - * ``` - * @param assertion the {Func} function to be executed by this `BrowserVerifier` - * @returns a new `BrowserVerifier` instance - */ -export const verifyWithBrowser = (assertion: Func): BrowserVerifier => { - return new BrowserVerifier().verify(assertion); -} \ No newline at end of file diff --git a/packages/aft-ui-browsers/src/index.ts b/packages/aft-ui-browsers/src/index.ts deleted file mode 100644 index 6b31f598..00000000 --- a/packages/aft-ui-browsers/src/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* facets */ -export * from './facets/browser-facet'; -/* helpers */ -export * from './helpers/browser-verifier'; -/* sessions */ -export * from './sessions/browser-session-generator-plugin'; -export * from './sessions/browser-session'; -export {browserSessionGeneratorMgr} from './sessions/browser-session-generator-manager'; -/* sessions - BrowserStack plugin */ -export * from './sessions/browserstack/browserstack-browser-session-generator-plugin'; -export * from './sessions/browserstack/browserstack-browser-session'; -/* sessions - Saucelabs plugin */ -export * from './sessions/sauce-labs/sauce-labs-browser-session-generator-plugin'; -export * from './sessions/sauce-labs/sauce-labs-browser-session'; -/* sessions - Selenium Grid plugin */ -export * from './sessions/selenium-grid/selenium-grid-session-generator-plugin'; \ No newline at end of file diff --git a/packages/aft-ui-browsers/src/sessions/browser-session-generator-manager.ts b/packages/aft-ui-browsers/src/sessions/browser-session-generator-manager.ts deleted file mode 100644 index 20398831..00000000 --- a/packages/aft-ui-browsers/src/sessions/browser-session-generator-manager.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { UiSessionGeneratorManager, UiSessionGeneratorManagerOptions } from "aft-ui"; -import { BrowserSession, BrowserSessionOptions } from "./browser-session"; -import { BrowserSessionGeneratorPlugin } from "./browser-session-generator-plugin"; - -export type BrowserSessionGeneratorManagerOptions = UiSessionGeneratorManagerOptions - -/** - * responsible for loading in any referenced `BrowserSessionGeneratorPlugin` implementations - * from the `aftconfig.json` file under the following section: - * ```json - * { - * "BrowserSessionGeneratorManager": { - * "plugins": [{ - * "name": "browserstack-browser-session-generator-plugin", - * "options": { - * "uiplatform": "android_11_chrome_99_Google Pixel XL", - * "capabilities": { - * "key": "value" - * } - * } - * }] - * } - * } - * ``` - */ -export class BrowserSessionGeneratorManager extends UiSessionGeneratorManager, BrowserSessionGeneratorManagerOptions> { - override async newUiSession(options?: BrowserSessionOptions): Promise> { - return await this.first() - .then(f => f.newUiSession(options) - .catch(async (err) => { - const l = await this.logMgr(); - await l.warn(`error calling '${f.constructor.name}.newUiSession(...)' due to: ${err}`); - return null; - })) - .catch(async (err) => { - const l = await this.logMgr(); - await l.warn(`error calling 'plugin.newUiSession(...)' due to: ${err}`); - return null; - }); - } -} - -/** - * responsible for loading in any referenced `BrowserSessionGeneratorPlugin` implementations - * from the `aftconfig.json` file under the following section: - * ```json - * { - * "BrowserSessionGeneratorManager": { - * "uiplatform": "android_11_chrome_99_Google Pixel XL", - * "plugins": [{ - * "name": "browserstack-browser-session-generator-plugin", - * "options": { - * "capabilities": { - * "key": "value" - * } - * } - * }] - * } - * } - * ``` - */ -export const browserSessionGeneratorMgr = new BrowserSessionGeneratorManager(); \ No newline at end of file diff --git a/packages/aft-ui-browsers/src/sessions/browser-session-generator-plugin.ts b/packages/aft-ui-browsers/src/sessions/browser-session-generator-plugin.ts deleted file mode 100644 index d50647e0..00000000 --- a/packages/aft-ui-browsers/src/sessions/browser-session-generator-plugin.ts +++ /dev/null @@ -1,88 +0,0 @@ -import { WebDriver, Builder, Capabilities } from "selenium-webdriver"; -import { UiSessionGeneratorPlugin, UiSessionGeneratorPluginOptions } from "aft-ui"; -import { BrowserSessionOptions } from "./browser-session"; -import { Err, Merge } from "aft-core"; - -export type BrowserSessionGeneratorPluginOptions = Merge; - -/** - * abstract class to be extended by any Browser Session Generator Plugins to be - * loaded by the `BrowserSessionGeneratorManager`. accepts options of the following: - * ```json - * { - * "url": "http://url.to/selenium/grid", - * "uiplatform": "android_11_firefox_75_Google Pixel XL", - * "additionalCapabilities": { - * "someKey": "someValue" - * }, - * "implicitTimeout": 3000 - * } - * ``` - */ -export abstract class BrowserSessionGeneratorPlugin extends UiSessionGeneratorPlugin { - private _url: string; - private _resolution: string; - private _caps: object; - private _timeout: number; - - get url(): string { - if (!this._url) { - this._url = this.option('url'); - } - return this._url; - } - get resolution(): string { - if (!this._resolution) { - this._resolution = this.option('resolution'); - } - return this._resolution; - } - get additionalCapabilities(): object { - if (!this._caps) { - this._caps = this.option('additionalCapabilities', {}); - } - return this._caps; - } - get implicitTimeout(): number { - if (!this._timeout) { - this._timeout = this.option('implicitTimeout', 1000); - } - return this._timeout; - } - - abstract generateCapabilities(options?: BrowserSessionOptions): Promise; - - /** - * expected to be called from within `BrowserSessionGeneratorPlugin` implementations - * after configuring their own `Capabilties` within their `newUiSession` function - * @param capabilities capabilities to pass to the Remote WebDriver Builder - * @returns a new `WebDriver` instance - */ - protected async createDriver(capabilities: Capabilities): Promise { - if (capabilities) { - try { - const driver: WebDriver = await new Builder() - .usingServer(this.url) - .withCapabilities(capabilities) - .build(); - await Err.handle(() => driver.manage().setTimeouts({implicit: this.implicitTimeout}), { - logMgr: this.logMgr, - errLevel: 'debug' - }); - await Err.handle(() => driver.manage().window().maximize(), { - logMgr: this.logMgr, - errLevel: 'debug' - }); - return driver; - } catch (e) { - return Promise.reject(e); - } - } - return null; - } -} \ No newline at end of file diff --git a/packages/aft-ui-browsers/src/sessions/browser-session.ts b/packages/aft-ui-browsers/src/sessions/browser-session.ts deleted file mode 100644 index cd35e55a..00000000 --- a/packages/aft-ui-browsers/src/sessions/browser-session.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { WebDriver } from "selenium-webdriver"; -import { Class, Merge } from "aft-core"; -import { UiFacet, UiFacetOptions, UiPlatform, UiSession, UiSessionOptions } from "aft-ui"; - -export type BrowserSessionOptions = Merge; - -export class BrowserSession extends UiSession { - private _uiplatform: UiPlatform; - private _resolution: string; - private _additionalCapabilities: object; - - get uiplatform(): UiPlatform { - if (!this._uiplatform) { - const plt = this.option('uiplatform', '+_+_+_+_+'); - this._uiplatform = UiPlatform.parse(plt); - } - return this._uiplatform; - } - - get resolution(): string { - if (!this._resolution) { - this._resolution = this.option('resolution'); - } - return this._resolution; - } - - get additionalCapabilities(): object { - if (!this._additionalCapabilities) { - this._additionalCapabilities = this.option('additionalCapabilities', {}); - } - return this._additionalCapabilities; - } - - override get driver(): WebDriver { - return this.option('driver'); - } - - async getFacet, To extends UiFacetOptions>(facetType: Class, options?: To): Promise { - options = options || {} as To; - options.session = options.session || this; - options.logMgr = options.logMgr || this.logMgr; - const facet: T = new facetType(options); - return facet; - } - - async goTo(url: string): Promise> { - try { - await this.driver?.get(url); - } catch (e) { - return Promise.reject(e); - } - return this; - } - - async refresh(): Promise> { - try { - await this.driver?.navigate().refresh(); - } catch (e) { - return Promise.reject(e); - } - return this; - } - - async resize(width: number, height: number): Promise> { - try { - await this.driver?.manage().window().setSize(width, height); - } catch (e) { - return Promise.reject(e); - } - return this; - } - - async dispose(error?: any): Promise { - if (error) { - await this.logMgr.warn(error); - } - await this.logMgr.debug(`closing driver instance...`); - await this.driver?.quit(); - await this.logMgr.debug(`driver instance closed.`); - } -} \ No newline at end of file diff --git a/packages/aft-ui-browsers/src/sessions/browserstack/browserstack-browser-session-generator-plugin.ts b/packages/aft-ui-browsers/src/sessions/browserstack/browserstack-browser-session-generator-plugin.ts deleted file mode 100644 index 2ff52300..00000000 --- a/packages/aft-ui-browsers/src/sessions/browserstack/browserstack-browser-session-generator-plugin.ts +++ /dev/null @@ -1,116 +0,0 @@ -import { UiPlatform } from "aft-ui"; -import { BrowserSessionGeneratorPlugin, BrowserSessionGeneratorPluginOptions } from "../browser-session-generator-plugin"; -import { Capabilities } from "selenium-webdriver"; -import { BrowserStackBrowserSession, BrowserStackBrowserSessionOptions } from "./browserstack-browser-session"; -import { buildinfo, Merge } from "aft-core"; - -export type BrowserStackBrowserSessionGeneratorPluginOptions = Merge; - -export class BrowserStackBrowserSessionGeneratorPlugin extends BrowserSessionGeneratorPlugin { - private _user: string; - private _key: string; - private _local: boolean; - private _localIdentifier: string; - private _debug: boolean; - - get user(): string { - if (!this._user) { - this._user = this.option('user'); - } - return this._user; - } - - get key(): string { - if (!this._key) { - this._key = this.option('key'); - } - return this._key; - } - - get local(): boolean { - if (!this._local) { - this._local = this.option('local', false); - } - return this._local; - } - - get localIdentifier(): string { - if (!this._localIdentifier) { - this._localIdentifier = this.option('localIdentifier'); - } - return this._localIdentifier; - } - - get debug(): boolean { - if (!this._debug) { - this._debug = this.option('debug', false); - } - return this._debug; - } - - override get url(): string { - return super.url || 'https://hub-cloud.browserstack.com/wd/hub/'; - } - - override async newUiSession(options?: BrowserStackBrowserSessionOptions): Promise { - const caps: Capabilities = await this.generateCapabilities(options) - options.driver = options.driver || await this.createDriver(caps); - return new BrowserStackBrowserSession(options); - } - - override async generateCapabilities(options?: BrowserStackBrowserSessionOptions): Promise { - options = options || {}; - options.uiplatform = options?.uiplatform || this.uiplatform.toString(); - options.user = options.user || this.user; - options.key = options.key || this.key; - options.debug = options.debug || this.debug; - options.local = options.local || this.local; - options.localIdentifier = options.localIdentifier || this.localIdentifier; - options.resolution = options.resolution || this.resolution; - options.logMgr = options.logMgr || this.logMgr; - options.additionalCapabilities = options.additionalCapabilities || this.additionalCapabilities; - - let capabilities: Capabilities = new Capabilities(); - const platform = UiPlatform.parse(options.uiplatform); - if (platform.browser) { - capabilities.set('browserName', platform.browser); - } - if (platform.browserVersion) { - capabilities.set('browser_version', platform.browserVersion); - } - if (platform.os) { - capabilities.set('os', platform.os); - } - if (platform.osVersion) { - capabilities.set('os_version', platform.osVersion); - } - if (platform.deviceName) { - capabilities.set('device', platform.deviceName); - capabilities.set('realMobile', 'true'); - } - if (options.resolution) { - capabilities.set('resolution', options.resolution); - } - capabilities.set('browserstack.user', options.user); - capabilities.set('browserstack.key', options.key); - capabilities.set('browserstack.debug', options.debug); - capabilities.set('build', await buildinfo.get()); - capabilities.set('name', options.logMgr?.logName); - if (options.local) { - capabilities.set('browserstack.local', true); - if (options.localIdentifier) { - capabilities.set('browserstack.localIdentifier', options.localIdentifier); - } - } - // overwrite the above with passed in capabilities if any - const addlCaps: Capabilities = new Capabilities(options.additionalCapabilities); - capabilities = capabilities.merge(addlCaps); - return capabilities; - } -} \ No newline at end of file diff --git a/packages/aft-ui-browsers/src/sessions/browserstack/browserstack-browser-session.ts b/packages/aft-ui-browsers/src/sessions/browserstack/browserstack-browser-session.ts deleted file mode 100644 index 01fcb811..00000000 --- a/packages/aft-ui-browsers/src/sessions/browserstack/browserstack-browser-session.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { Merge } from "aft-core"; -import { BrowserSession, BrowserSessionOptions } from "../browser-session"; - -export type BrowserStackBrowserSessionOptions = Merge; - -export class BrowserStackBrowserSession extends BrowserSession { - private _user: string; - private _key: string; - private _local: boolean; - private _localIdentifier: string; - private _debug: boolean; - - get user(): string { - if (!this._user) { - this._user = this.option('user'); - } - return this._user; - } - - get key(): string { - if (!this._key) { - this._key = this.option('key'); - } - return this._key; - } - - get local(): boolean { - if (!this._local) { - this._local = this.option('local'); - } - return this._local; - } - - get localIdentifier(): string { - if (!this._localIdentifier) { - this._localIdentifier = this.option('localIdentifier'); - } - return this._localIdentifier; - } - - get debug(): boolean { - if (!this._debug) { - this._debug = this.option('debug'); - } - return this._debug; - } - - override async dispose(error?: any): Promise { - try { - let setStatus: {} = { - "action": "setSessionStatus", - "arguments": { - "status": (error) ? 'failed' : 'passed', - "reason": error || 'successful test' - } - }; - await this.driver?.executeScript(`browserstack_executor: ${JSON.stringify(setStatus)}`); - } catch (e) { - await this.logMgr.warn(e); - } - - await super.dispose(error); - } -} \ No newline at end of file diff --git a/packages/aft-ui-browsers/src/sessions/sauce-labs/sauce-labs-browser-session-generator-plugin.ts b/packages/aft-ui-browsers/src/sessions/sauce-labs/sauce-labs-browser-session-generator-plugin.ts deleted file mode 100644 index 77d7b655..00000000 --- a/packages/aft-ui-browsers/src/sessions/sauce-labs/sauce-labs-browser-session-generator-plugin.ts +++ /dev/null @@ -1,113 +0,0 @@ -import { UiPlatform } from "aft-ui"; -import { BrowserSessionGeneratorPlugin, BrowserSessionGeneratorPluginOptions } from "../browser-session-generator-plugin"; -import { Capabilities } from "selenium-webdriver"; -import { BrowserSessionOptions } from "../browser-session"; -import { SauceLabsBrowserSession, SauceLabsBrowserSessionOptions } from "./sauce-labs-browser-session"; -import { buildinfo, Merge } from "aft-core"; - -export type SauceLabsBrowserSessionGeneratorPluginOptions = Merge; - -export class SauceLabsBrowserSessionGeneratorPlugin extends BrowserSessionGeneratorPlugin { - private _username: string; - private _accessKey: string; - private _tunnel: boolean; - private _tunnelIdentifier: string; - - get username(): string { - if (!this._username) { - this._username = this.option('username'); - } - return this._username; - } - - get accessKey(): string { - if (!this._accessKey) { - this._accessKey = this.option('accessKey'); - } - return this._accessKey; - } - - get tunnel(): boolean { - if (!this._tunnel) { - this._tunnel = this.option('tunnel', false); - } - return this._tunnel; - } - - get tunnelIdentifier(): string { - if (!this._tunnelIdentifier) { - this._tunnelIdentifier = this.option('tunnelIdentifier'); - } - return this._tunnelIdentifier; - } - - override get url(): string { - return super.url || 'https://ondemand.us-east-1.saucelabs.com/wd/hub/'; - } - - override async newUiSession(options?: BrowserSessionOptions): Promise { - const caps: Capabilities = await this.generateCapabilities(options); - options.driver = options.driver || await this.createDriver(caps); - return new SauceLabsBrowserSession(options); - } - - override async generateCapabilities(options?: SauceLabsBrowserSessionOptions): Promise { - options = options || {}; - options.uiplatform = options?.uiplatform || this.uiplatform.toString(); - options.username = options.username || this.username; - options.accessKey = options.accessKey || this.accessKey; - options.tunnel = options.tunnel || this.tunnel; - options.tunnelIdentifier = options.tunnelIdentifier || this.tunnelIdentifier; - options.resolution = options.resolution || this.resolution; - options.logMgr = options.logMgr || this.logMgr; - options.additionalCapabilities = options.additionalCapabilities || this.additionalCapabilities; - let capabilities: Capabilities = new Capabilities(); - const platform: UiPlatform = (options?.uiplatform) ? UiPlatform.parse(options.uiplatform) : this.uiplatform; - if (platform.deviceName) { - capabilities.set('platformName', platform.os); - capabilities.set('platformVersion', platform.osVersion); - } else { - let osVersion: string = ''; - if (platform.osVersion) { - osVersion = ' ' + platform.osVersion; - } - capabilities.set('platformName', `${platform.os}${osVersion}`); - } - if (platform.browser) { - capabilities.set('browserName', platform.browser); - } - if (platform.browserVersion) { - capabilities.set('browserVersion', platform.browserVersion); - } - if (platform.deviceName) { - capabilities.set('deviceName', platform.deviceName); - } - capabilities.set('sauce:options', { - 'username': options.username, - 'accessKey': options.accessKey, - 'build': await buildinfo.get(), - 'name': options?.logMgr?.logName || this.logMgr.logName - }); - let resolution: string = options?.resolution || this.resolution; - if (resolution) { - let opts: object = capabilities.get('sauce:options'); - opts['screenResolution'] = resolution; - capabilities.set('sauce:options', opts); - } - let tunnel: boolean = options.tunnel; - if (tunnel) { - let opts: {} = capabilities.get('sauce:options'); - opts['tunnelIdentifier'] = options.tunnelIdentifier; - capabilities.set('sauce:options', opts); - } - // overwrite the above with passed in capabilities if any - const addlCaps: Capabilities = new Capabilities(options.additionalCapabilities); - capabilities = capabilities.merge(addlCaps); - return capabilities; - } -} \ No newline at end of file diff --git a/packages/aft-ui-browsers/src/sessions/sauce-labs/sauce-labs-browser-session.ts b/packages/aft-ui-browsers/src/sessions/sauce-labs/sauce-labs-browser-session.ts deleted file mode 100644 index e0b803f7..00000000 --- a/packages/aft-ui-browsers/src/sessions/sauce-labs/sauce-labs-browser-session.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { Merge } from "aft-core"; -import { BrowserSession, BrowserSessionOptions } from "../browser-session"; - -export type SauceLabsBrowserSessionOptions = Merge; - -export class SauceLabsBrowserSession extends BrowserSession { - private _username: string; - private _accessKey: string; - private _tunnel: boolean; - private _tunnelIdentifier: string; - - get username(): string { - if (!this._username) { - this._username = this.option('username'); - } - return this._username; - } - - get accessKey(): string { - if (!this._accessKey) { - this._accessKey = this.option('accessKey'); - } - return this._accessKey; - } - - get tunnel(): boolean { - if (!this._tunnel) { - this._tunnel = this.option('tunnel'); - } - return this._tunnel; - } - - get tunnelIdentifier(): string { - if (!this._tunnelIdentifier) { - this._tunnelIdentifier = this.option('tunnelIdentifier'); - } - return this._tunnelIdentifier; - } - - override async dispose(error: any): Promise { - try { - await this.driver?.executeScript(`sauce:job-result=${(error) ? 'failed' : 'passed'}`); - } catch (e) { - await this.logMgr.warn(e); - } - - await super.dispose(error); - } -} \ No newline at end of file diff --git a/packages/aft-ui-browsers/src/sessions/selenium-grid/selenium-grid-session-generator-plugin.ts b/packages/aft-ui-browsers/src/sessions/selenium-grid/selenium-grid-session-generator-plugin.ts deleted file mode 100644 index f1b3ad2c..00000000 --- a/packages/aft-ui-browsers/src/sessions/selenium-grid/selenium-grid-session-generator-plugin.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { BrowserSessionGeneratorPlugin, BrowserSessionGeneratorPluginOptions } from "../browser-session-generator-plugin"; -import { UiPlatform } from "aft-ui"; -import { Capabilities } from "selenium-webdriver"; -import { BrowserSession, BrowserSessionOptions } from "../browser-session"; - -export class SeleniumGridSessionGeneratorPlugin extends BrowserSessionGeneratorPlugin { - override async newUiSession(options?: BrowserSessionOptions): Promise> { - const caps: Capabilities = await this.generateCapabilities(options); - options.driver = options.driver || await this.createDriver(caps); - return new BrowserSession(options); - } - override async generateCapabilities(options?: BrowserSessionOptions): Promise { - options = options || {}; - options.logMgr = options.logMgr || this.logMgr; - options.uiplatform = options.uiplatform || this.uiplatform.toString(); - options.additionalCapabilities = options.additionalCapabilities || this.additionalCapabilities; - let capabilities: Capabilities = new Capabilities(); - let platform: UiPlatform = UiPlatform.parse(options.uiplatform); - let osVersion = ''; - if (platform.osVersion) { - osVersion = ' ' + platform.osVersion; - } - let browserVersion = ''; - if (platform.browserVersion) { - browserVersion = ' ' + platform.browserVersion; - } - capabilities.set('platform', `${platform.os}${osVersion}`); - capabilities.set('browserName', `${platform.browser}${browserVersion}`); - // overwrite the above with passed in capabilities if any - const optCaps: Capabilities = new Capabilities(options.additionalCapabilities); - capabilities = capabilities.merge(optCaps); - return capabilities; - } -} \ No newline at end of file diff --git a/packages/aft-ui-browsers/test/facets/browser-facet-spec.ts b/packages/aft-ui-browsers/test/facets/browser-facet-spec.ts deleted file mode 100644 index f9ce091b..00000000 --- a/packages/aft-ui-browsers/test/facets/browser-facet-spec.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { By, WebDriver, WebElement, Session } from "selenium-webdriver"; -import { LogManager, rand } from "aft-core"; -import { BrowserSession, BrowserFacet, BrowserFacetOptions } from "../../src"; - -describe('BrowserFacet', () => { - beforeEach(() => { - jasmine.getEnv().allowRespy(true); - }); - - it('can auto-refresh from WebDriver on Error in getRoot', async () => { - let element: WebElement = jasmine.createSpyObj('WebElement', { - 'isDisplayed': Promise.resolve(true), - 'isEnabled': Promise.resolve(true), - 'click': Promise.resolve(), - 'sendKeys': Promise.resolve(), - 'getAttribute': Promise.resolve('foo'), - 'findElements': Promise.resolve([]) - }); - let sesh: Session = jasmine.createSpyObj('Session', { - 'getId': rand.guid - }); - let driver: WebDriver = jasmine.createSpyObj('WebDriver', { - 'findElements': Promise.resolve([element]), - 'close': Promise.resolve(), - 'quit': Promise.resolve(), - 'getSession': Promise.resolve(sesh) - }); - spyOn(driver, 'findElements').and.returnValues(Promise.reject('no element'), Promise.resolve([element])); - let session: BrowserSession = new BrowserSession({ - driver: driver, - logMgr: new LogManager({logName: 'can auto-refresh from WebDriver on Error in getRoot'}) - }); - let facet: BrowserFacet = await session.getFacet(BrowserFacet, { - locator: By.css('div.fake'), - maxWaitMs: 4000 - }); - let actual: WebElement = await facet.getRoot(); - - expect(actual).toBeDefined(); - expect(await actual.isDisplayed()).toBe(true); - expect(driver.findElements).toHaveBeenCalledTimes(2); - }); -}); \ No newline at end of file diff --git a/packages/aft-ui-browsers/test/helpers/browser-verifier-spec.ts b/packages/aft-ui-browsers/test/helpers/browser-verifier-spec.ts deleted file mode 100644 index 10be5126..00000000 --- a/packages/aft-ui-browsers/test/helpers/browser-verifier-spec.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { rand, TestCaseManager } from "aft-core"; -import { Session, WebDriver } from "selenium-webdriver"; -import { BrowserSession, BrowserSessionOptions, verifyWithBrowser, BrowserVerifier } from "../../src"; -import { BrowserSessionGeneratorManager } from "../../src/sessions/browser-session-generator-manager"; - -describe('BrowserVerifier', () => { - it('can create a BrowserSession', async () => { - let sessionMgr: BrowserSessionGeneratorManager = new BrowserSessionGeneratorManager(); - spyOn(sessionMgr, 'newUiSession').and.callFake((options?: BrowserSessionOptions): Promise> => { - return Promise.resolve(new BrowserSession(options)); - }); - - await verifyWithBrowser(async (bv: BrowserVerifier) => { - expect(bv.session).withContext('BrowserVerifier should create a new session').toBeDefined(); - expect(bv.session.logMgr.logName).withContext('the new session should use the same logger as the verifier').toBe(bv.logMgr.logName); - }).and.withBrowserSessionGeneratorManager(sessionMgr); - - expect(sessionMgr.newUiSession).toHaveBeenCalledTimes(1); - }); - - it('can create a BrowserSession using specific BrowserSessionOptions', async () => { - let sessionMgr: BrowserSessionGeneratorManager = new BrowserSessionGeneratorManager(); - spyOn(sessionMgr, 'newUiSession').and.callFake((options?: BrowserSessionOptions): Promise> => { - expect(options.uiplatform).toEqual('windows_8.1_firefox'); - return Promise.resolve(new BrowserSession(options)); - }); - - await verifyWithBrowser((bv: BrowserVerifier) => { - expect(bv.session).toBeDefined(); - expect(bv.session.platform.toString()).toEqual('windows_8.1_firefox_+_+'); - }).and.withBrowserSessionGeneratorManager(sessionMgr) - .and.withBrowserSessionOptions({ - uiplatform: 'windows_8.1_firefox' - }); - - expect(sessionMgr.newUiSession).toHaveBeenCalledTimes(1); - }); - - it('disposes of BrowserSession on completion', async () => { - let sessionMgr: BrowserSessionGeneratorManager = new BrowserSessionGeneratorManager(); - spyOn(sessionMgr, 'newUiSession').and.callFake((options?: BrowserSessionOptions): Promise> => { - return Promise.resolve(new BrowserSession(options)); - }); - let sesh: Session = jasmine.createSpyObj('Session', { - 'getId': rand.guid - }); - let driver: WebDriver = jasmine.createSpyObj('WebDriver', { - 'quit': Promise.resolve(), - 'getSession': Promise.resolve(sesh) - }); - - await verifyWithBrowser((bv: BrowserVerifier) => { - expect(bv.session).toBeDefined(); - }).and.withBrowserSessionOptions({driver: driver}) - .and.withBrowserSessionGeneratorManager(sessionMgr); - - expect(sessionMgr.newUiSession).toHaveBeenCalledTimes(1); - expect(driver.quit).toHaveBeenCalledTimes(1); - }); - - it('no BrowserSession is created if assertion should not be run', async () => { - let sessionMgr: BrowserSessionGeneratorManager = new BrowserSessionGeneratorManager(); - spyOn(sessionMgr, 'newUiSession').and.callFake((options?: BrowserSessionOptions): Promise> => { - return Promise.resolve(new BrowserSession(options)); - }); - let tcMgr: TestCaseManager = new TestCaseManager(); - spyOn(tcMgr, 'shouldRun').and.callFake((testId: string) => Promise.resolve(false)); - - await verifyWithBrowser((bv: BrowserVerifier) => { - expect(true).toBeFalse(); - }).and.withBrowserSessionGeneratorManager(sessionMgr) - .and.withTestIds('C1234') - .and.withTestCaseManager(tcMgr); - - expect(sessionMgr.newUiSession).not.toHaveBeenCalled(); - }); -}); \ No newline at end of file diff --git a/packages/aft-ui-browsers/test/sessions/browser-session-generator-plugin-manager-spec.ts b/packages/aft-ui-browsers/test/sessions/browser-session-generator-plugin-manager-spec.ts deleted file mode 100644 index 85b1fefa..00000000 --- a/packages/aft-ui-browsers/test/sessions/browser-session-generator-plugin-manager-spec.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { BrowserSessionGeneratorManager } from "../../src/sessions/browser-session-generator-manager"; - -describe('BrowserSessionGeneratorManager', () => { - it('can load the BrowserStackBrowserSessionGeneratorPlugin', async () => { - let mgr: BrowserSessionGeneratorManager = new BrowserSessionGeneratorManager({ - plugins: ['browserstack-browser-session-generator-plugin'] - }); - let plugin = await mgr.first(); - - expect(plugin).toBeDefined(); - expect(plugin.constructor.name).toEqual('BrowserStackBrowserSessionGeneratorPlugin'); - }); - - it('can load the SauceLabsBrowserSessionGeneratorPlugin', async () => { - let mgr: BrowserSessionGeneratorManager = new BrowserSessionGeneratorManager({ - plugins: ['sauce-labs-browser-session-generator-plugin'] - }); - let plugin = await mgr.first(); - - expect(plugin).toBeDefined(); - expect(plugin.constructor.name).toEqual('SauceLabsBrowserSessionGeneratorPlugin'); - }); - - it('can load the SeleniumGridSessionGeneratorPlugin', async () => { - let mgr: BrowserSessionGeneratorManager = new BrowserSessionGeneratorManager({ - plugins: ['selenium-grid-session-generator-plugin'] - }); - let plugin = await mgr.first(); - - expect(plugin).toBeDefined(); - expect(plugin.constructor.name).toEqual('SeleniumGridSessionGeneratorPlugin'); - }); -}); \ No newline at end of file diff --git a/packages/aft-ui-browsers/test/sessions/browserstack/browserstack-browser-session-generator-plugin-spec.ts b/packages/aft-ui-browsers/test/sessions/browserstack/browserstack-browser-session-generator-plugin-spec.ts deleted file mode 100644 index b56c5747..00000000 --- a/packages/aft-ui-browsers/test/sessions/browserstack/browserstack-browser-session-generator-plugin-spec.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { By, Capabilities } from 'selenium-webdriver'; -import { using, LogManager, rand, buildinfo } from "aft-core"; -import { UiPlatform } from "aft-ui"; -import { BrowserStackBrowserSessionGeneratorPlugin, BrowserStackBrowserSessionGeneratorPluginOptions, BrowserFacet, BrowserSession, BrowserFacetOptions, BrowserStackBrowserSessionOptions } from "../../../src"; - -describe('BrowserStackBrowserSessionGeneratorPlugin', () => { - it('can generate capabilities from the BrowserStackBrowserSessionGeneratorPluginOptions', async () => { - const platform: UiPlatform = new UiPlatform({ - os: 'os-' + rand.getString(10), - osVersion: 'osVersion-' + rand.getString(2, false, true), - browser: 'browser-' + rand.getString(15), - browserVersion: 'browserVersion-' + rand.getString(2, false, true), - deviceName: 'deviceName-' + rand.getString(22) - }); - const opts: BrowserStackBrowserSessionGeneratorPluginOptions = { - user: rand.getString(10, true, false, false, false), - key: rand.getString(12, true, true, false, false), - resolution: rand.getString(4, false, true) + 'x' + rand.getString(4, false, true), - local: true, - uiplatform: platform.toString(), - logMgr: new LogManager({logName: 'can generate capabilities from the BrowserStackBrowserSessionGeneratorPluginOptions'}) - }; - const session: BrowserStackBrowserSessionGeneratorPlugin = new BrowserStackBrowserSessionGeneratorPlugin(opts); - - const capabilities: Capabilities = await session.generateCapabilities(); - - expect(capabilities.get('browserstack.user')).toEqual(opts.user); - expect(capabilities.get('browserstack.key')).toEqual(opts.key); - expect(capabilities.get('os')).toEqual(platform.os); - expect(capabilities.get('os_version')).toEqual(platform.osVersion); - expect(capabilities.get('browserName')).toEqual(platform.browser); - expect(capabilities.get('browser_version')).toEqual(platform.browserVersion); - expect(capabilities.get('device')).toEqual(platform.deviceName); - expect(capabilities.get('realMobile')).toEqual('true'); - expect(capabilities.get('browserstack.local')).toEqual(true); - expect(capabilities.get('build')).toEqual(await buildinfo.get()); - expect(capabilities.get('name')).toEqual(opts.logMgr.logName); - }); - - it('can generate capabilities from the passed in BrowserStackBrowserSessionOptions', async () => { - const session: BrowserStackBrowserSessionGeneratorPlugin = new BrowserStackBrowserSessionGeneratorPlugin(); - const platform: UiPlatform = new UiPlatform({ - os: 'os-' + rand.getString(10), - osVersion: 'osVersion-' + rand.getString(2, false, true), - browser: 'browser-' + rand.getString(15), - browserVersion: 'browserVersion-' + rand.getString(2, false, true), - deviceName: 'deviceName-' + rand.getString(22) - }); - const opts: BrowserStackBrowserSessionOptions = { - user: rand.getString(10, true, false, false, false), - key: rand.getString(12, true, true, false, false), - resolution: rand.getString(4, false, true) + 'x' + rand.getString(4, false, true), - local: true, - uiplatform: platform.toString(), - logMgr: new LogManager({logName: 'can generate capabilities from the passed in BrowserStackBrowserSessionOptions'}) - }; - - const capabilities: Capabilities = await session.generateCapabilities(opts); - - expect(capabilities.get('browserstack.user')).toEqual(opts.user); - expect(capabilities.get('browserstack.key')).toEqual(opts.key); - expect(capabilities.get('os')).toEqual(platform.os); - expect(capabilities.get('os_version')).toEqual(platform.osVersion); - expect(capabilities.get('browserName')).toEqual(platform.browser); - expect(capabilities.get('browser_version')).toEqual(platform.browserVersion); - expect(capabilities.get('device')).toEqual(platform.deviceName); - expect(capabilities.get('realMobile')).toEqual('true'); - expect(capabilities.get('browserstack.local')).toEqual(true); - expect(capabilities.get('build')).toEqual(await buildinfo.get()); - expect(capabilities.get('name')).toEqual(opts.logMgr.logName); - }); - - /** - * WARNING: this test will attempt to create an actual session on BrowserStack - * it should only be used for local debugging. - * NOTE: you will need to set a value for the following via BrowserStackConfig - * or as environment variables: - * - browserstack_user - * - browserstack_accesskey - */ - xit('can create a session in BrowserStack', async () => { - let plugin: BrowserStackBrowserSessionGeneratorPlugin = new BrowserStackBrowserSessionGeneratorPlugin({ - user: '%browserstack_user%', - key: '%browserstack_key%', - uiplatform: 'windows_10_chrome' - }); - await using (await plugin.newUiSession(), async (session: BrowserSession) => { - let expectedUrl: string = 'https://the-internet.herokuapp.com/login'; - await session.goTo(expectedUrl); - - let actualUrl: string = await session.driver.getCurrentUrl(); - - expect(actualUrl).toEqual(expectedUrl); - - let facet: BrowserFacet = await session.getFacet(BrowserFacet, {locator: By.css('button.radius')}); - - expect(facet).toBeDefined(); - expect(await facet.getRoot().then(r => r.getText())).toEqual('Login'); - }); - }, 300000); -}); \ No newline at end of file diff --git a/packages/aft-ui-browsers/test/sessions/sauce-labs/sauce-labs-browser-session-generator-plugin-spec.ts b/packages/aft-ui-browsers/test/sessions/sauce-labs/sauce-labs-browser-session-generator-plugin-spec.ts deleted file mode 100644 index 993b7651..00000000 --- a/packages/aft-ui-browsers/test/sessions/sauce-labs/sauce-labs-browser-session-generator-plugin-spec.ts +++ /dev/null @@ -1,103 +0,0 @@ -import { By, Capabilities } from 'selenium-webdriver'; -import { using, LogManager, rand, buildinfo } from "aft-core"; -import { UiPlatform } from "aft-ui"; -import { BrowserFacet, BrowserFacetOptions, SauceLabsBrowserSessionGeneratorPlugin, SauceLabsBrowserSessionGeneratorPluginOptions, SauceLabsBrowserSessionOptions } from '../../../src'; - -describe('SauceLabsBrowserSessionGeneratorPlugin', () => { - it('can generate capabilities from the passed in SauceLabsBrowserSessionGeneratorPluginOptions', async () => { - const plt: UiPlatform = new UiPlatform({ - os: 'os-' + rand.getString(10), - osVersion: 'osVersion-' + rand.getString(2, false, true), - browser: 'browser-' + rand.getString(15), - browserVersion: 'browserVersion-' + rand.getString(2, false, true), - deviceName: 'deviceName-' + rand.getString(22) - }); - const opts: SauceLabsBrowserSessionGeneratorPluginOptions = { - username: rand.getString(10, true, false, false, false), - accessKey: rand.getString(12, true, true, false, false), - resolution: rand.getString(4, false, true) + 'x' + rand.getString(4, false, true), - tunnel: true, - tunnelIdentifier: rand.getString(11, true), - uiplatform: plt.toString(), - logMgr: new LogManager({logName:'can generate capabilities from the passed in SauceLabsBrowserSessionGeneratorPluginOptions'}) - } - const session: SauceLabsBrowserSessionGeneratorPlugin = new SauceLabsBrowserSessionGeneratorPlugin(opts); - - const caps: Capabilities = await session.generateCapabilities(); - - expect(caps.get('platformName')).toEqual(plt.os); - expect(caps.get('platformVersion')).toEqual(plt.osVersion); - expect(caps.get('browserName')).toEqual(plt.browser); - expect(caps.get('browserVersion')).toEqual(plt.browserVersion); - expect(caps.get('deviceName')).toEqual(plt.deviceName); - let sauceOpts: object = caps.get('sauce:options'); - expect(sauceOpts).toBeDefined(); - expect(sauceOpts['build']).toEqual(await buildinfo.get()); - expect(sauceOpts['name']).toEqual(opts.logMgr.logName); - expect(sauceOpts['screenResolution']).toEqual(opts.resolution); - expect(sauceOpts['tunnelIdentifier']).toEqual(opts.tunnelIdentifier); - }); - - it('can generate capabilities from the passed in SauceLabsBrowserSessionOptions', async () => { - let session: SauceLabsBrowserSessionGeneratorPlugin = new SauceLabsBrowserSessionGeneratorPlugin(); - const plt: UiPlatform = new UiPlatform({ - os: 'os-' + rand.getString(10), - osVersion: 'osVersion-' + rand.getString(2, false, true), - browser: 'browser-' + rand.getString(15), - browserVersion: 'browserVersion-' + rand.getString(2, false, true), - deviceName: 'deviceName-' + rand.getString(22) - }); - const opts: SauceLabsBrowserSessionOptions = { - username: rand.getString(10, true, false, false, false), - accessKey: rand.getString(12, true, true, false, false), - resolution: rand.getString(4, false, true) + 'x' + rand.getString(4, false, true), - tunnel: true, - tunnelIdentifier: rand.getString(11, true), - uiplatform: plt.toString(), - logMgr: new LogManager({logName:'can generate capabilities from the passed in SauceLabsBrowserSessionOptions'}) - }; - - const caps: Capabilities = await session.generateCapabilities(opts); - - expect(caps.get('platformName')).toEqual(plt.os); - expect(caps.get('platformVersion')).toEqual(plt.osVersion); - expect(caps.get('browserName')).toEqual(plt.browser); - expect(caps.get('browserVersion')).toEqual(plt.browserVersion); - expect(caps.get('deviceName')).toEqual(plt.deviceName); - let sauceOpts: object = caps.get('sauce:options'); - expect(sauceOpts).toBeDefined(); - expect(sauceOpts['build']).toEqual(await buildinfo.get()); - expect(sauceOpts['name']).toEqual(opts.logMgr.logName); - expect(sauceOpts['screenResolution']).toEqual(opts.resolution); - expect(sauceOpts['tunnelIdentifier']).toEqual(opts.tunnelIdentifier); - }); - - /** - * WARNING: this test will attempt to create an actual session on Sauce Labs - * it should only be used for local debugging. - * NOTE: you will need to set a value for the following via SauceLabsConfig - * or as environment variables: - * - sauce_username - * - sauce_access_key - */ - xit('can create a session in Sauce Labs', async () => { - let plugin: SauceLabsBrowserSessionGeneratorPlugin = new SauceLabsBrowserSessionGeneratorPlugin({ - uiplatform: 'windows_10_chrome', - username: '%saucelabs_username%', - accessKey: '%saucelabs_accesskey%', - }); - await using (await plugin.newUiSession(), async (session) => { - let expectedUrl: string = 'https://the-internet.herokuapp.com/login'; - await session.goTo(expectedUrl); - - let actualUrl: string = await session.driver.getCurrentUrl(); - - expect(actualUrl).toEqual(expectedUrl); - - let facet: BrowserFacet = await session.getFacet(BrowserFacet, {locator: By.css('button.radius')}); - - expect(facet).toBeDefined(); - expect(await facet.getRoot().then(r => r.getText())).toEqual('Login'); - }); - }, 300000); -}); \ No newline at end of file diff --git a/packages/aft-ui-browsers/test/sessions/selenium-grid/selenium-grid-session-generator-plugin-spec.ts b/packages/aft-ui-browsers/test/sessions/selenium-grid/selenium-grid-session-generator-plugin-spec.ts deleted file mode 100644 index 1a8844a4..00000000 --- a/packages/aft-ui-browsers/test/sessions/selenium-grid/selenium-grid-session-generator-plugin-spec.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { rand } from "aft-core"; -import { UiPlatform } from "aft-ui"; -import { BrowserFacet, BrowserFacetOptions, BrowserSession, SeleniumGridSessionGeneratorPlugin } from "../../../src"; -import { By, Capabilities } from "selenium-webdriver"; - -describe('SeleniumGridSessionGeneratorPlugin', () => { - it('can generate capabilities from the passed in options', async () => { - const platform: UiPlatform = new UiPlatform({ - os: 'os-' + rand.getString(10), - osVersion: 'osVersion-' + rand.getString(2, false, true), - browser: 'browser-' + rand.getString(15), - browserVersion: 'browserVersion-' + rand.getString(2, false, true) - }); - const plugin: SeleniumGridSessionGeneratorPlugin = new SeleniumGridSessionGeneratorPlugin({ - uiplatform: platform.toString() - }); - const capabilities: Capabilities = await plugin.generateCapabilities(); - - expect(capabilities.get('platform')).toEqual(`${platform.os} ${platform.osVersion}`); - expect(capabilities.get('browserName')).toEqual(`${platform.browser} ${platform.browserVersion}`); - }); - - /** - * WARNING: this test will attempt to create an actual session on your own Selenium Grid - * it should only be used for local debugging. - * NOTE: you will need to set a value for the following via SeleniumGridConfig - * or as environment variables: - * - selenium_grid_url - */ - xit('can create a session on Selenium Grid', async () => { - let platform: string = 'windows_10_chrome'; - let plugin: SeleniumGridSessionGeneratorPlugin = new SeleniumGridSessionGeneratorPlugin({uiplatform: platform}); - let session = await plugin.newUiSession(); - - let expectedUrl: string = 'https://the-internet.herokuapp.com/login'; - await session.goTo(expectedUrl); - - let actualUrl: string = await session.driver.getCurrentUrl(); - - expect(actualUrl).toEqual(expectedUrl); - - let facet: BrowserFacet = await session.getFacet(BrowserFacet, {locator: By.css('button.radius')}); - - expect(facet).toBeDefined(); - expect(await facet.getRoot().then(r => r.getText())).toEqual('Login'); - }, 300000); -}); \ No newline at end of file diff --git a/packages/aft-ui-mobile-apps/README.md b/packages/aft-ui-mobile-apps/README.md deleted file mode 100644 index 05d8a1e8..00000000 --- a/packages/aft-ui-mobile-apps/README.md +++ /dev/null @@ -1,119 +0,0 @@ -# AFT-UI-Mobile-Apps -Automated Functional Testing (AFT) package providing Appium-based `MobileAppFacet extends UiFacet` Plugins and BrowserStack, Sauce Labs and Appium Grid `UiSession` Plugins extending the `aft-ui` package. This enables testing using BrowserStack's, Sauce Labs's or a Local Selenium Grid for any Mobile Device application tests. - -## Installation -`> npm i aft-ui-mobile-apps` - -## Creating your own Facets for use in testing -Take the following as an example of how one could interact with the following Android App - -### Step 1: create the View Facet - -```typescript -export class WikipediaView extends MobileAppFacet { - readonly locator: string = '//*'; - private _searchButton = async (): Promise> => await this.getElement({locator: "~Search Wikipedia", maxWaitMs: 10000}); - private _searchInput = async (): Promise> => await this.session.driver.$('android=new UiSelector().resourceId("org.wikipedia.alpha:id/search_src_text")'); - private _searchResults = async (): Promise => await this.getElements({locator: "android.widget.TextView", maxWaitMs: 10000}); - async searchFor(term: string): Promise { - await this._searchButton().then(b => b.click()); - await this.sendTextToSearch(term); - return await this.getResults(); - } - async sendTextToSearch(text: string): Promise { - await this._searchInput().then(i => i.addValue(text)); - } - async getResults(): Promise { - let resultsText: string[] = []; - var searchResults: ElementArray = await this._searchResults(); - for (var i=0; i = searchResults[i]; - let txt: string = await res.getText().catch(err => err); - resultsText.push(txt); - } - return resultsText; - } -} -``` -### Step 2: use them to interact with the mobile application - -```typescript -await verifyWithMobileApp(async (mav: MobileAppVerifier) => { - await mav.logMgr.step('get the WikipediaView Facet from the Session...'); - let view: WikipediaView = await mav.session.getFacet(WikipediaView); - await mav.logMgr.step('enter a search term...'); - await view.searchFor('pizza'); - await mav.logMgr.step('get the results and ensure they contain the search term...'); - let results: string[] = await view.getResults(); - let contains: boolean = false; - for (var i=0; i; - -export type MobileAppFacetOptions = Merge; - parent?: MobileAppFacet; -}>; - -export class MobileAppFacet extends UiFacet { - override get locator(): string { - return super.locator as string; - } - override get session(): MobileAppSession { - return super.session as MobileAppSession; - } - override get parent(): MobileAppFacet { - return super.parent as MobileAppFacet; - } - - override async getElements(options: MobileAppElementOptions): Promise { - const maxWait = options.maxWaitMs ?? this.maxWaitMs; - const delay = options.retryDelayMs ?? this.retryDelayMs; - const delayType = options.retryDelayBackOff ?? this.retryDelayBackOff; - return retry(() => { - return this.getRoot().then(r => r.$$(options.locator)); - }).withStartDelayBetweenAttempts(delay).withBackOff(delayType) - .withMaxDuration(maxWait); - } - - override async getElement(options: MobileAppElementOptions): Promise> { - const maxWait = options.maxWaitMs ?? this.maxWaitMs; - const delay = options.retryDelayMs ?? this.retryDelayMs; - const delayType = options.retryDelayBackOff ?? this.retryDelayBackOff; - return retry(() => { - return this.getRoot() - .then(r => r.$(options.locator)); - }).withStartDelayBetweenAttempts(delay).withBackOff(delayType) - .withMaxDuration(maxWait); - } - - override async getFacet>(facetType: Class, options?: MobileAppFacetOptions): Promise { - options = options || {} as MobileAppFacetOptions; - options.parent = options.parent || this; - options.session = options.session || this.session; - options.logMgr = options.logMgr || this.logMgr; - options.maxWaitMs = options.maxWaitMs ?? this.maxWaitMs; - options.retryDelayMs = options.retryDelayMs ?? this.retryDelayMs; - options.retryDelayBackOff = options.retryDelayBackOff ?? this.retryDelayBackOff; - let facet: T = new facetType(options); - return facet; - } - - override async getRoot(): Promise> { - return retry(() => { - if (this.parent) { - return this.parent.getRoot() - .then(r => r.$$(this.locator)) - .then(els => els[this.index]); - } else { - return this.session.driver.$$(this.locator) - .then(els => els[this.index]); - } - }).withStartDelayBetweenAttempts(this.retryDelayMs) - .withBackOff(this.retryDelayBackOff) - .withMaxDuration(this.maxWaitMs); - } -} \ No newline at end of file diff --git a/packages/aft-ui-mobile-apps/src/helpers/mobile-app-verifier.ts b/packages/aft-ui-mobile-apps/src/helpers/mobile-app-verifier.ts deleted file mode 100644 index f0cdd0f9..00000000 --- a/packages/aft-ui-mobile-apps/src/helpers/mobile-app-verifier.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { Func, using, Verifier } from "aft-core"; -import { MobileAppSession, MobileAppSessionOptions } from "../sessions/mobile-app-session"; -import { mobileAppSessionGeneratorMgr, MobileAppSessionGeneratorManager } from "../sessions/mobile-app-session-generator-manager"; - -export class MobileAppVerifier extends Verifier { - protected override _assertion: Func; - protected _sessionMgr: MobileAppSessionGeneratorManager; - protected _session: MobileAppSession; - protected _sessionOptions: MobileAppSessionOptions; - - /** - * a `MobileAppSessionGeneratorManager` instance used to generate new - * Mobile App sessions - */ - get sessionGeneratorManager(): MobileAppSessionGeneratorManager { - if (!this._sessionMgr) { - this._sessionMgr = mobileAppSessionGeneratorMgr; - } - return this._sessionMgr; - } - - /** - * after a new `MobileAppSession` is created, this holds the instance - * so it can be referenced from within the executing `assertion` - */ - get session(): MobileAppSession { - return this._session; - } - - /** - * allows for specifying custom `MobileAppSessionOptions` to be used when creating - * a new `MobileAppSession` prior to executing the `assertion`. - * NOTE: if not set then only the `MobileAppVerifier.logMgr` will be included in - * the `MobileAppSessionOptions` - * @param options the `MobileAppSessionOptions` to be used to create a new `MobileAppSession` - * @returns this `MobileAppVerifier` instance - */ - withMobileAppSessionOptions(options: MobileAppSessionOptions): this { - this._sessionOptions = options; - return this; - } - - /** - * allows for passing in an instance of `MobileAppSessionGeneratorManager` to be - * used in locating a `MobileAppSessionGeneratorPlugin` instance to use in - * generating a `MobileAppSession`. - * NOTE: if not set then the global const `mobileAppSessionGeneratorMgr` - * will be used - * @param sessionMgr a `MobileAppSessionGeneratorManager` to be used instead of the Global instance - * @returns this `MobileAppVerifier` instance - */ - withMobileAppSessionGeneratorManager(sessionMgr: MobileAppSessionGeneratorManager): this { - this._sessionMgr = sessionMgr; - return this; - } - - /** - * the `MobileAppSessionOptions` that will be used when creating a - * new `MobileAppSession` - */ - get sessionOptions(): MobileAppSessionOptions { - if (!this._sessionOptions) { - this._sessionOptions = {logMgr: this.logMgr}; - } - return this._sessionOptions; - } - - protected override async _resolveAssertion(): Promise { - let opts: MobileAppSessionOptions = this.sessionOptions; - opts.logMgr = opts.logMgr || this.logMgr; - await using(await this.sessionGeneratorManager.newUiSession(opts), async (session) => { - this._session = session; - await super._resolveAssertion(); - }); - } -} - -/** - * creates a new `MobileAppVerifier` instace to be used for executing some Functional - * Test Assertion. - * ex: - * ``` - * await verifyWithMobileApp(async (v: MobileAppVerifier) => { - * let facet: MyFacet = await v.session.getFacet(MyFacet); - * return await facet.returnExpectedValue(); - * }).withDescription('example usage for MobileAppVerifier') - * .and.withTestId('C1234') - * .returns('expected value'); - * ``` - * @param assertion the `Func` function to be executed by this `MobileAppVerifier` - * @returns a new `MobileAppVerifier` instance - */ -export const verifyWithMobileApp = (assertion: Func): MobileAppVerifier => { - let v: MobileAppVerifier = new MobileAppVerifier(); - v.verify(assertion); - return v; -} \ No newline at end of file diff --git a/packages/aft-ui-mobile-apps/src/index.ts b/packages/aft-ui-mobile-apps/src/index.ts deleted file mode 100644 index 04b1fadd..00000000 --- a/packages/aft-ui-mobile-apps/src/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* facets */ -export * from './facets/mobile-app-facet'; -/* helpers */ -export * from './helpers/mobile-app-verifier'; -/* sessions */ -export * from './sessions/mobile-app-session-generator-plugin'; -export * from './sessions/mobile-app-session'; -export {mobileAppSessionGeneratorMgr} from './sessions/mobile-app-session-generator-manager'; -/* sessions - BrowserStack */ -export * from './sessions/browserstack/browserstack-mobile-app-session-generator-plugin'; -export * from './sessions/browserstack/browserstack-mobile-app-session'; -export * from './sessions/browserstack/app-automate/app-automate-api-custom-types'; -export * from './sessions/browserstack/app-automate/browserstack-app-automate-api'; -/* sessions - Saucelabs */ -export * from './sessions/sauce-labs/sauce-labs-mobile-app-session-generator-plugin'; -export * from './sessions/sauce-labs/sauce-labs-mobile-app-session'; -/* sessions - Appium Grid */ -export * from './sessions/appium-grid/appium-grid-session-generator-plugin'; \ No newline at end of file diff --git a/packages/aft-ui-mobile-apps/src/sessions/appium-grid/appium-grid-session-generator-plugin.ts b/packages/aft-ui-mobile-apps/src/sessions/appium-grid/appium-grid-session-generator-plugin.ts deleted file mode 100644 index c014f082..00000000 --- a/packages/aft-ui-mobile-apps/src/sessions/appium-grid/appium-grid-session-generator-plugin.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { MobileAppSessionGeneratorPlugin, MobileAppSessionGeneratorPluginOptions } from "../mobile-app-session-generator-plugin"; -import { UiPlatform } from "aft-ui"; -import { MobileAppSession, MobileAppSessionOptions } from "../mobile-app-session"; -import { RemoteOptions } from "webdriverio"; - -export type AppiumGridSessionGeneratorPluginOptions = MobileAppSessionGeneratorPluginOptions; - -export class AppiumGridSessionGeneratorPlugin extends MobileAppSessionGeneratorPlugin { - override async newUiSession(options?: MobileAppSessionOptions): Promise> { - const remopts = await this.generateRemoteOptions(options); - options.driver = options.driver || await this.createDriver(remopts); - return new MobileAppSession(options); - } - override async generateRemoteOptions(options?: MobileAppSessionOptions): Promise { - options = options || {}; - options.logMgr = options.logMgr || this.logMgr; - options.uiplatform = options.uiplatform || this.uiplatform.toString(); - options.app = options.app || this.app; - - let remOpts: RemoteOptions = await super.generateRemoteOptions(options); - remOpts.capabilities = {}; - let platform: UiPlatform = UiPlatform.parse(options.uiplatform); - let osVersion = ''; - if (platform.osVersion) { - osVersion = ' ' + platform.osVersion; - } - remOpts.capabilities['platform'] = `${platform.os}${osVersion}`; - return remOpts; - } - override async sendCommand(command: string, data?: any): Promise { - return Promise.reject(`command '${command}' not supported`); - } -} \ No newline at end of file diff --git a/packages/aft-ui-mobile-apps/src/sessions/browserstack/app-automate/app-automate-api-custom-types.ts b/packages/aft-ui-mobile-apps/src/sessions/browserstack/app-automate/app-automate-api-custom-types.ts deleted file mode 100644 index 05a1cd4c..00000000 --- a/packages/aft-ui-mobile-apps/src/sessions/browserstack/app-automate/app-automate-api-custom-types.ts +++ /dev/null @@ -1,30 +0,0 @@ -export type RecentGroupAppsResponse = { - apps: BrowserStackMobileApp[]; -}; - -export type BrowserStackMobileApp = { - app_name?: string; - app_version?: string; - app_url?: string; - app_id?: string; - uploaded_at?: string; - custom_id?: string; - shareable_id?: string; -}; - -export type SetSessionStatusRequest = { - sessionId: string; - status: 'passed' | 'failed'; - message?: string; -}; - -export type UploadRequest = { - file?: string; - custom_id?: string; -}; - -export type UploadResponse = { - app_url: string; - custom_id: string; - shareable_id: string; -}; \ No newline at end of file diff --git a/packages/aft-ui-mobile-apps/src/sessions/browserstack/app-automate/browserstack-app-automate-api.ts b/packages/aft-ui-mobile-apps/src/sessions/browserstack/app-automate/browserstack-app-automate-api.ts deleted file mode 100644 index ad03aa84..00000000 --- a/packages/aft-ui-mobile-apps/src/sessions/browserstack/app-automate/browserstack-app-automate-api.ts +++ /dev/null @@ -1,119 +0,0 @@ -import { convert, IHasOptions, LogManager, optmgr } from "aft-core"; -import { HttpResponse, httpService, httpData } from "aft-web-services"; -import * as fs from "fs"; -import * as FormData from "form-data"; -import { BrowserStackMobileApp, RecentGroupAppsResponse, SetSessionStatusRequest, UploadRequest, UploadResponse } from "./app-automate-api-custom-types"; - -export type BrowserStackAppAutomateApiOptions = { - apiUrl?: string; - user?: string; - key?: string; - logMgr?: LogManager; -}; - -export class BrowserStackAppAutomateApi implements IHasOptions { - private _options: BrowserStackAppAutomateApiOptions; - private _apiUrl: string; - private _user: string; - private _key: string; - private _logMgr: LogManager; - - constructor(options?: BrowserStackAppAutomateApiOptions) { - options = options || {} as BrowserStackAppAutomateApiOptions; - this._options = optmgr.process(options); - } - - option(key: K, defaultVal?: V): V { - const response: V = this._options[key] as V; - return (response === undefined) ? defaultVal : response; - } - - get apiUrl(): string { - if (!this._apiUrl) { - this._apiUrl = this.option('apiUrl', 'https://api.browserstack.com/app-automate/'); - } - return this._apiUrl; - } - - get user(): string { - if (!this._user) { - this._user = this.option('user'); - } - return this._user; - } - - get key(): string { - if (!this._key) { - this._key = this.option('key'); - } - return this._key; - } - - get logMgr(): LogManager { - if (!this._logMgr) { - this._logMgr = this.option('logMgr') || new LogManager({logName: this.constructor.name}); - } - return this._logMgr; - } - - async uploadApp(data: UploadRequest): Promise { - const url = this.apiUrl; - if(!fs.existsSync(data.file)) { - return Promise.reject(`file could not be found at: ${data.file}`); - } - let formData: FormData = new FormData(); - formData.append('file', fs.createReadStream(data.file)); - if (data.custom_id) { - formData.append('custom_id', data.custom_id); - } - let bsResp: HttpResponse = await httpService.performRequest({ - url: `${url}upload`, - method: 'POST', - headers: {"Authorization": await this._getAuthHeader()}, - multipart: true, - postData: formData, - logMgr: this._logMgr - }); - if (bsResp && bsResp.statusCode == 200) { - return httpData.as(bsResp); - } - return Promise.reject(`unable to upload file '${data.file} to BrowserStack due to: ${bsResp?.data}`); - } - - async getApps(): Promise { - const url = this.apiUrl; - let bsResp: HttpResponse = await httpService.performRequest({ - url: `${url}recent_group_apps`, - method: 'GET', - headers: {"Authorization": await this._getAuthHeader()}, - logMgr: this._logMgr - }); - if (bsResp && bsResp.statusCode == 200) { - return {apps: httpData.as(bsResp)}; - } - return Promise.reject(`unable to get list of mobile apps from BrowserStack due to: ${bsResp?.data}`); - } - - async setSessionStatus(data: SetSessionStatusRequest): Promise { - const url = this.apiUrl; - let urlPath: string = `sessions/${data.sessionId}.json`; - let pdata: {} = { - status: data.status, - reason: data.message - }; - var resp: HttpResponse = await httpService.performRequest({ - method: 'PUT', - headers: {"Authorization": await this._getAuthHeader()}, - url: `${url}${urlPath}`, - postData: JSON.stringify(pdata), - logMgr: this._logMgr - }); - if (resp.statusCode != 200) { - return Promise.reject(resp.data); - } - } - - private async _getAuthHeader(): Promise { - return `Basic ${convert.toBase64Encoded(`${this.user}:${this.key}`)}`; - } -} \ No newline at end of file diff --git a/packages/aft-ui-mobile-apps/src/sessions/browserstack/browserstack-mobile-app-session-generator-plugin.ts b/packages/aft-ui-mobile-apps/src/sessions/browserstack/browserstack-mobile-app-session-generator-plugin.ts deleted file mode 100644 index 495438d4..00000000 --- a/packages/aft-ui-mobile-apps/src/sessions/browserstack/browserstack-mobile-app-session-generator-plugin.ts +++ /dev/null @@ -1,137 +0,0 @@ -import { UiPlatform } from "aft-ui"; -import { MobileAppSessionGeneratorPlugin, MobileAppSessionGeneratorPluginOptions } from "../mobile-app-session-generator-plugin"; -import { MobileAppSessionOptions } from "../mobile-app-session"; -import { RemoteOptions } from "webdriverio"; -import { BrowserStackAppAutomateApi } from "./app-automate/browserstack-app-automate-api"; -import { BrowserStackMobileAppSession, BrowserStackMobileAppSessionOptions } from "./browserstack-mobile-app-session"; -import { UploadRequest } from "./app-automate/app-automate-api-custom-types"; -import { buildinfo, Merge } from "aft-core"; - -export type BrowserStackMobileAppSessionGeneratorPluginOptions = Merge; - -export class BrowserStackMobileAppSessionGeneratorPlugin extends MobileAppSessionGeneratorPlugin { - private _api: BrowserStackAppAutomateApi; - private _apiUrl: string; - private _user: string; - private _key: string; - private _debug: boolean; - private _local: boolean; - private _localIdentifier: string; - - get api(): BrowserStackAppAutomateApi { - if (!this._api) { - this._api = this.option('api') || new BrowserStackAppAutomateApi({ - apiUrl: this.apiUrl, - user: this.user, - key: this.key, - logMgr: this.logMgr - }); - } - return this._api; - } - - get apiUrl(): string { - if (!this._apiUrl) { - this._apiUrl = this.option('apiUrl'); - } - return this._apiUrl; - } - - get user(): string { - if (!this._user) { - this._user = this.option('user'); - } - return this._user; - } - - get key(): string { - if (!this._key) { - this._key = this.option('key'); - } - return this._key; - } - - get debug(): boolean { - if (this._debug === undefined) { - this._debug = this.option('debug', false); - } - return this._debug; - } - - get local(): boolean { - if (this._local === undefined) { - this._local = this.option('local', false); - } - return this._local; - } - - get localIdentifier(): string { - if (!this._localIdentifier) { - this._localIdentifier = this.option('localIdentifier'); - } - return this._localIdentifier; - } - - override async newUiSession(options?: MobileAppSessionOptions): Promise { - const remopts = await this.generateRemoteOptions(options); - options.driver = options.driver || await this.createDriver(remopts); - return new BrowserStackMobileAppSession(options); - } - - override async generateRemoteOptions(options?: BrowserStackMobileAppSessionOptions): Promise { - options = options || {}; - options.logMgr = options.logMgr || this.logMgr; - options.uiplatform = options.uiplatform || this.uiplatform.toString(); - options.app = options.app || this.app; - options.user = options.user || this.user; - options.key = options.key || this.key; - options.local = options.local || this.local; - options.localIdentifier = options.localIdentifier || this.localIdentifier; - options.debug = options.debug || this.debug; - - const remOpts: RemoteOptions = await super.generateRemoteOptions(options); - remOpts.user = remOpts.user || options.user; - remOpts.key = remOpts.key || options.key; - remOpts.capabilities = remOpts.capabilities || {}; - const platform: UiPlatform = (options?.uiplatform) ? UiPlatform.parse(options.uiplatform) : this.uiplatform; - remOpts.capabilities['os'] = remOpts.capabilities['os'] || platform.os; - remOpts.capabilities['os_version'] = remOpts.capabilities['os_version'] || platform.osVersion; - remOpts.capabilities['device'] = remOpts.capabilities['device'] || platform.deviceName; - remOpts.capabilities['realMobile'] = true; - remOpts.capabilities['browserstack.debug'] = remOpts.capabilities['browserstack.debug'] || options.debug; - remOpts.capabilities['build'] = remOpts.capabilities['build'] || await buildinfo.buildName(); - remOpts.capabilities['name'] = remOpts.capabilities['name'] || options.logMgr?.logName; - remOpts.capabilities['browserstack.local'] = remOpts.capabilities['browserstack.local'] || options.local; - remOpts.capabilities['browserstack.localIdentifier'] = remOpts.capabilities['browserstack.localIdentifier'] || options.localIdentifier; - return remOpts; - } - - override async sendCommand(command: string, data?: any): Promise { - let resp: any; - try { - switch (command) { - case 'upload': - resp = await this.api.uploadApp(data as UploadRequest); - break; - case 'getApps': - resp = await this.api.getApps(); - break; - default: - resp = { error: `unknown command of '${command}' sent to BrowserStackMobileAppSessionGeneratorPlugin.sendCommand` }; - break; - } - } catch (e) { - return Promise.reject(e); - } - return resp; - } -} \ No newline at end of file diff --git a/packages/aft-ui-mobile-apps/src/sessions/browserstack/browserstack-mobile-app-session.ts b/packages/aft-ui-mobile-apps/src/sessions/browserstack/browserstack-mobile-app-session.ts deleted file mode 100644 index 19f2a829..00000000 --- a/packages/aft-ui-mobile-apps/src/sessions/browserstack/browserstack-mobile-app-session.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { Merge } from "aft-core"; -import { MobileAppSession, MobileAppSessionOptions } from "../mobile-app-session"; - -export type BrowserStackMobileAppSessionOptions = Merge; - -export class BrowserStackMobileAppSession extends MobileAppSession { - private _user: string; - private _key: string; - private _debug: boolean; - private _local: boolean; - private _localIdentifier: string; - - get user(): string { - if (!this._user) { - this._user = this.option('user'); - } - return this._user; - } - - get key(): string { - if (!this._key) { - this._key = this.option('key'); - } - return this._key; - } - - get debug(): boolean { - if (this._debug === undefined) { - this._debug = this.option('debug', false); - } - return this._debug; - } - - get local(): boolean { - if (this._local === undefined) { - this._local = this.option('local', false); - } - return this._local; - } - - get localIdentifier(): string { - if (!this._localIdentifier) { - this._localIdentifier = this.option('localIdentifier'); - } - return this._localIdentifier; - } - - override async dispose(error?: any): Promise { - try { - let setStatus: {} = { - "action": "setSessionStatus", - "arguments": { - "status": (error) ? 'failed' : 'passed', - "reason": error || 'successful test' - } - }; - await this.driver?.execute(`browserstack_executor: ${JSON.stringify(setStatus)}`); - } catch (e) { - await this.logMgr.warn(e); - } - - await super.dispose(error); - } -} \ No newline at end of file diff --git a/packages/aft-ui-mobile-apps/src/sessions/mobile-app-session-generator-manager.ts b/packages/aft-ui-mobile-apps/src/sessions/mobile-app-session-generator-manager.ts deleted file mode 100644 index 6a832655..00000000 --- a/packages/aft-ui-mobile-apps/src/sessions/mobile-app-session-generator-manager.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { UiSessionGeneratorManager, UiSessionGeneratorManagerOptions } from "aft-ui"; -import { MobileAppSessionGeneratorPlugin, MobileAppSessionGeneratorPluginOptions } from "./mobile-app-session-generator-plugin"; -import { MobileAppSession, MobileAppSessionOptions } from "./mobile-app-session"; -import { Merge } from "aft-core"; - -export type MobileAppSessionGeneratorManagerOptions = Merge; - -export class MobileAppSessionGeneratorManager extends UiSessionGeneratorManager, MobileAppSessionGeneratorManagerOptions> { - async newUiSession(options?: MobileAppSessionOptions): Promise> { - return await this.first().then(f => f.newUiSession(options) - .catch(async (err) => { - const l = await this.logMgr(); - await l.warn(`error in call to '${f.constructor.name}.newSession(...)' due to: ${err}`); - return null; - })) - .catch(async (err) => { - const l = await this.logMgr(); - await l.warn(`error in call to 'plugin.newSession(...)' due to: ${err}`); - return null; - }); - } - async sendCommand(command: string, data?: any): Promise { - return await this.first().then(f => f.sendCommand(command, data) - .catch(async (err) => { - const l = await this.logMgr(); - await l.warn(`error in call to '${f.constructor.name}.sendCommand(${command}, ${data})' due to: ${err}`); - return null; - })) - .catch(async (err) => { - const l = await this.logMgr(); - await l.warn(`error in call to 'plugin.sendCommand(${command}, ${data})' due to: ${err}`); - return null; - }); - } -} - -export const mobileAppSessionGeneratorMgr = new MobileAppSessionGeneratorManager(); \ No newline at end of file diff --git a/packages/aft-ui-mobile-apps/src/sessions/mobile-app-session-generator-plugin.ts b/packages/aft-ui-mobile-apps/src/sessions/mobile-app-session-generator-plugin.ts deleted file mode 100644 index c1826674..00000000 --- a/packages/aft-ui-mobile-apps/src/sessions/mobile-app-session-generator-plugin.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { UiSessionGeneratorPlugin, UiSessionGeneratorPluginOptions } from "aft-ui"; -import { MobileAppSession, MobileAppSessionOptions } from "./mobile-app-session"; -import { Browser, remote, RemoteOptions } from "webdriverio"; -import { Merge } from "aft-core"; - -export type MobileAppSessionGeneratorPluginOptions = Merge; - -export abstract class MobileAppSessionGeneratorPlugin extends UiSessionGeneratorPlugin { - private _app: string; - - async generateRemoteOptions(options?: MobileAppSessionOptions): Promise { - options = options || {}; - let remOpts: RemoteOptions = this.option('remoteOptions', {}) as RemoteOptions; - if (options.remoteOptions) { - remOpts = {...remOpts, ...options.remoteOptions} - } - let app: string = options?.app || this.app; - if (app) { - remOpts.capabilities = remOpts.capabilities || {}; - remOpts.capabilities['app'] = app; - } - return remOpts; - } - - get app(): string { - if (!this._app) { - this._app = this.option('app'); - } - return this._app; - } - - abstract override newUiSession(options?: MobileAppSessionOptions): Promise>; - - async createDriver(remoteOptions: RemoteOptions): Promise> { - if (remoteOptions) { - try { - let driver: Browser<'async'> = await remote(remoteOptions); - return driver; - } catch (e) { - return Promise.reject(e); - } - } - return null; - } - - abstract sendCommand(command: string, data?: any): Promise; -} \ No newline at end of file diff --git a/packages/aft-ui-mobile-apps/src/sessions/mobile-app-session.ts b/packages/aft-ui-mobile-apps/src/sessions/mobile-app-session.ts deleted file mode 100644 index 1ef7aa1f..00000000 --- a/packages/aft-ui-mobile-apps/src/sessions/mobile-app-session.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { Class, Merge } from "aft-core"; -import { UiFacet, UiSession, UiSessionOptions, UiFacetOptions } from "aft-ui"; -import { Browser, RemoteOptions } from "webdriverio"; - -export type MobileAppSessionOptions = Merge; - /** - * a path to the mobile application (.apk or .ipa). - * NOTE: if left blank then you must specify the value in - * your `remoteOptions.capabilities['app']` - */ - app?: string; - /** - * an object consisting of string key value pairs used to specify - * any remote device options to be passed to the Appium grid when - * creating a session - */ - remoteOptions?: RemoteOptions; -}>; - -export class MobileAppSession extends UiSession { - private _driver: Browser<'async'>; - - get driver(): Browser<'async'> { - if (!this._driver) { - this._driver = this.option('driver'); - } - return this._driver; - } - - async getFacet, To extends UiFacetOptions>(facetType: Class, options?: To): Promise { - options = options || {} as To; - options.session = options.session || this; - options.logMgr = options.logMgr || this.logMgr; - let facet: T = new facetType(options); - return facet; - } - - async dispose(error?: any): Promise { - if (error) { - await this.logMgr.warn(`Error: ${this.constructor.name} - ${error}`); - } - await this.logMgr.trace(`shutting down ${this.constructor.name}`); - await this.driver?.deleteSession(); - } -} \ No newline at end of file diff --git a/packages/aft-ui-mobile-apps/src/sessions/sauce-labs/sauce-labs-mobile-app-session-generator-plugin.ts b/packages/aft-ui-mobile-apps/src/sessions/sauce-labs/sauce-labs-mobile-app-session-generator-plugin.ts deleted file mode 100644 index 06edefc9..00000000 --- a/packages/aft-ui-mobile-apps/src/sessions/sauce-labs/sauce-labs-mobile-app-session-generator-plugin.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { UiPlatform } from "aft-ui"; -import { MobileAppSessionGeneratorPlugin, MobileAppSessionGeneratorPluginOptions } from "../mobile-app-session-generator-plugin"; -import { MobileAppSessionOptions } from "../mobile-app-session"; -import { RemoteOptions } from "webdriverio"; -import { SauceLabsMobileAppSession, SauceLabsMobileAppSessionOptions } from "./sauce-labs-mobile-app-session"; -import { buildinfo, Merge } from "aft-core"; - -export type SauceLabsMobileAppSessionGeneratorPluginOptions = Merge; - -export class SauceLabsMobileAppSessionGeneratorPlugin extends MobileAppSessionGeneratorPlugin { - private _username: string; - private _accessKey: string; - private _tunnel: boolean; - private _tunnelIdentifier: string; - private _apiUrl: string; - - get username(): string { - if (!this._username) { - this._username = this.option('username'); - } - return this._username; - } - - get accessKey(): string { - if (!this._accessKey) { - this._accessKey = this.option('accessKey'); - } - return this._accessKey; - } - - get tunnel(): boolean { - if (this._tunnel === undefined) { - this._tunnel = this.option('tunnel', false); - } - return this._tunnel; - } - - get tunnelIdentifier(): string { - if (!this._tunnelIdentifier) { - this._tunnelIdentifier = this.option('tunnelIdentifier'); - } - return this._tunnelIdentifier; - } - - get apiUrl(): string { - if (!this._apiUrl) { - this._apiUrl = this.option('apiUrl', 'http://saucelabs.com/rest/v1/'); - } - return this._apiUrl; - } - - override async newUiSession(options?: MobileAppSessionOptions): Promise { - const remopts = await this.generateRemoteOptions(options); - options.driver = options.driver || await this.createDriver(remopts); - return new SauceLabsMobileAppSession(options); - } - - override async generateRemoteOptions(options?: SauceLabsMobileAppSessionOptions): Promise { - options = options || {}; - options.logMgr = options.logMgr || this.logMgr; - options.uiplatform = options.uiplatform || this.uiplatform.toString(); - options.app = options.app || this.app; - options.username = options.username || this.username; - options.accessKey = options.accessKey || this.accessKey; - options.tunnel = options.tunnel || this.tunnel; - options.tunnelIdentifier = options.tunnelIdentifier || this.tunnelIdentifier; - - let remOpts: RemoteOptions = await super.generateRemoteOptions(options); - remOpts.capabilities = remOpts.capabilities || {}; - const platform: UiPlatform = UiPlatform.parse(options.uiplatform); - remOpts.capabilities['platformName'] = remOpts.capabilities['platformName'] || platform.os; - remOpts.capabilities['platformVersion'] = remOpts.capabilities['platformVersion'] || platform.osVersion; - remOpts.capabilities['deviceName'] = remOpts.capabilities['deviceName'] || platform.deviceName; - remOpts.user = remOpts.user || options.username; - remOpts.key = remOpts.key || options.accessKey; - remOpts.capabilities['buildName'] = remOpts.capabilities['buildName'] || await buildinfo.get(); - remOpts.capabilities['name'] = remOpts.capabilities['name'] || options.logMgr?.logName; - remOpts.capabilities['tunnel'] = remOpts.capabilities['tunnel'] || options.tunnel; - remOpts.capabilities['tunnelIdentifier'] = remOpts.capabilities['tunnelIdentifier'] || options.tunnelIdentifier; - remOpts.capabilities['automationName'] = remOpts.capabilities['automationName'] || 'Appium'; - return remOpts; - } - - override async sendCommand(command: string, data?: any): Promise { - return Promise.reject(`command '${command}' not supported`); - } -} \ No newline at end of file diff --git a/packages/aft-ui-mobile-apps/src/sessions/sauce-labs/sauce-labs-mobile-app-session.ts b/packages/aft-ui-mobile-apps/src/sessions/sauce-labs/sauce-labs-mobile-app-session.ts deleted file mode 100644 index 74e3e8b3..00000000 --- a/packages/aft-ui-mobile-apps/src/sessions/sauce-labs/sauce-labs-mobile-app-session.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { Merge } from "aft-core"; -import { MobileAppSession, MobileAppSessionOptions } from "../mobile-app-session"; - -export type SauceLabsMobileAppSessionOptions = Merge; - -export class SauceLabsMobileAppSession extends MobileAppSession { - private _username: string; - private _accessKey: string; - private _tunnel: boolean; - private _tunnelIdentifier: string; - - get username(): string { - if (!this._username) { - this._username = this.option('username'); - } - return this._username; - } - - get accessKey(): string { - if (!this._accessKey) { - this._accessKey = this.option('accessKey'); - } - return this._accessKey; - } - - get tunnel(): boolean { - if (this._tunnel === undefined) { - this._tunnel = this.option('tunnel', false); - } - return this._tunnel; - } - - get tunnelIdentifier(): string { - if (!this._tunnelIdentifier) { - this._tunnelIdentifier = this.option('tunnelIdentifier'); - } - return this._tunnelIdentifier; - } - - override async dispose(error: any): Promise { - try { - await this.driver?.execute(`sauce:job-result=${(error) ? 'failed' : 'passed'}`); - } catch (e) { - await this.logMgr.warn(e); - } - - await super.dispose(error); - } -} \ No newline at end of file diff --git a/packages/aft-ui-mobile-apps/test/facets/mobile-app-facet-spec.ts b/packages/aft-ui-mobile-apps/test/facets/mobile-app-facet-spec.ts deleted file mode 100644 index faf6dce3..00000000 --- a/packages/aft-ui-mobile-apps/test/facets/mobile-app-facet-spec.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { LogManager, rand } from "aft-core"; -import { Browser, Element, ElementArray, ChainablePromiseArray } from "webdriverio"; -import { MobileAppFacet, MobileAppFacetOptions, MobileAppSession } from "../../src"; - -describe('MobileAppFacet', () => { - beforeEach(() => { - jasmine.getEnv().allowRespy(true); - }); - - it('can auto-refresh from Driver on Error in getRoot', async () => { - let element: Element<'async'> = jasmine.createSpyObj('Element<"async">', { - 'isDisplayed': Promise.resolve(true), - 'isEnabled': Promise.resolve(true), - 'click': Promise.resolve(), - 'sendKeys': Promise.resolve(), - 'getAttribute': Promise.resolve('foo'), - '$$': Promise.resolve([] as ElementArray) - }); - let driver: Browser<'async'> = jasmine.createSpyObj('Browser<"async">', { - '$$': Promise.resolve([element]), - 'closeApp': Promise.resolve(), - 'destroySession': Promise.resolve(), - 'sessionId': rand.guid - }); - spyOn(driver, '$$').and.returnValues(Promise.reject('no element') as ChainablePromiseArray, Promise.resolve([element] as ElementArray) as ChainablePromiseArray); - let session = new MobileAppSession({ - driver: driver, - logMgr: new LogManager({logName: 'can auto-refresh from Driver on Error in getRoot'}) - }); - let facet: MobileAppFacet = await session.getFacet(MobileAppFacet, { - locator: 'div.fake', - maxWaitMs: 4000 - }); - let actual: Element<'async'> = await facet.getRoot(); - - expect(actual).toBeDefined(); - expect(await actual.isDisplayed()).toBe(true); - expect(driver.$$).toHaveBeenCalledTimes(2); - }); -}); \ No newline at end of file diff --git a/packages/aft-ui-mobile-apps/test/helpers/mobile-app-verifier-spec.ts b/packages/aft-ui-mobile-apps/test/helpers/mobile-app-verifier-spec.ts deleted file mode 100644 index dee407d3..00000000 --- a/packages/aft-ui-mobile-apps/test/helpers/mobile-app-verifier-spec.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { TestCaseManager } from "aft-core"; -import { Browser } from "webdriverio"; -import { MobileAppSession, MobileAppSessionOptions, MobileAppVerifier, verifyWithMobileApp } from "../../src"; -import { MobileAppSessionGeneratorManager } from "../../src/sessions/mobile-app-session-generator-manager"; - -describe('MobileAppVerifier', () => { - it('can create a MobileAppSession', async () => { - let sessionMgr: MobileAppSessionGeneratorManager = new MobileAppSessionGeneratorManager({plugins: []}); - spyOn(sessionMgr, 'newUiSession').and.callFake((options?: MobileAppSessionOptions): Promise> => { - return Promise.resolve(new MobileAppSession(options)); - }); - - await verifyWithMobileApp(async (mav: MobileAppVerifier) => { - expect(mav.session).toBeDefined(); - expect(mav.session.logMgr.logName).toBe(mav.logMgr.logName); - }).and.withMobileAppSessionGeneratorManager(sessionMgr); - - expect(sessionMgr.newUiSession).toHaveBeenCalledTimes(1); - }); - - it('can create a MobileAppSession using specific MobileAppSessionOptions', async () => { - let sessionMgr: MobileAppSessionGeneratorManager = new MobileAppSessionGeneratorManager({plugins: []}); - spyOn(sessionMgr, 'newUiSession').and.callFake((options?: MobileAppSessionOptions): Promise> => { - expect(options.uiplatform).toEqual('android_11_+_+_Google Pixel 5'); - return Promise.resolve(new MobileAppSession(options)); - }); - - await verifyWithMobileApp((mav: MobileAppVerifier) => { - expect(mav.session).toBeDefined(); - expect(mav.session.platform.toString()).toEqual('android_11_+_+_Google Pixel 5'); - }).and.withMobileAppSessionOptions({ - uiplatform: 'android_11_+_+_Google Pixel 5' - }).and.withMobileAppSessionGeneratorManager(sessionMgr); - - expect(sessionMgr.newUiSession).toHaveBeenCalledTimes(1); - }); - - it('disposes of MobileAppSession on completion', async () => { - let sessionMgr: MobileAppSessionGeneratorManager = new MobileAppSessionGeneratorManager({plugins: []}); - spyOn(sessionMgr, 'newUiSession').and.callFake((options?: MobileAppSessionOptions): Promise> => { - return Promise.resolve(new MobileAppSession(options)); - }); - let driver: Browser<'async'> = jasmine.createSpyObj('Browser<"async">', { - 'deleteSession': Promise.resolve() - }); - - await verifyWithMobileApp((mav: MobileAppVerifier) => { - expect(mav.session).toBeDefined(); - }).and.withMobileAppSessionOptions({driver: driver}) - .and.withMobileAppSessionGeneratorManager(sessionMgr); - - expect(sessionMgr.newUiSession).toHaveBeenCalledTimes(1); - expect(driver.deleteSession).toHaveBeenCalledTimes(1); - }); - - it('no MobileAppSession is created if assertion should not be run', async () => { - let sessionMgr: MobileAppSessionGeneratorManager = new MobileAppSessionGeneratorManager({plugins: []}); - spyOn(sessionMgr, 'newUiSession').and.callFake((options?: MobileAppSessionOptions): Promise> => { - return Promise.resolve(new MobileAppSession(options)); - }); - let tcMgr: TestCaseManager = new TestCaseManager(); - spyOn(tcMgr, 'shouldRun').and.callFake((testId: string) => Promise.resolve(false)); - - await verifyWithMobileApp((mav: MobileAppVerifier) => { - expect(true).toBeFalse(); - }).withTestIds('C1234') - .and.withMobileAppSessionGeneratorManager(sessionMgr) - .and.withTestCaseManager(tcMgr); - - expect(sessionMgr.newUiSession).not.toHaveBeenCalled(); - }); -}); \ No newline at end of file diff --git a/packages/aft-ui-mobile-apps/test/sessions/abstract-mobile-app-session-generator-plugin-spec.ts b/packages/aft-ui-mobile-apps/test/sessions/abstract-mobile-app-session-generator-plugin-spec.ts deleted file mode 100644 index 5775edc8..00000000 --- a/packages/aft-ui-mobile-apps/test/sessions/abstract-mobile-app-session-generator-plugin-spec.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { rand } from "aft-core"; -import { MobileAppSessionGeneratorPlugin, MobileAppSession, MobileAppSessionGeneratorPluginOptions, MobileAppSessionOptions } from "../../src"; -import { RemoteOptions } from "webdriverio"; - -describe('AbstractMobileAppGridSessionGeneratorPlugin', () => { - beforeEach(() => { - jasmine.getEnv().allowRespy(true); - }); - - it('can generate capabilities from the passed in SessionOptions', async () => { - let caps: {} = { - 'custom1': `custom1-${rand.getString(10)}`, - 'custom2': `custom2-${rand.getString(10)}`, - 'custom3': `custom3-${rand.getString(10)}`, - 'custom4': `custom4-${rand.getString(10)}` - }; - let session: FakeMobileAppSessionGeneratorPlugin = new FakeMobileAppSessionGeneratorPlugin({remoteOptions: {capabilities: caps}}); - let actual: RemoteOptions = await session.generateRemoteOptions(); - - for (var prop in caps) { - expect(actual.capabilities[prop]).toEqual(caps[prop]); - } - }); -}); - -class FakeMobileAppSessionGeneratorPlugin extends MobileAppSessionGeneratorPlugin { - async newUiSession(options?: MobileAppSessionOptions): Promise> { - return new MobileAppSession({ - driver: options?.driver || await this.createDriver({capabilities: {}}), - logMgr: options?.logMgr || this.logMgr, - uiplatform: options?.uiplatform || this.uiplatform.toString(), - app: options?.app || this.app - }); - } - async dispose(error?: Error): Promise { - /* do nothing */ - } - async sendCommand(command: string, data?: any): Promise { - /* do nothing */ - return null; - } -} \ No newline at end of file diff --git a/packages/aft-ui-mobile-apps/test/sessions/appium-grid/appium-grid-session-generator-plugin-spec.ts b/packages/aft-ui-mobile-apps/test/sessions/appium-grid/appium-grid-session-generator-plugin-spec.ts deleted file mode 100644 index 69cfb7e3..00000000 --- a/packages/aft-ui-mobile-apps/test/sessions/appium-grid/appium-grid-session-generator-plugin-spec.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { rand } from "aft-core"; -import { UiPlatform } from "aft-ui"; -import { RemoteOptions } from "webdriverio"; -import { AppiumGridSessionGeneratorPlugin } from "../../../src"; - -describe('AppiumGridSessionGeneratorPlugin', () => { - it('can generate capabilities from the passed in options', async () => { - let platform: UiPlatform = new UiPlatform({ - os: 'os-' + rand.getString(10), - osVersion: 'osVersion-' + rand.getString(2, false, true), - browser: 'browser-' + rand.getString(15), - browserVersion: 'browserVersion-' + rand.getString(2, false, true) - }); - let plugin: AppiumGridSessionGeneratorPlugin = new AppiumGridSessionGeneratorPlugin({ - uiplatform: platform.toString() - }); - let remOpts: RemoteOptions = await plugin.generateRemoteOptions(); - - expect(remOpts.capabilities['platform']).toEqual(`${platform.os} ${platform.osVersion}`); - expect(remOpts.capabilities['browserName']).not.toBeDefined(); - }); -}); \ No newline at end of file diff --git a/packages/aft-ui-mobile-apps/test/sessions/browserstack/browserstack-mobile-app-session-generator-plugin-spec.ts b/packages/aft-ui-mobile-apps/test/sessions/browserstack/browserstack-mobile-app-session-generator-plugin-spec.ts deleted file mode 100644 index 5d887dc1..00000000 --- a/packages/aft-ui-mobile-apps/test/sessions/browserstack/browserstack-mobile-app-session-generator-plugin-spec.ts +++ /dev/null @@ -1,103 +0,0 @@ -import { using, LogManager, rand, buildinfo } from "aft-core"; -import { UiPlatform } from "aft-ui"; -import { BrowserStackAppAutomateApi, BrowserStackMobileAppSession, BrowserStackMobileAppSessionGeneratorPlugin, BrowserStackMobileAppSessionGeneratorPluginOptions, MobileAppFacet, MobileAppFacetOptions, MobileAppSession, UploadRequest, UploadResponse } from "../../../src"; -import { RemoteOptions } from "webdriverio"; - -describe('BrowserStackMobileAppSessionGeneratorPlugin', () => { - it('can generate RemoteOptions from the passed in Options', async () => { - const platform: UiPlatform = new UiPlatform({ - os: `os-${rand.getString(10)}`, - osVersion: `osVersion-${rand.getString(2, false, true)}`, - browser: `browser-${rand.getString(15)}`, - browserVersion: `browserVersion-${rand.getString(2, false, true)}`, - deviceName: `deviceName-${rand.getString(22)}` - }); - const opts: BrowserStackMobileAppSessionGeneratorPluginOptions = { - user: `user-${rand.getString(10, true, false, false, false)}`, - key: `key-${rand.getString(12, true, true, false, false)}`, - local: true, - localIdentifier: `localId-${rand.getString(15)}`, - uiplatform: platform.toString(), - remoteOptions: { - capabilities: {"app": `app-${rand.getString(10)}`} - }, - logMgr: new LogManager({logName: 'can generate RemoteOptions from the passed in Options'}) - }; - const plugin: BrowserStackMobileAppSessionGeneratorPlugin = new BrowserStackMobileAppSessionGeneratorPlugin(opts); - - const remOpts: RemoteOptions = await plugin.generateRemoteOptions(); - - expect(remOpts.user).toEqual(opts.user); - expect(remOpts.key).toEqual(opts.key); - expect(remOpts.capabilities['os']).toEqual(platform.os); - expect(remOpts.capabilities['os_version']).toEqual(platform.osVersion); - expect(remOpts.capabilities['browserName']).not.toBeDefined(); - expect(remOpts.capabilities['browser_version']).not.toBeDefined(); - expect(remOpts.capabilities['device']).toEqual(platform.deviceName); - expect(remOpts.capabilities['realMobile']).toEqual(true); - expect(remOpts.capabilities['browserstack.local']).toEqual(true); - expect(remOpts.capabilities['browserstack.localIdentifier']).toEqual(opts.localIdentifier); - expect(remOpts.capabilities['build']).toEqual(await buildinfo.buildName()); - expect(remOpts.capabilities['name']).toEqual(opts.logMgr.logName); - expect(remOpts.capabilities['app']).toEqual(remOpts.capabilities['app']); - }); - - it('can upload a mobile application using sendCommand', async () => { - const platform: UiPlatform = new UiPlatform({ - os: 'os-' + rand.getString(10), - osVersion: 'osVersion-' + rand.getString(2, false, true), - browser: 'browser-' + rand.getString(15), - browserVersion: 'browserVersion-' + rand.getString(2, false, true), - deviceName: 'deviceName-' + rand.getString(22) - }); - const mockApi: BrowserStackAppAutomateApi = jasmine.createSpyObj('BrowserStackAppAutomateApi', { - "uploadApp": Promise.resolve({ - name: 'upload', - app_url: `app_url-${rand.guid}`, - custom_id: `custom_id-${rand.guid}`, - shareable_id: `shareable_id-${rand.guid}` - } as UploadResponse) - }); - const opts: BrowserStackMobileAppSessionGeneratorPluginOptions = { - user: rand.getString(10, true, false, false, false), - key: rand.getString(12, true, true, false, false), - local: true, - uiplatform: platform.toString(), - logMgr: new LogManager({logName: 'can upload a mobile application using sendCommand'}), - api: mockApi - }; - const plugin: BrowserStackMobileAppSessionGeneratorPlugin = new BrowserStackMobileAppSessionGeneratorPlugin(opts); - const response: any = await plugin.sendCommand('upload', { - file: `file-${rand.guid}`, - custom_id: `custom_id-${rand.guid}` - }); - - expect(response).toBeDefined(); - let uploadResponse: UploadResponse = response as UploadResponse; - expect(uploadResponse.app_url).toBeDefined(); - expect(uploadResponse.custom_id).toBeDefined(); - expect(uploadResponse.shareable_id).toBeDefined(); - }); - - /** - * WARNING: this test will attempt to create an actual session on BrowserStack - * it should only be used for local debugging. - * NOTE: you will need to set a value for the following via BrowserStackConfig - * or as environment variables: - * - browserstack_user - * - browserstack_accesskey - */ - xit('can create a session in BrowserStack', async () => { - const plugin: BrowserStackMobileAppSessionGeneratorPlugin = new BrowserStackMobileAppSessionGeneratorPlugin({ - user: '%browserstack_user%', - key: '%browserstack_key%', - uiplatform: 'android_11_+_+_Google Pixel 5' - }); - await using (await plugin.newUiSession(), async (session: BrowserStackMobileAppSession) => { - let facet = await session.getFacet(MobileAppFacet, {locator: 'button.radius'}); - - expect(facet).toBeDefined(); - expect(await facet.getRoot().then(r => r.getText())).toEqual('Login'); - }); - }, 300000); -}); \ No newline at end of file diff --git a/packages/aft-ui-mobile-apps/test/sessions/mobile-app-session-generator-plugin-manager-spec.ts b/packages/aft-ui-mobile-apps/test/sessions/mobile-app-session-generator-plugin-manager-spec.ts deleted file mode 100644 index 3a087f85..00000000 --- a/packages/aft-ui-mobile-apps/test/sessions/mobile-app-session-generator-plugin-manager-spec.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { MobileAppSessionGeneratorManager } from "../../src/sessions/mobile-app-session-generator-manager"; - -describe('MobileAppSessionGeneratorManager', () => { - it('can load BrowserStackMobileAppSessionGeneratorPlugin', async () => { - let mgr: MobileAppSessionGeneratorManager = new MobileAppSessionGeneratorManager({ - plugins: ['browserstack-mobile-app-session-generator-plugin'] - }); - - let plugin = await mgr.first(); - - expect(plugin).toBeDefined(); - expect(plugin.constructor.name).withContext('plugin should be instance type expected').toEqual('BrowserStackMobileAppSessionGeneratorPlugin'); - }); - - it('can load SauceLabsMobileAppSessionGeneratorPlugin', async () => { - let mgr: MobileAppSessionGeneratorManager = new MobileAppSessionGeneratorManager({ - plugins: ['sauce-labs-mobile-app-session-generator-plugin'] - }); - - let plugin = await mgr.first(); - - expect(plugin).toBeDefined(); - expect(plugin.constructor.name).withContext('plugin should be instance type expected').toEqual('SauceLabsMobileAppSessionGeneratorPlugin'); - }); - - it('can load AppiumGridSessionGeneratorPlugin', async () => { - let mgr: MobileAppSessionGeneratorManager = new MobileAppSessionGeneratorManager({ - plugins: ['appium-grid-session-generator-plugin'] - }); - - let plugin = await mgr.first(); - - expect(plugin).toBeDefined(); - expect(plugin.constructor.name).withContext('plugin should be instance type expected').toEqual('AppiumGridSessionGeneratorPlugin'); - }); -}); \ No newline at end of file diff --git a/packages/aft-ui-mobile-apps/test/sessions/sauce-labs/sauce-labs-mobile-app-session-generator-plugin-spec.ts b/packages/aft-ui-mobile-apps/test/sessions/sauce-labs/sauce-labs-mobile-app-session-generator-plugin-spec.ts deleted file mode 100644 index 62f9d1f9..00000000 --- a/packages/aft-ui-mobile-apps/test/sessions/sauce-labs/sauce-labs-mobile-app-session-generator-plugin-spec.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { using, LogManager, rand, buildinfo } from "aft-core"; -import { UiPlatform } from "aft-ui"; -import { MobileAppFacet, MobileAppFacetOptions, SauceLabsMobileAppSessionGeneratorPlugin, SauceLabsMobileAppSessionGeneratorPluginOptions } from '../../../src'; -import { RemoteOptions } from "webdriverio"; - -describe('SauceLabsMobileAppSessionGeneratorPlugin', () => { - it('can generate capabilities from the passed in SessionOptions', async () => { - const plt: UiPlatform = new UiPlatform({ - os: 'os-' + rand.getString(10), - osVersion: 'osVersion-' + rand.getString(2, false, true), - browser: 'browser-' + rand.getString(15), - browserVersion: 'browserVersion-' + rand.getString(2, false, true), - deviceName: 'deviceName-' + rand.getString(22) - }); - const opts: SauceLabsMobileAppSessionGeneratorPluginOptions = { - username: rand.getString(10, true, false, false, false), - accessKey: rand.getString(12, true, true, false, false), - tunnel: true, - tunnelIdentifier: rand.getString(11, true), - uiplatform: plt.toString(), - app: `app-${rand.getString(15)}`, - logMgr: new LogManager({logName:'can generate capabilities from the passed in SessionOptions'}) - } - const session: SauceLabsMobileAppSessionGeneratorPlugin = new SauceLabsMobileAppSessionGeneratorPlugin(opts); - - const remOpts: RemoteOptions = await session.generateRemoteOptions(); - - expect(remOpts.user).toEqual(opts.username); - expect(remOpts.key).toEqual(opts.accessKey); - expect(remOpts.capabilities['platformName']).toEqual(plt.os); - expect(remOpts.capabilities['platformVersion']).toEqual(plt.osVersion); - expect(remOpts.capabilities['browserName']).not.toBeDefined(); - expect(remOpts.capabilities['browserVersion']).not.toBeDefined(); - expect(remOpts.capabilities['deviceName']).toEqual(plt.deviceName); - expect(remOpts.capabilities['app']).toEqual(opts.app); - expect(remOpts.user).toEqual(opts.username); - expect(remOpts.key).toEqual(opts.accessKey); - expect(remOpts.capabilities['buildName']).toEqual(await buildinfo.get()); - expect(remOpts.capabilities['name']).toEqual(opts.logMgr.logName); - expect(remOpts.capabilities['tunnelIdentifier']).toEqual(opts.tunnelIdentifier); - }); - - /** - * WARNING: this test will attempt to create an actual session on Sauce Labs - * it should only be used for local debugging. - * NOTE: you will need to set a value for the following via SauceLabsConfig - * or as environment variables: - * - sauce_username - * - sauce_access_key - */ - xit('can create a session in Sauce Labs', async () => { - const plugin: SauceLabsMobileAppSessionGeneratorPlugin = new SauceLabsMobileAppSessionGeneratorPlugin({ - uiplatform: 'android_11_+_+_Google Pixel XL', - username: '%saucelabs_username%', - accessKey: '%saucelabs_accessKey%' - }); - await using (await plugin.newUiSession(), async (session) => { - let facet = await session.getFacet(MobileAppFacet, {locator: 'button.radius'}); - - expect(facet).toBeDefined(); - expect(await facet.getRoot().then(r => r.getText())).toEqual('Login'); - }); - }, 300000); -}); \ No newline at end of file diff --git a/packages/aft-ui-browsers/.nycrc b/packages/aft-ui-selenium/.nycrc similarity index 100% rename from packages/aft-ui-browsers/.nycrc rename to packages/aft-ui-selenium/.nycrc diff --git a/packages/aft-ui-browsers/LICENSE b/packages/aft-ui-selenium/LICENSE similarity index 100% rename from packages/aft-ui-browsers/LICENSE rename to packages/aft-ui-selenium/LICENSE diff --git a/packages/aft-ui-browsers/README.md b/packages/aft-ui-selenium/README.md similarity index 96% rename from packages/aft-ui-browsers/README.md rename to packages/aft-ui-selenium/README.md index fdd5a855..f479485e 100644 --- a/packages/aft-ui-browsers/README.md +++ b/packages/aft-ui-selenium/README.md @@ -137,13 +137,13 @@ export class HerokuMessagesFacet extends BrowserFacet { ```typescript await verifyWithBrowser(async (bv: BrowserVerifier) => { let loginPage: HerokuLoginPage = await bv.session.getFacet(HerokuLoginPage); - await bv.logMgr.step('navigate to LoginPage...'); + await bv.reporter.step('navigate to LoginPage...'); await loginPage.navigateTo(); - await bv.logMgr.step('login'); + await bv.reporter.step('login'); await loginPage.login("tomsmith", "SuperSecretPassword!"); - await bv.logMgr.step('wait for message to appear...') + await bv.reporter.step('wait for message to appear...') await wait.untilTrue(() => loginPage.hasMessage(), 20000); - await bv.logMgr.step('get message...'); + await bv.reporter.step('get message...'); return await loginPage.getMessage(); }).withDescription('can access websites using AFT and Page Widgets and Facets') .and.withTestId('C3456').and.withTestId('C2345').and.withTestId('C1234') diff --git a/packages/aft-ui-browsers/aft-ui-pom.drawio b/packages/aft-ui-selenium/aft-ui-pom.drawio similarity index 100% rename from packages/aft-ui-browsers/aft-ui-pom.drawio rename to packages/aft-ui-selenium/aft-ui-pom.drawio diff --git a/packages/aft-ui-browsers/aft-ui-pom.png b/packages/aft-ui-selenium/aft-ui-pom.png similarity index 100% rename from packages/aft-ui-browsers/aft-ui-pom.png rename to packages/aft-ui-selenium/aft-ui-pom.png diff --git a/packages/aft-ui-browsers/aftconfig.json b/packages/aft-ui-selenium/aftconfig.json similarity index 100% rename from packages/aft-ui-browsers/aftconfig.json rename to packages/aft-ui-selenium/aftconfig.json diff --git a/packages/aft-ui-browsers/package.json b/packages/aft-ui-selenium/package.json similarity index 79% rename from packages/aft-ui-browsers/package.json rename to packages/aft-ui-selenium/package.json index 60c8e5ff..bb269ce9 100644 --- a/packages/aft-ui-browsers/package.json +++ b/packages/aft-ui-selenium/package.json @@ -1,14 +1,14 @@ { - "name": "aft-ui-browsers", - "version": "9.0.0", - "description": "Automated Functional Testing (AFT) package supporting UI testing in browsers with support for BrowserStack, Sauce Labs and Local Selenium Grid", + "name": "aft-ui-selenium", + "version": "10.0.0", + "description": "Automated Functional Testing (AFT) package supporting UI testing in browsers", "main": "./dist/src/index.js", "types": "./dist/src/index.d.ts", "scripts": { "clean": "rimraf ./dist && rimraf ./.nyc_output && rimraf ./coverage", "build": "npm run clean && tsc --build", - "test": "jasmine-ts ./test/**/*-spec.ts", - "coverage": "nyc npm run test" + "test": "npm run build && jasmine-ts ./test/**/*-spec.ts", + "coverage": "npm run build && nyc jasmine-ts ./test/**/*-spec.ts" }, "repository": { "type": "git", @@ -24,8 +24,7 @@ "browser", "selenium", "browserstack", - "saucelabs", - "seleniumgrid" + "saucelabs" ], "author": "Jason Holt Smith ", "license": "MIT", @@ -34,11 +33,12 @@ }, "homepage": "https://github.com/bicarbon8/automated-functional-testing#readme", "dependencies": { - "aft-ui": "^9.0.0", + "aft-ui": "^10.0.0", "selenium-webdriver": "^4.3.0" }, "devDependencies": { "@types/jasmine": "^3.6.10", + "@types/lodash": "^4.14.194", "@types/node": "^15.0.1", "@types/selenium-webdriver": "^4.0.12", "jasmine": "^3.7.0", diff --git a/packages/aft-ui-selenium/src/components/selenium-component.ts b/packages/aft-ui-selenium/src/components/selenium-component.ts new file mode 100644 index 00000000..5dac90aa --- /dev/null +++ b/packages/aft-ui-selenium/src/components/selenium-component.ts @@ -0,0 +1,19 @@ +import { Func } from "aft-core"; +import { UiComponent } from "aft-ui"; +import { Locator, WebDriver, WebElement } from "selenium-webdriver"; + +export class SeleniumComponent extends UiComponent { + override get driver(): WebDriver { + return this._driver as WebDriver; + } + override get parent(): Func> { + return this._parent as Func>; + } + override get locator(): Locator { + return this._locator as Locator; + } + override async getRoot(): Promise { + const searchContext = (this.parent != null) ? await this.parent() : this.driver; + return await searchContext.findElement(this.locator); + } +} \ No newline at end of file diff --git a/packages/aft-ui-selenium/src/index.ts b/packages/aft-ui-selenium/src/index.ts new file mode 100644 index 00000000..324b7a6f --- /dev/null +++ b/packages/aft-ui-selenium/src/index.ts @@ -0,0 +1,8 @@ +/* components */ +export * from './components/selenium-component'; +/* verification */ +export * from './verification/selenium-verifier'; +export * from './verification/selenium-verifier-internals'; +/* sessions */ +export * from './sessions/local-session-generator-plugin'; +export * from './sessions/grid-session-generator-plugin'; \ No newline at end of file diff --git a/packages/aft-ui-selenium/src/sessions/grid-session-generator-plugin.ts b/packages/aft-ui-selenium/src/sessions/grid-session-generator-plugin.ts new file mode 100644 index 00000000..a872615b --- /dev/null +++ b/packages/aft-ui-selenium/src/sessions/grid-session-generator-plugin.ts @@ -0,0 +1,43 @@ +import { Builder, Capabilities, WebDriver } from "selenium-webdriver"; +import { UiSessionGeneratorPlugin } from "aft-ui"; +import { Err, Reporter } from "aft-core"; + +type GridSessionOptions = { + url: string; + implicitTimeoutMs: number; + capabilities: Record; +} + +export class GridSessionGeneratorPlugin extends UiSessionGeneratorPlugin { + private _reporter: Reporter; + get reporter(): Reporter { + if (!this._reporter) { + this._reporter = new Reporter(this.constructor.name, this.aftCfg); + } + return this._reporter; + } + override getSession = async (sessionOptions?: Record): Promise => { + const gso: GridSessionOptions = {...sessionOptions} as GridSessionOptions; + const caps: Capabilities = new Capabilities(gso.capabilities); + let driver: WebDriver; + if (caps) { + try { + driver = await new Builder() + .usingServer(gso.url ?? 'http://127.0.0.1:4444/wd/hub') + .withCapabilities(caps) + .build(); + await Err.handleAsync(async () => await driver.manage().setTimeouts({implicit: gso.implicitTimeoutMs ?? 1000}), { + logger: this.reporter, + errLevel: 'debug' + }); + await Err.handleAsync(async () => await driver.manage().window().maximize(), { + logger: this.reporter, + errLevel: 'debug' + }); + } catch (e) { + this.reporter.warn(`error in creating WebDriver due to: ${Err.full(e)}`); + } + } + return driver; + } +} \ No newline at end of file diff --git a/packages/aft-ui-selenium/src/sessions/local-session-generator-plugin.ts b/packages/aft-ui-selenium/src/sessions/local-session-generator-plugin.ts new file mode 100644 index 00000000..c68561da --- /dev/null +++ b/packages/aft-ui-selenium/src/sessions/local-session-generator-plugin.ts @@ -0,0 +1,24 @@ +import { Builder, WebDriver } from "selenium-webdriver"; +import { UiSessionGeneratorPlugin } from "aft-ui"; + +type LocalSessionOptions = { + browserName: string; + capabilities: Record; +}; + +export class LocalSessionGeneratorPlugin extends UiSessionGeneratorPlugin { + override getSession = async (sessionOptions?: Record): Promise => { + const lso = {...sessionOptions} as LocalSessionOptions; + const caps = lso.capabilities ?? {}; + let driver: WebDriver; + try { + driver = new Builder() + .forBrowser(lso.browserName ?? 'chrome') + .withCapabilities(caps) + .build(); + } catch (e) { + this.aftLogger.log({name: this.constructor.name, level: 'error', message: e}); + } + return driver; + } +} \ No newline at end of file diff --git a/packages/aft-ui-selenium/src/verification/selenium-verifier-internals.ts b/packages/aft-ui-selenium/src/verification/selenium-verifier-internals.ts new file mode 100644 index 00000000..b8cb9a1e --- /dev/null +++ b/packages/aft-ui-selenium/src/verification/selenium-verifier-internals.ts @@ -0,0 +1,13 @@ +import { Merge, VerifierInternals, Verifier } from "aft-core"; +import { UiSessionGeneratorManager } from "aft-ui"; + +export type SeleniumVerifierInternals = Merge Verifier +}>; \ No newline at end of file diff --git a/packages/aft-ui-selenium/src/verification/selenium-verifier.ts b/packages/aft-ui-selenium/src/verification/selenium-verifier.ts new file mode 100644 index 00000000..70be421f --- /dev/null +++ b/packages/aft-ui-selenium/src/verification/selenium-verifier.ts @@ -0,0 +1,123 @@ +import { Class, Err, Func, Verifier } from "aft-core"; +import { WebDriver } from "selenium-webdriver"; +import { UiComponentOptions, UiSessionGeneratorManager } from "aft-ui"; +import { SeleniumVerifierInternals } from "./selenium-verifier-internals"; +import { SeleniumComponent } from "../components/selenium-component"; + +export class SeleniumVerifier extends Verifier { + protected override _assertion: Func; + protected _driver: unknown; + protected _sessionMgr: UiSessionGeneratorManager; + private _sessionOptions: Record = {}; + + /** + * a {UiSessionGeneratorManager} instance used to generate new + * Browser sessions + */ + get sessionGeneratorManager(): UiSessionGeneratorManager { + if (!this._sessionMgr) { + this._sessionMgr = new UiSessionGeneratorManager(this.aftCfg); + } + return this._sessionMgr; + } + + /** + * after a new driver instance is created, this holds the instance + * so it can be referenced from within the executing `assertion` + */ + get driver(): WebDriver { + return this._driver as WebDriver; + } + + override get internals(): SeleniumVerifierInternals { + const baseInternals = super.internals as SeleniumVerifierInternals; + baseInternals.usingUiSessionGeneratorManager = (mgr: UiSessionGeneratorManager) => { + this._sessionMgr = mgr; + return this; + }; + return baseInternals; + } + + /** + * allows specifying additional session options to be merged with those + * specified in your `aftconfig.json` file under the `UiSessionConfig.options` + * property. for example, if your `aftconfig.json` already contained the + * following options: + * ```json + * // aftconfig.json + * { + * "UiSessionConfig": { + * "generatorName": "foo-bar-baz", + * "options": { + * "bstack:options": { + * "user": "foo1234", + * "key": "klajsdflk1241234" + * } + * } + * } + * } + * ``` + * and you provided the following via `opts` here: + * ```typescript + * verifyWithSelenium(...).withAdditionalSessionOptions({ + * "bstack:options": { + * "sessionName": "FooBarBaz" + * } + * }); + * ``` + * your resulting options passed to the {UiSessionGeneratorManager} would + * look like: + * ```typescript + * { + * "bstack:options": { + * "user": "foo1234", + * "key": "klajsdflk1241234", + * "sessionName": "FooBarBaz" + * } + * } + * ``` + * @param opts a {Record} containing capabilities to be used + * @returns a reference to {this} + */ + withAdditionalSessionOptions(opts: Record): this { + this._sessionOptions = opts; + return this; + } + + getComponent(componentType: Class, opts?: UiComponentOptions): T { + opts ??= {} as UiComponentOptions; + opts.aftCfg ??= this.aftCfg; + opts.driver ??= this.driver; + opts.reporter ??= this.reporter; + return new componentType(opts); + } + + protected override async _resolveAssertion(): Promise { + this._driver = await this.sessionGeneratorManager.getSession(this._sessionOptions); + try { + await super._resolveAssertion(); + } finally { + Err.handleAsync(async () => await this.driver?.close()); + Err.handleAsync(async () => await this.driver?.quit()); + } + } +} + +/** + * creates a new `SeleniumVerifier` instace to be used for executing some Functional + * Test Assertion. + * ex: + * ``` + * await verifyWithSelenium(async (v: SeleniumVerifier) => { + * let facet: MyFacet = await v.getComponent(MyFacet); + * return await facet.returnExpectedValue(); + * }).withDescription('example usage for SeleniumVerifier') + * .and.withTestId('C1234') + * .returns('expected value'); + * ``` + * @param assertion the {Func} function to be executed by this `SeleniumVerifier` + * @returns a new `SeleniumVerifier` instance + */ +export const verifyWithSelenium = (assertion: Func): SeleniumVerifier => { + return new SeleniumVerifier().verify(assertion); +} \ No newline at end of file diff --git a/packages/aft-ui-selenium/test/components/selenium-component-spec.ts b/packages/aft-ui-selenium/test/components/selenium-component-spec.ts new file mode 100644 index 00000000..0399c8ae --- /dev/null +++ b/packages/aft-ui-selenium/test/components/selenium-component-spec.ts @@ -0,0 +1,42 @@ +import { By, WebDriver, WebElement, WebElementPromise } from "selenium-webdriver" +import { SeleniumComponent } from "../../src/components/selenium-component"; + +describe('SeleniumComponent', () => { + it('uses the driver if no parent present', async () => { + let mockElement: WebElement; + mockElement = jasmine.createSpyObj({ + findElement: Promise.resolve(mockElement) as WebElementPromise + }); + const mockDriver = jasmine.createSpyObj({ + findElement: Promise.resolve(mockElement) as WebElementPromise + }); + const compo = new SeleniumComponent({ + driver: mockDriver, + locator: By.css('fake.css') + }); + + const root = await compo.getRoot(); + + expect(mockDriver.findElement).toHaveBeenCalledTimes(1); + }) + + it('uses the parent if parent present', async () => { + let mockElement: WebElement; + mockElement = jasmine.createSpyObj({ + findElement: Promise.resolve(mockElement) as WebElementPromise + }); + const mockDriver = jasmine.createSpyObj({ + findElement: Promise.resolve(mockElement) as WebElementPromise + }); + const compo = new SeleniumComponent({ + driver: mockDriver, + locator: By.css('fake.css'), + parent: () => Promise.resolve(mockElement) + }); + + const root = await compo.getRoot(); + + expect(mockDriver.findElement).not.toHaveBeenCalled(); + expect(mockElement.findElement).toHaveBeenCalledTimes(1); + }) +}) \ No newline at end of file diff --git a/packages/aft-ui-selenium/test/sessions/grid-session-generator-plugin-spec.ts b/packages/aft-ui-selenium/test/sessions/grid-session-generator-plugin-spec.ts new file mode 100644 index 00000000..204524f8 --- /dev/null +++ b/packages/aft-ui-selenium/test/sessions/grid-session-generator-plugin-spec.ts @@ -0,0 +1,47 @@ +import { AftConfig, rand } from "aft-core"; +import { By } from "selenium-webdriver"; +import { GridSessionGeneratorPlugin } from "../../src"; +import { SeleniumComponent } from "../../src/components/selenium-component"; + +describe('GridSessionGeneratorPlugin', () => { + /** + * WARNING: this test will attempt to create an actual session on your own Selenium Grid + * it should only be used for local debugging. + * NOTE: you will need to set a value for the following via SeleniumGridConfig + * or as environment variables: + * - selenium_grid_url + */ + xit('can create a session on Selenium Grid', async () => { + const aftCfg = new AftConfig({ + UiSessionConfig: { + options: { + capabilities: { + platform: 'windows', + browserName: 'chrome' + } + } + } + }); + const plugin: GridSessionGeneratorPlugin = new GridSessionGeneratorPlugin(); + const session = await plugin.getSession(); + try { + let expectedUrl: string = 'https://the-internet.herokuapp.com/login'; + await session.navigate().to(expectedUrl); + + let actualUrl: string = await session.getCurrentUrl(); + + expect(actualUrl).toEqual(expectedUrl); + + let facet = new SeleniumComponent({ + driver: session, + locator: By.css('button.radius') + }); + + expect(facet).toBeDefined(); + expect(await facet.getRoot().then(r => r.getText())).toEqual('Login'); + } finally { + session?.close(); + session?.quit(); + } + }, 300000); +}); \ No newline at end of file diff --git a/packages/aft-ui-selenium/test/verification/selenium-verifier-spec.ts b/packages/aft-ui-selenium/test/verification/selenium-verifier-spec.ts new file mode 100644 index 00000000..1a3a4126 --- /dev/null +++ b/packages/aft-ui-selenium/test/verification/selenium-verifier-spec.ts @@ -0,0 +1,65 @@ +import { TestExecutionPolicyManager, AftConfig } from "aft-core"; +import { UiSessionGeneratorManager } from "aft-ui"; +import { WebDriver } from "selenium-webdriver"; +import { SeleniumVerifier, verifyWithSelenium } from "../../src"; + +describe('SeleniumVerifier', () => { + it('calls UiSessionGeneratorManager.getSession when run', async () => { + const sessionMgr = new UiSessionGeneratorManager(); + spyOn(sessionMgr, 'getSession').and.callFake((opts?: Record) => Promise.resolve({})); + await verifyWithSelenium(async (bv: SeleniumVerifier) => { + expect(bv.driver).withContext('SeleniumVerifier should create a new driver').toBeDefined(); + }).internals.usingUiSessionGeneratorManager(sessionMgr); + + expect(sessionMgr.getSession).toHaveBeenCalledTimes(1); + }); + + it('can create a BrowserSession using specific BrowserSessionOptions', async () => { + const sessionMgr = new UiSessionGeneratorManager(new AftConfig({ + UiSessionConfig: { + uiplatform: { + os: 'windows', + osVersion: '8.1', + browser: 'firefox' + } + } + })); + spyOn(sessionMgr, 'getSession').and.callFake((opts?: Record) => Promise.resolve({})); + + await verifyWithSelenium((bv: SeleniumVerifier) => { + expect(bv.driver).toBeDefined(); + }).internals.usingUiSessionGeneratorManager(sessionMgr); + + expect(sessionMgr.getSession).toHaveBeenCalledTimes(1); + }); + + it('disposes of BrowserSession on completion', async () => { + const sessionMgr = new UiSessionGeneratorManager(); + let driver: WebDriver = jasmine.createSpyObj('WebDriver', { + 'quit': Promise.resolve() + }); + spyOn(sessionMgr, 'getSession').and.callFake((opts?: Record) => Promise.resolve(driver)); + + await verifyWithSelenium((bv: SeleniumVerifier) => { + expect(bv.driver).toBeDefined(); + }).internals.usingUiSessionGeneratorManager(sessionMgr); + + expect(sessionMgr.getSession).toHaveBeenCalledTimes(1); + expect(driver.quit).toHaveBeenCalledTimes(1); + }); + + it('no BrowserSession is created if assertion should not be run', async () => { + const sessionMgr = new UiSessionGeneratorManager(); + spyOn(sessionMgr, 'getSession').and.callFake((opts?: Record) => Promise.resolve({})); + let tcMgr: TestExecutionPolicyManager = new TestExecutionPolicyManager(); + spyOn(tcMgr, 'shouldRun').and.callFake((testId: string) => Promise.resolve({result: false})); + + await verifyWithSelenium((bv: SeleniumVerifier) => { + expect(true).toBeFalse(); + }).internals.usingUiSessionGeneratorManager(sessionMgr) + .internals.usingTestExecutionPolicyManager(tcMgr) + .and.withTestIds('C1234') + + expect(sessionMgr.getSession).not.toHaveBeenCalled(); + }); +}); \ No newline at end of file diff --git a/packages/aft-ui-browsers/tsconfig.json b/packages/aft-ui-selenium/tsconfig.json similarity index 100% rename from packages/aft-ui-browsers/tsconfig.json rename to packages/aft-ui-selenium/tsconfig.json diff --git a/packages/aft-ui-mobile-apps/.nycrc b/packages/aft-ui-webdriverio/.nycrc similarity index 100% rename from packages/aft-ui-mobile-apps/.nycrc rename to packages/aft-ui-webdriverio/.nycrc diff --git a/packages/aft-ui-mobile-apps/LICENSE b/packages/aft-ui-webdriverio/LICENSE similarity index 100% rename from packages/aft-ui-mobile-apps/LICENSE rename to packages/aft-ui-webdriverio/LICENSE diff --git a/packages/aft-ui-webdriverio/README.md b/packages/aft-ui-webdriverio/README.md new file mode 100644 index 00000000..061b046c --- /dev/null +++ b/packages/aft-ui-webdriverio/README.md @@ -0,0 +1,69 @@ +# AFT-UI-Mobile-Apps +Automated Functional Testing (AFT) package providing Appium-based `MobileAppFacet extends UiFacet` Plugins and BrowserStack, Sauce Labs and Appium Grid `UiSession` Plugins extending the `aft-ui` package. This enables testing using BrowserStack's, Sauce Labs's or a Local Selenium Grid for any Mobile Device application tests. + +## Installation +`> npm i aft-ui-mobile-apps` + +## Creating your own Components for use in testing +Take the following as an example of how one could interact with the following Android App + +### Step 1: create the View Component + +```typescript +// wikipedia-view.ts +export class WikipediaView extends WebdriverIoComponent { + override get locator(): string { + return '//*'; + } + private _searchButton = async (): Promise> => await (await this.getRoot()).$("~Search Wikipedia"); + private _searchInput = async (): Promise> => await this.driver.$('android=new UiSelector().resourceId("org.wikipedia.alpha:id/search_src_text")'); + private _searchResults = async (): Promise>> => await (await this.getRoot()).$$("android.widget.TextView"); + async searchFor(term: string): Promise { + await this.reporter.info("tapping on 'SearchButton'"); + await this._searchButton().then(b => b.click()); + await this.sendTextToSearch(term); + return await this.getResults(); + } + async sendTextToSearch(text: string): Promise { + await this.reporter.info(`setting 'SearchInput' to '${text}'...`); + await this._searchInput().then(i => i.addValue(text)); + } + async getResults(): Promise { + await this.reporter.info("getting text from 'SearchResults' to return as 'string[]'"); + let resultsText: string[] = []; + + var searchResults = await this._searchResults(); + for (var i=0; i err); + resultsText.push(txt); + } + await this.reporter.info(`found results of: [${resultsText.join(', ')}]`); + return resultsText; + } +} +``` +### Step 2: use them to interact with the mobile application + +```typescript +// wikipedia-app.spec.ts +await verifyWithWebdriverIO(async (v: WebdriverIoVerifier) => { + await v.reporter.step('get the WikipediaView Facet from the Session...'); + let view: WikipediaView = v.getComponent(WikipediaView); + await v.reporter.step('enter a search term...'); + await view.searchFor('pizza'); + await v.reporter.step('get the results and ensure they contain the search term...'); + let results: string[] = await view.getResults(); + let contains: boolean = false; + for (var i=0; i { + return this._driver as Browser<'async'>; + } + override get locator(): string { + return this._locator as string; + } + override get parent(): Func>> { + return this._parent as Func>>; + } + override async getRoot(): Promise> { + const searchCtx = (this.parent) ? await this.parent() : this.driver; + return await searchCtx.$(this.locator); + } +} \ No newline at end of file diff --git a/packages/aft-ui-webdriverio/src/index.ts b/packages/aft-ui-webdriverio/src/index.ts new file mode 100644 index 00000000..a30b0175 --- /dev/null +++ b/packages/aft-ui-webdriverio/src/index.ts @@ -0,0 +1,7 @@ +/* facets */ +export * from './components/webdriverio-component'; +/* verification */ +export * from './verification/webdriverio-verifier-internals'; +export * from './verification/webdriverio-verifier'; +/* sessions */ +export * from './sessions/webdriverio-remote-session-generator-plugin'; \ No newline at end of file diff --git a/packages/aft-ui-webdriverio/src/sessions/webdriverio-remote-session-generator-plugin.ts b/packages/aft-ui-webdriverio/src/sessions/webdriverio-remote-session-generator-plugin.ts new file mode 100644 index 00000000..6eeb5806 --- /dev/null +++ b/packages/aft-ui-webdriverio/src/sessions/webdriverio-remote-session-generator-plugin.ts @@ -0,0 +1,15 @@ +import { UiSessionGeneratorPlugin } from "aft-ui"; +import { Browser, remote, RemoteOptions } from "webdriverio"; + +export class WebdriverIoRemoteSessionGeneratorPlugin extends UiSessionGeneratorPlugin { + override getSession = async(options?: Record): Promise> => { + const ro: RemoteOptions = {...options} as RemoteOptions; + let browser: Browser<'async'>; + try { + browser = await remote(ro); + } catch (e) { + this.aftLogger.log({name: this.constructor.name, level: 'error', message: e}); + } + return browser; + } +} \ No newline at end of file diff --git a/packages/aft-ui-webdriverio/src/verification/webdriverio-verifier-internals.ts b/packages/aft-ui-webdriverio/src/verification/webdriverio-verifier-internals.ts new file mode 100644 index 00000000..7a10fa58 --- /dev/null +++ b/packages/aft-ui-webdriverio/src/verification/webdriverio-verifier-internals.ts @@ -0,0 +1,13 @@ +import { Merge, Verifier, VerifierInternals } from "aft-core"; +import { UiSessionGeneratorManager } from "aft-ui"; + +export type WebdriverIoVerifierInternals = Merge Verifier +}>; \ No newline at end of file diff --git a/packages/aft-ui-webdriverio/src/verification/webdriverio-verifier.ts b/packages/aft-ui-webdriverio/src/verification/webdriverio-verifier.ts new file mode 100644 index 00000000..4df58cb2 --- /dev/null +++ b/packages/aft-ui-webdriverio/src/verification/webdriverio-verifier.ts @@ -0,0 +1,124 @@ +import { Class, Err, Func, Verifier } from "aft-core"; +import { UiComponentOptions, UiSessionGeneratorManager } from "aft-ui"; +import { Browser } from "webdriverio"; +import { WebdriverIoVerifierInternals } from "./webdriverio-verifier-internals"; +import { WebdriverIoComponent } from "../components/webdriverio-component"; + +export class WebdriverIoVerifier extends Verifier { + protected override _assertion: Func; + protected _sessionMgr: UiSessionGeneratorManager; + protected _browser: unknown; + protected _sessionOptions: Record; + + /** + * a `UiSessionGeneratorManager` instance used to generate new + * UI Sessions from + */ + get sessionGeneratorManager(): UiSessionGeneratorManager { + if (!this._sessionMgr) { + this._sessionMgr = new UiSessionGeneratorManager(this.aftCfg); + } + return this._sessionMgr; + } + + /** + * after a new `Browser<'async'>` session is created, this holds the instance + * so it can be referenced from within the executing `assertion` + */ + get browser(): Browser<'async'> { + return this._browser as Browser<'async'>; + } + + override get internals(): WebdriverIoVerifierInternals { + const baseInternals = super.internals as WebdriverIoVerifierInternals; + baseInternals.usingUiSessionGeneratorManager = (mgr: UiSessionGeneratorManager) => { + this._sessionMgr = mgr; + return this; + }; + return baseInternals; + } + + /** + * allows specifying additional session options to be merged with those + * specified in your `aftconfig.json` file under the `UiSessionConfig.options` + * property. for example, if your `aftconfig.json` already contained the + * following options: + * ```json + * // aftconfig.json + * { + * "UiSessionConfig": { + * "generatorName": "foo-bar-baz", + * "options": { + * "bstack:options": { + * "user": "foo1234", + * "key": "klajsdflk1241234" + * } + * } + * } + * } + * ``` + * and you provided the following via `opts` here: + * ```typescript + * verifyWithWebdriverIO(...).withAdditionalSessionOptions({ + * "bstack:options": { + * "sessionName": "FooBarBaz" + * } + * }); + * ``` + * your resulting options passed to the {UiSessionGeneratorManager} would + * look like: + * ```typescript + * { + * "bstack:options": { + * "user": "foo1234", + * "key": "klajsdflk1241234", + * "sessionName": "FooBarBaz" + * } + * } + * ``` + * @param opts a {Record} containing capabilities to be used + * @returns a reference to {this} + */ + withAdditionalSessionOptions(opts: Record): this { + this._sessionOptions = opts; + return this; + } + + getComponent(componentType: Class, opts?: UiComponentOptions): T { + opts ??= {} as UiComponentOptions; + opts.aftCfg ??= this.aftCfg; + opts.driver ??= this.browser; + opts.reporter ??= this.reporter; + return new componentType(opts); + } + + protected override async _resolveAssertion(): Promise { + this._browser = await this.sessionGeneratorManager.getSession(this._sessionOptions); + try { + await super._resolveAssertion(); + } finally { + Err.handleAsync(async () => await this.browser.deleteSession()); + } + } +} + +/** + * creates a new `WebdriverIoVerifier` instace to be used for executing some Functional + * Test Assertion. + * ex: + * ``` + * await verifyWithWebdriverIO(async (v: WebdriverIoVerifier) => { + * let compo: MyComponent = await v.getComponent(MyComponent); + * return await compo.returnExpectedValue(); + * }).withDescription('example usage for WebdriverIoVerifier') + * .and.withTestId('C1234') + * .returns('expected value'); + * ``` + * @param assertion the `Func` function to be executed by this `WebdriverIoVerifier` + * @returns a new `WebdriverIoVerifier` instance + */ +export const verifyWithWebdriverIO = (assertion: Func): WebdriverIoVerifier => { + let v: WebdriverIoVerifier = new WebdriverIoVerifier(); + v.verify(assertion); + return v; +} \ No newline at end of file diff --git a/packages/aft-ui-webdriverio/test/verification/webdriverio-verifier-spec.ts b/packages/aft-ui-webdriverio/test/verification/webdriverio-verifier-spec.ts new file mode 100644 index 00000000..ecaed696 --- /dev/null +++ b/packages/aft-ui-webdriverio/test/verification/webdriverio-verifier-spec.ts @@ -0,0 +1,99 @@ +import { AftConfig, TestExecutionPolicyManager } from "aft-core"; +import { UiSessionGeneratorManager } from "aft-ui"; +import { Browser, ChainablePromiseElement, Element } from "webdriverio"; +import { WebdriverIoVerifier, verifyWithWebdriverIO } from "../../src"; + +describe('WebdriverIoVerifier', () => { + it('can create a MobileAppSession', async () => { + let mockElement: Element<'async'>; + mockElement = jasmine.createSpyObj>({ + "$": Promise.resolve(mockElement) as ChainablePromiseElement> + }); + const mockBrowser: Browser<'async'> = jasmine.createSpyObj>({ + "$": Promise.resolve(mockElement) as ChainablePromiseElement> + }) + const sessionMgr = new UiSessionGeneratorManager(new AftConfig({})); + spyOn(sessionMgr, 'getSession').and.callFake((options?: Record): Promise => { + return Promise.resolve(mockBrowser); + }); + + await verifyWithWebdriverIO(async (mav: WebdriverIoVerifier) => { + expect(mav.browser).toBeDefined(); + }).internals.usingUiSessionGeneratorManager(sessionMgr); + + expect(sessionMgr.getSession).toHaveBeenCalledTimes(1); + }); + + it('can create a MobileAppSession using specific MobileAppSessionOptions', async () => { + let mockElement: Element<'async'>; + mockElement = jasmine.createSpyObj>({ + "$": Promise.resolve(mockElement) as ChainablePromiseElement> + }); + const mockBrowser: Browser<'async'> = jasmine.createSpyObj>({ + "$": Promise.resolve(mockElement) as ChainablePromiseElement> + }) + const sessionMgr = new UiSessionGeneratorManager(new AftConfig({})); + spyOn(sessionMgr, 'getSession').and.callFake((options?: Record): Promise => { + expect(options['foo']).toEqual('bar'); + expect(options['baz']).toBe(1); + return Promise.resolve(mockBrowser); + }); + + const opts = { + foo: 'bar', + baz: 1 + }; + await verifyWithWebdriverIO(async (mav: WebdriverIoVerifier) => { + expect(mav.browser).toBeDefined(); + }).withAdditionalSessionOptions(opts) + .internals.usingUiSessionGeneratorManager(sessionMgr); + + expect(sessionMgr.getSession).toHaveBeenCalledTimes(1); + }); + + it('disposes of MobileAppSession on completion', async () => { + let mockElement: Element<'async'>; + mockElement = jasmine.createSpyObj>({ + "$": Promise.resolve(mockElement) as ChainablePromiseElement> + }); + const mockBrowser: Browser<'async'> = jasmine.createSpyObj>({ + "$": Promise.resolve(mockElement) as ChainablePromiseElement>, + "deleteSession": Promise.resolve() + }); + const sessionMgr = new UiSessionGeneratorManager(new AftConfig({})); + spyOn(sessionMgr, 'getSession').and.callFake((options?: Record): Promise => { + return Promise.resolve(mockBrowser); + }); + + await verifyWithWebdriverIO(async (mav: WebdriverIoVerifier) => { + expect(mav.browser).toBeDefined(); + }).internals.usingUiSessionGeneratorManager(sessionMgr); + + expect(sessionMgr.getSession).toHaveBeenCalledTimes(1); + expect(mockBrowser.deleteSession).toHaveBeenCalledTimes(1); + }); + + it('no MobileAppSession is created if assertion should not be run', async () => { + let mockElement: Element<'async'>; + mockElement = jasmine.createSpyObj>({ + "$": Promise.resolve(mockElement) as ChainablePromiseElement> + }); + const mockBrowser: Browser<'async'> = jasmine.createSpyObj>({ + "$": Promise.resolve(mockElement) as ChainablePromiseElement> + }) + const sessionMgr = new UiSessionGeneratorManager(new AftConfig({})); + spyOn(sessionMgr, 'getSession').and.callFake((options?: Record): Promise => { + return Promise.resolve(mockBrowser); + }); + const peMgr: TestExecutionPolicyManager = new TestExecutionPolicyManager(); + spyOn(peMgr, 'shouldRun').and.callFake((testId: string) => Promise.resolve({result: false})); + + await verifyWithWebdriverIO((mav: WebdriverIoVerifier) => { + expect(true).toBeFalse(); + }).withTestIds('C1234') + .internals.usingUiSessionGeneratorManager(sessionMgr) + .internals.usingTestExecutionPolicyManager(peMgr); + + expect(sessionMgr.getSession).not.toHaveBeenCalled(); + }); +}); \ No newline at end of file diff --git a/packages/aft-ui-mobile-apps/tsconfig.json b/packages/aft-ui-webdriverio/tsconfig.json similarity index 69% rename from packages/aft-ui-mobile-apps/tsconfig.json rename to packages/aft-ui-webdriverio/tsconfig.json index 0c1a4dcb..e1eecc80 100644 --- a/packages/aft-ui-mobile-apps/tsconfig.json +++ b/packages/aft-ui-webdriverio/tsconfig.json @@ -6,7 +6,6 @@ }, "include": ["src", "test"], "references": [ - { "path": "../aft-ui" }, - { "path": "../aft-web-services" } + { "path": "../aft-ui" } ] } \ No newline at end of file diff --git a/packages/aft-ui/README.md b/packages/aft-ui/README.md index 88266140..9e5a0611 100644 --- a/packages/aft-ui/README.md +++ b/packages/aft-ui/README.md @@ -1,172 +1,75 @@ -# AFT-UI -Automated Functional Testing (AFT) package supporting UI interactions using the Page Object Model (POM) to streamline UI test development and also supporting extension via plugins to support systems such as Selenium and Cypress. - -> **!!WARNING!!** -this package is only for those who know what they're doing and are familiar with AFT internals. it is intended as a base to be consumed by packages implementing support for UI test session creation (such as Selenium) +# AFT-SELENIUM +Automated Functional Testing (AFT) package supporting Selenium interactions using the Page Object Model (POM) to streamline UI test development and also supporting extension via plugins to support systems such as Selenium and Cypress. ## Installation -`> npm i aft-ui` +`> npm i aft-selenium` ## Page Object Model (POM) -the POM is a standard design pattern used in UI and layout testing. AFT-UI supports this model via an `UiFacet` class that is made up of one or more `UiFacet` classes and / or elements encapsulating logical blocks of functionality on the page. The `aft-ui` package supports development of libraries used to generate UI test sessions (via the `UiSessionGeneratorManager`, `UiSessionGeneratorPlugin`, classes and `UiSession` interface). +the POM is a standard design pattern used in UI and layout testing. AFT-UI supports this model via an `UiComponent` class that is made up of one or more `UiComponent` classes and / or elements encapsulating logical blocks of functionality on the page. The `aft-selenium` package supports local and remote Selenium WebDriver instantiation as well as development of libraries used to generate UI test sessions (via the `UiSessionGeneratorManager`, `UiSessionGeneratorPlugin`, classes). -### Creating a Session Generator Plugin (Selenium) -the `UiSessionGeneratorPlugin` implementation is responsible for creating new UI session instances (classes extending from `UiSession`) +### Creating a Session Generator Plugin (BrowserStack) +the `UiSessionGeneratorPlugin` implementation is responsible for creating new UI session instances (classes extending from `WebDriver`) ```typescript -export type SeleniumSessionGeneratorPluginOptions = Merge; - -export class SeleniumSessionGeneratorPlugin extends UiSessionGeneratorPlugin { - override async newUiSession(options?: SeleniumSessionOptions): Promise { - if (!options?.driver) { - try { - let url: string = this.option('url', 'http://127.0.0.1:4444/'); - let caps: Capabilities = new Capabilities(this.option('additionalCapabilities', {})); - let driver: WebDriver = await new Builder() - .usingServer(url) - .withCapabilities(caps) - .build(); - await driver.manage().setTimeouts({implicit: 1000}); - await driver.manage().window().maximize(); - return new SeleniumSession({ - driver: driver, - logMgr: options?.logMgr || this.logMgr - }); - } catch (e) { - return Promise.reject(e); - } - } - return new SeleniumSession({driver: options.driver, logMgr: options.logMgr || this.logMgr}); - } +export class BrowserStackAutomateConfig { + uiplatform: UiPlatform; + url: string = 'https://hub-cloud.browserstack.com/wd/hub/'; + api: string = 'https://api.browserstack.com/automate/'; + username: string; + accessKey: string; } -``` - -### Create a `UiSession` implementation (Selenium) -the `UiSession` implementation is used to keep reference to the running UI session as well as to create instances of the logical UI groups (`UiFacet`) which manage interactions with the UI elements - -```typescript -export type SeleniumSessionOptions = Merge; - -export class SeleniumSession implements UiSession { - readonly driver: WebDriver; // overrides 'unknown' driver type from 'UiSession' - readonly logMgr: LogManager; - constructor(options: SeleniumSessionOptions) { - this._driver = options.driver; - this.logMgr = options.logMgr || new LogManager({logName: this.constructor.name}); - } - async getFacet, To extends UiFacetOptions>(facetType: Class, options?: To): Promise { - options = options || {} as To; - options.session = options.session || this; - options.logMgr = options.logMgr || this.logMgr; - let facet: T = new facetType(options); - return facet; - } - async goTo(url: string): Promise { - try { - await this.driver?.get(url); - } catch (e) { - return Promise.reject(e); - } - } - async refresh(): Promise { - try { - await this.driver?.navigate().refresh(); - } catch (e) { - return Promise.reject(e); - } +export class BrowserStackAutomateSessionGeneratorPlugin extends UiSessionGeneratorPlugin { + override getSession = async (aftCfg?: AftConfig): Promise => { + aftCfg ??= this.aftCfg; + const cfg = aftCfg.getSection(BrowserStackAutomateConfig); + const caps: Capabilities = await this.getCapabilities(aftCfg); + return await new Builder() + .usingServer(cfg.url) + .withCapabilities(caps) + .build(); } - async resize(width: number, height: number): Promise { - try { - await this.driver?.manage().window().setSize(width, height); - } catch (e) { - return Promise.reject(e); - } - } - async dispose(error?: Error): Promise { - if (error) { - await this.logMgr.warn(`Error: SeleniumSession - ${error.message}`); - } - await this.logMgr.trace('shutting down SeleniumSession'); - await this.driver?.quit(); + async getCapabilities(aftCfg?: AftConfig): Promise { + aftCfg ??= this.aftCfg; + const bsc = aftCfg.getSection(BrowserStackConfig); + let capabilities: Capabilities = new Capabilities(); + const platform: UiPlatform = bsc.uiplatform; + capabilities.set('browserstack.user', bsc.username); + capabilities.set('browserstack.key', bsc.accessKey); + capabilities.set('platform', platform.os); + capabilities.set('platform_version', platform.osVersion) + capabilities.set('browserName', platform.browser); + capabilities.set('browser_version', platform.browserVersion); + return capabilities; } } ``` -### Create an `UiFacet` implementation (Selenium) -the `UiFacet` represents a logical container / section of the UI and is responsible for providing a resilient lookup mechanism for sub-facets or individual elements in the UI -```typescript -export type SeleniumFacetOptions = Merge; - -export type WebElementOptions = Merge; +## aftconfig.json keys and values supported by aft-selenium package -export class SeleniumFacet extends UiFacet { - readonly locator: Locator; // overrides 'unknown' type from 'UiFacet' - readonly session: SeleniumSession; // overrides 'UiSession' type from 'UiFacet' - readonly parent: SeleniumFacet; // overrides 'UiFacet' type from 'UiFacet' - async getElements(options: WebElementOptions): Promise { - let elements: WebElement[] - await wait.untilTrue(async () => { - elements = await this.getRoot().then(r => r.findElements(options.locator)); - return elements.length > 0; - }, options.maxWaitMs || 0); - return elements; - } - async getElement(options: WebElementOptions): Promise { - let element: WebElement; - await wait.untilTrue(async () => { - element = await this.getRoot().then(r => r.findElement(options.locator)); - return !!element; - }, options.maxWaitMs || 0); - return element; - } - async getFacet, To extends UiFacetOptions>(facetType: Class, options?: To): Promise { - options = options || {}; - options.parent = options.parent || this; - options.session = options.session || this.session; - options.logMgr = options.logMgr || this.logMgr; - options.maxWaitMs = (options.maxWaitMs === undefined) ? this.maxWaitMs : options.maxWaitMs; - let facet: T = new facetType(options); - return facet; - } - async getRoot(): Promise { - let el: WebElement; - await wait.untilTrue(async () => { - let parent = this.parent; - if (parent) { - let els: WebElement[] = await parent.getRoot() - .then(r => r.findElements(this.locator)); - el = els[this.index]; - } else { - let els: WebElement[] = await this.session.driver.findElements(this.locator)); - el = els[this.index]; - } - if (el) { - return true; +**GridSessionGeneratorPlugin Example using BrowserStack:** +```json +// aftconfig.json +{ + "UiSessionConfig": { + "generatorName": "grid-session-generator-plugin", + "options": { + "url": "https://hub-cloud.browserstack.com/wd/hub", + "capabilities": { + "browserName": "android", + "platformName": "android", + "appium:platformVersion": "13.0", + "appium:deviceName": "Samsung Galaxy S23", + "appium:app": "bs://some-identifier-for-your-uploaded-app", + "bstack:options": { + "userName": "yourBrowserStackUser", + "accessKey": "yourBrowserStackAccessKey", + "debug": true + } } - return false; - }, this.maxWaitMs); - return el; + } } } ``` -## aftconfig.json keys and values supported by aft-ui package -this package is an abstract base to be extended by other packages providing support for UI testing so no configuration is expected. that said, the base options provided for packages extending this one will be: +- **generatorName** - a `string` containing the class name (optionally separated using `-` characters) that is used to get the specific `UiSessionGeneratorPlugin` implementation to be used -**UiSessionGeneratorPlugin** -```json -{ - "uiplatform": "android_11_chrome_99_Google Pixel XL" -} -``` -- **uiplatform** - a `string` of `_` delimited values representing the `OS`, `OS Version`, `Browser`, `Browser Version`, and `Mobile Device` to be used for the UI session. any of the values may be replaced with `+` meaning any value and an empty `uiplatform` is equivalent to a string of `+_+_+_+_+` \ No newline at end of file +> NOTE: if using the `LocalBrowserSessionGeneratorPlugin` you may also need to include npm package references to your Browser Driver package such as `ChromeDriver` \ No newline at end of file diff --git a/packages/aft-ui/package.json b/packages/aft-ui/package.json index 0045cbb2..40321b42 100644 --- a/packages/aft-ui/package.json +++ b/packages/aft-ui/package.json @@ -1,6 +1,6 @@ { "name": "aft-ui", - "version": "9.0.0", + "version": "10.0.0", "description": "Automated Functional Testing (AFT) core package supporting UI testing via plugins", "repository": { "type": "git", @@ -11,8 +11,8 @@ "scripts": { "clean": "rimraf ./dist && rimraf ./.nyc_output && rimraf ./coverage", "build": "npm run clean && tsc --build", - "test": "jasmine-ts ./test/**/*-spec.ts", - "coverage": "nyc npm run test" + "test": "npm run build && jasmine-ts ./test/**/*-spec.ts", + "coverage": "npm run build && nyc jasmine-ts ./test/**/*-spec.ts" }, "keywords": [ "aft", @@ -29,7 +29,7 @@ }, "homepage": "https://github.com/bicarbon8/automated-functional-testing#readme", "dependencies": { - "aft-core": "^9.0.0" + "aft-core": "^10.0.0" }, "devDependencies": { "@types/jasmine": "^3.6.10", diff --git a/packages/aft-ui/src/components/ui-component.ts b/packages/aft-ui/src/components/ui-component.ts new file mode 100644 index 00000000..a11c2373 --- /dev/null +++ b/packages/aft-ui/src/components/ui-component.ts @@ -0,0 +1,50 @@ +import { AftConfig, Class, Func, Reporter, aftConfig } from 'aft-core'; + +export type UiComponentOptions = { + driver: unknown; + + aftCfg?: AftConfig; + locator?: unknown; + parent?: Func>; + reporter?: Reporter; +}; + +/** + * used to encapsulate logical blocks of a UI providing the ability to chain + * element lookups back to a root ancestor meaning that individual locators + * only need to be concerned with elements that exist as a child of the parent + * of this `UiFacet`. this is especially useful when UI elements exist in + * multiple places on a page and you only wish to get one instance in a specific + * location + */ +export abstract class UiComponent { + public readonly aftCfg: AftConfig; + public readonly reporter: Reporter; + + protected readonly _driver: unknown; + protected readonly _parent: Func>; + protected readonly _locator: unknown; + + constructor(options: UiComponentOptions) { + this._driver = options.driver; + this.aftCfg = options.aftCfg ?? aftConfig; + this.reporter ??= options.reporter ?? new Reporter(this.constructor.name, this.aftCfg); + this._parent ??= options.parent; + this._locator ??= options.locator; + } + + abstract get driver(): unknown; + abstract get parent(): Func>; + abstract get locator(): unknown; + + abstract getRoot(): Promise; + + getComponent(componentType: Class, options?: Partial): F { + options ??= {} as UiComponentOptions; + options.driver ??= this.driver; + options.aftCfg ??= this.aftCfg; + options.reporter ??= this.reporter; + options.parent ??= () => this.getRoot(); + return new componentType(options); + } +} \ No newline at end of file diff --git a/packages/aft-ui/src/configuration/ui-platform.ts b/packages/aft-ui/src/configuration/ui-platform.ts deleted file mode 100644 index 0aacbba2..00000000 --- a/packages/aft-ui/src/configuration/ui-platform.ts +++ /dev/null @@ -1,68 +0,0 @@ -export type UiTestPlatformOptions = { - os?: string; - osVersion?: string; - browser?: string; - browserVersion?: string; - deviceName?: string; -}; - -export class UiPlatform { - static ANY: string = '+'; - - readonly os: string; - readonly osVersion: string; - readonly browser: string; - readonly browserVersion: string; - readonly deviceName: string; - - constructor(options?: UiTestPlatformOptions) { - this.os = options?.os; - this.osVersion = options?.osVersion; - this.browser = options?.browser; - this.browserVersion = options?.browserVersion; - this.deviceName = options?.deviceName; - } - - toString(): string { - let str: string = ''; - str += (this.os) ? this.os : UiPlatform.ANY; - str += '_'; - str += (this.osVersion) ? this.osVersion : UiPlatform.ANY; - str += '_'; - str += (this.browser) ? this.browser : UiPlatform.ANY; - str += '_'; - str += (this.browserVersion) ? this.browserVersion : UiPlatform.ANY; - str += '_'; - str += (this.deviceName) ? this.deviceName : UiPlatform.ANY; - return str; - } - - static parse(input: string): UiPlatform { - let os: string; - let osVer: string; - let browser: string; - let browserVer: string; - let devName: string; - - if (input) { - let parts: string[] = input.split('_'); - if (parts.length > 0) { - os = (parts[0] != UiPlatform.ANY) ? parts[0] : null; - } - if (parts.length > 1) { - osVer = (parts[1] != UiPlatform.ANY) ? parts[1] : null; - } - if (parts.length > 2) { - browser = (parts[2] != UiPlatform.ANY) ? parts[2] : null; - } - if (parts.length > 3) { - browserVer = (parts[3] != UiPlatform.ANY) ? parts[3] : null; - } - if (parts.length > 4) { - devName = (parts[4] != UiPlatform.ANY) ? parts[4] : null; - } - } - - return new UiPlatform({os: os, osVersion: osVer, browser: browser, browserVersion: browserVer, deviceName: devName}); - } -} \ No newline at end of file diff --git a/packages/aft-ui/src/configuration/ui-session-config.ts b/packages/aft-ui/src/configuration/ui-session-config.ts new file mode 100644 index 00000000..f291879d --- /dev/null +++ b/packages/aft-ui/src/configuration/ui-session-config.ts @@ -0,0 +1,4 @@ +export class UiSessionConfig { + generatorName: string; + options: Record = {}; +} \ No newline at end of file diff --git a/packages/aft-ui/src/facets/ui-element-options.ts b/packages/aft-ui/src/facets/ui-element-options.ts deleted file mode 100644 index c6e8413a..00000000 --- a/packages/aft-ui/src/facets/ui-element-options.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { RetryBackOffType } from "aft-core"; - -export type UiElementOptions = { - locator: unknown; - maxWaitMs?: number; - retryDelayMs?: number; - retryDelayBackOff?: RetryBackOffType; -}; \ No newline at end of file diff --git a/packages/aft-ui/src/facets/ui-facet.ts b/packages/aft-ui/src/facets/ui-facet.ts deleted file mode 100644 index edde028f..00000000 --- a/packages/aft-ui/src/facets/ui-facet.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { Class, RetryBackOffType, IHasOptions, LogManager, optmgr, rand } from 'aft-core'; -import { UiSession } from '../sessions/ui-session'; -import { UiElementOptions } from './ui-element-options'; - -export type UiFacetOptions = { - index?: number; - locator?: unknown; - parent?: UiFacet; - session?: UiSession; - logMgr?: LogManager; - maxWaitMs?: number; - retryDelayMs?: number; - retryDelayBackOff?: RetryBackOffType; -}; - -export abstract class UiFacet implements IHasOptions { - private _logMgr: LogManager; - private _opts: T; - - constructor(options?: T) { - options = options || {} as T - this._opts = optmgr.process(options); - } - - option(key: K, defaultVal?: V): V { - const result: V = this._opts[key] as V; - return (result === undefined) ? defaultVal : result; - } - - get logMgr(): LogManager { - if (!this._logMgr) { - this._logMgr = this.option('logMgr') || new LogManager({logName: `${this.constructor.name}_${rand.guid}`}); - } - return this._logMgr; - } - - get index(): number { - return this.option('index', 0); - } - - get maxWaitMs(): number { - return this.option('maxWaitMs', 10000); - } - - get retryDelayMs(): number { - return this.option('retryDelayMs', 100); - } - - get retryDelayBackOff(): RetryBackOffType { - return this.option('retryDelayBackOff', 'linear'); - } - - get locator(): unknown { - return this.option('locator'); - } - - get session(): UiSession { - return this.option('session'); - } - - get parent(): UiFacet { - return this.option('parent'); - } - - abstract getElements(options?: UiElementOptions): Promise; - abstract getElement(options?: UiElementOptions): Promise; - abstract getFacet>(facetType: Class, options?: T): Promise; - abstract getRoot(): Promise; -} \ No newline at end of file diff --git a/packages/aft-ui/src/index.ts b/packages/aft-ui/src/index.ts index 1c07c43b..142d9291 100644 --- a/packages/aft-ui/src/index.ts +++ b/packages/aft-ui/src/index.ts @@ -1,9 +1,7 @@ /* configuration */ -export * from './configuration/ui-platform'; -/* facets */ -export * from './facets/ui-facet'; -export * from './facets/ui-element-options'; +export * from './configuration/ui-session-config'; +/* components */ +export * from './components/ui-component'; /* sessions */ export * from './sessions/ui-session-generator-plugin'; -export * from './sessions/ui-session'; export * from './sessions/ui-session-generator-manager'; \ No newline at end of file diff --git a/packages/aft-ui/src/sessions/ui-session-generator-manager.ts b/packages/aft-ui/src/sessions/ui-session-generator-manager.ts index 8e1dc237..002fa4a0 100644 --- a/packages/aft-ui/src/sessions/ui-session-generator-manager.ts +++ b/packages/aft-ui/src/sessions/ui-session-generator-manager.ts @@ -1,71 +1,76 @@ -import { PluginManagerWithLogging, PluginManagerWithLoggingOptions, Merge, PluginConfig } from "aft-core"; -import { UiPlatform } from "../configuration/ui-platform"; -import { UiSession, UiSessionOptions } from "./ui-session"; +import { merge } from "lodash"; +import { AftConfig, Err, Reporter, aftConfig, aftLogger, pluginLoader } from "aft-core"; import { UiSessionGeneratorPlugin } from "./ui-session-generator-plugin"; - -export type UiSessionGeneratorManagerOptions = Merge; +import { UiSessionConfig } from "../configuration/ui-session-config"; /** - * abstract class that should be extended by `PluginManager` instances that manage UI Session Generator Plugins - * configuration options supported by this class are: - * * `platform` - _[optional]_ an string containing any, none or all of the following string values: _os_, _osVersion_, _browser_, _browserVersion_, _deviceName_ - * * `loadWaitDuration` - _[optional]_ a number representing the max milliseconds to wait for a UI element (defaults to 10000 ms) - * * `pluginNames` - an array containing any `UiSessionGeneratorPlugin` implementations to load (NOTE: only the first enabled will be used) - * * `searchDir` - the root directory from which to start searching for plugins (defaults to `process.cwd()`) + * class will get a UI Session Generator Plugin by name listed in `UiSessionConfig.sessionGeneratorName` + * and call it's `getSession` function * ``` * { + * "pluginNames": [ + * "grid-session-generator-plugin", + * "local-browser-session-generator-plugin" + * ] * ... - * "UiSessionGeneratorManagerInstance": { - * "uiplatform": "mac_11_safari", - * "plugins": [{ - * "name": "some-custom-session-plugin", - * "searchDirectory": "../starting/path/to/find/plugin/", - * "options": { - * "uiplatform": "windows_10_chrome_87_Google Pixel XL" + * "UiSessionConfig": { + * "generatorName": "grid-session-generator-plugin", + * "uiplatform": { + * "os": "android", + * "osValue": "13", + * "browser": "chrome", + * "browserVersion": "112", + * "deviceName": "Samsung Galaxy S23" + * }, + * "options": { + * "url": "https://hub-cloud.browserstack.com/wd/hub" + * "capabilities": { + * "browserName": "chrome" + * "bstack:options": { + * "userName": "lkjsdlak", + * "accessKey": "laksdjf12312", + * "debug": true * } - * }] + * } + * } * } * ... * } * ``` */ -export abstract class UiSessionGeneratorManager, Tc extends UiSessionGeneratorManagerOptions> extends PluginManagerWithLogging { - private _uiPlt: UiPlatform; +export class UiSessionGeneratorManager { + public readonly aftCfg: AftConfig; + public readonly plugins: Array; - async uiplatform(): Promise { - if (!this._uiPlt) { - const pltstr = await this.config('uiplatform', '+_+_+_+_+'); - this._uiPlt = UiPlatform.parse(pltstr); - } - return this._uiPlt; + constructor(aftCfg?: AftConfig) { + this.aftCfg = aftCfg ?? aftConfig; + this.plugins = pluginLoader.getPluginsByType(UiSessionGeneratorPlugin, this.aftCfg); } - override async pluginConfigs(): Promise> { - const configs = await this.config('plugins', []); - const updatedConfigs = new Array(); - for (var i=0; i p?.toString()); - cfg.options['logMgr'] = cfg.options['logMgr'] || await this.logMgr(); - updatedConfigs.push(cfg); - } - } - return updatedConfigs; - } - /** - * instantiates a new Session using the 'provider' specified in - * configuration + * instantiates a new Session using the `sessionGeneratorName` specified in + * `UiSessionConfig` */ - abstract newUiSession(options?: UiSessionOptions): Promise>; + async getSession(sessionOptions?: Record): Promise { + const uic = this.aftCfg.getSection(UiSessionConfig); + sessionOptions ??= {}; + sessionOptions = merge(uic.options, sessionOptions); + try { + const plugin = this.plugins.find(p => Err.handle(() => p?.enabled)); + aftLogger.log({ + name: this.constructor.name, + level: 'debug', + message: `using plugin: '${plugin.constructor.name}' to generate new UI session using options: ${JSON.stringify(sessionOptions)}` + }); + return await plugin.getSession(sessionOptions); + } catch (e) { + const err = `unable to generate UI session due to: ${Err.short(e)}`; + aftLogger.log({ + name: this.constructor.name, + level: 'error', + message: err + }); + return Promise.reject(err); + } + } } \ No newline at end of file diff --git a/packages/aft-ui/src/sessions/ui-session-generator-plugin.ts b/packages/aft-ui/src/sessions/ui-session-generator-plugin.ts index 16edf8dd..00f7694e 100644 --- a/packages/aft-ui/src/sessions/ui-session-generator-plugin.ts +++ b/packages/aft-ui/src/sessions/ui-session-generator-plugin.ts @@ -1,27 +1,12 @@ -import { Plugin, LogManager, Merge, PluginOptions } from "aft-core"; -import { UiPlatform } from "../configuration/ui-platform"; -import { UiSession, UiSessionOptions } from "./ui-session"; +import { Plugin, convert } from "aft-core"; +import { UiSessionConfig } from "../configuration/ui-session-config"; -export type UiSessionGeneratorPluginOptions = Merge; - -export abstract class UiSessionGeneratorPlugin extends Plugin { - private _logMgr: LogManager; - private _platform: UiPlatform; - get logMgr(): LogManager { - if (!this._logMgr) { - this._logMgr = this.option('logMgr') || new LogManager({logName: this.constructor.name}); - } - return this._logMgr; - } - get uiplatform(): UiPlatform { - if (!this._platform) { - let plt: string = this.option('uiplatform'); - this._platform = UiPlatform.parse(plt); - } - return this._platform; +export class UiSessionGeneratorPlugin extends Plugin { + override get enabled(): boolean { + const uisc = this.aftCfg.getSection(UiSessionConfig); + const genName = uisc.generatorName; + const safeName = convert.toSafeString(genName, [{exclude: /[-_.\s\d]/gi, replaceWith: ''}]); + return safeName.toLocaleLowerCase() === this.constructor.name.toLocaleLowerCase(); } - abstract newUiSession(options?: UiSessionOptions): Promise>; + getSession = async (sessionOptions?: Record): Promise => null; } \ No newline at end of file diff --git a/packages/aft-ui/src/sessions/ui-session.ts b/packages/aft-ui/src/sessions/ui-session.ts deleted file mode 100644 index 80b90d64..00000000 --- a/packages/aft-ui/src/sessions/ui-session.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { Class, Disposable, LogManager, rand, IHasOptions, optmgr } from "aft-core"; -import { UiPlatform } from "../configuration/ui-platform"; -import { UiFacet, UiFacetOptions } from "../facets/ui-facet"; - -export type UiSessionOptions = { - logMgr?: LogManager; - uiplatform?: string; - driver?: unknown; -}; - -export abstract class UiSession implements IHasOptions, Disposable { - private readonly _options: T; - - private _platform: UiPlatform; - private _logMgr: LogManager; - - constructor(options?: T) { - options = options || {} as T; - this._options = optmgr.process(options); - } - - option(key: K, defaultVal?: V): V { - const result: V = this._options[key] as V; - return (result === undefined) ? defaultVal : result; - } - - abstract readonly driver: unknown; - - get platform(): UiPlatform { - if (!this._platform) { - const pltStr: string = this.option('uiplatform'); - this._platform = UiPlatform.parse(pltStr); - } - return this._platform; - } - - get logMgr(): LogManager { - if (!this._logMgr) { - this._logMgr = this.option('logMgr') || new LogManager({logName: `${this.constructor.name}_${this.platform}_${rand.getString(4, false, true)}`}); - } - return this._logMgr; - } - - abstract getFacet, Fo extends UiFacetOptions>(facetType: Class, options?: Fo): Promise; - abstract dispose(error?: any): Promise; -} \ No newline at end of file diff --git a/packages/aft-ui/test/components/fake-component.ts b/packages/aft-ui/test/components/fake-component.ts new file mode 100644 index 00000000..fc164f10 --- /dev/null +++ b/packages/aft-ui/test/components/fake-component.ts @@ -0,0 +1,21 @@ +import { Func } from "aft-core"; +import { UiComponent } from "../../src"; +import { FakeDriver } from "./fake-driver"; +import { FakeElement } from "./fake-element"; +import { FakeLocator } from "./fake-locator"; + +export class FakeComponent extends UiComponent { + override get driver(): FakeDriver { + return this._driver as FakeDriver; + } + override get parent(): Func> { + return this._parent as Func>; + } + override get locator(): FakeLocator { + return this._locator as FakeLocator; + } + override async getRoot(): Promise { + const searchCtx = (this.parent) ? await this.parent() : this.driver; + return searchCtx.findFakeElement(this.locator); + } +} \ No newline at end of file diff --git a/packages/aft-ui/test/components/fake-driver.ts b/packages/aft-ui/test/components/fake-driver.ts new file mode 100644 index 00000000..85154cc8 --- /dev/null +++ b/packages/aft-ui/test/components/fake-driver.ts @@ -0,0 +1,8 @@ +import { FakeElement } from "./fake-element"; +import { FakeLocator } from "./fake-locator"; + +export class FakeDriver { + findFakeElement(locator: FakeLocator): Promise { + return null; + } +} \ No newline at end of file diff --git a/packages/aft-ui/test/components/fake-element.ts b/packages/aft-ui/test/components/fake-element.ts new file mode 100644 index 00000000..53a50332 --- /dev/null +++ b/packages/aft-ui/test/components/fake-element.ts @@ -0,0 +1,7 @@ +import { FakeLocator } from "./fake-locator"; + +export class FakeElement { + findFakeElement(loc: FakeLocator): Promise { + return null; + } +} \ No newline at end of file diff --git a/packages/aft-ui/test/components/fake-locator.ts b/packages/aft-ui/test/components/fake-locator.ts new file mode 100644 index 00000000..f7fda2a8 --- /dev/null +++ b/packages/aft-ui/test/components/fake-locator.ts @@ -0,0 +1,14 @@ +export class FakeLocator { + public readonly locType: string; + public readonly input: string; + constructor(locType: string, input: string) { + this.locType = locType; + this.input = input; + } + toString() { + return `${this.locType}_${this.input}`; + } +} +export module FakeLocator { + export var fakeLocType = (input: string) => new FakeLocator('fakeLocType', input); +} \ No newline at end of file diff --git a/packages/aft-ui/test/components/ui-component-spec.ts b/packages/aft-ui/test/components/ui-component-spec.ts new file mode 100644 index 00000000..0f9e79d7 --- /dev/null +++ b/packages/aft-ui/test/components/ui-component-spec.ts @@ -0,0 +1,28 @@ +import { Reporter, rand } from "aft-core"; +import { UiComponentOptions } from "../../src"; +import { FakeComponent } from "./fake-component"; +import { FakeElement } from "./fake-element"; +import { FakeDriver } from "./fake-driver"; +import { FakeLocator } from "./fake-locator"; + +describe('UiComponent', () => { + it('can be extended to return specific UiComponent types', async () => { + const mockElement = new FakeElement(); + spyOn(mockElement, 'findFakeElement').and.callFake((l: FakeLocator) => Promise.resolve(mockElement)); + const mockDriver = new FakeDriver(); + spyOn(mockDriver, 'findFakeElement').and.callFake((l: FakeLocator) => Promise.resolve(mockElement)); + const options: UiComponentOptions = { + driver: mockDriver, + locator: FakeLocator.fakeLocType('fake:loc'), + reporter: new Reporter(rand.getString(15)) + }; + const compo = new FakeComponent(options); + + const actual = await compo.getComponent(FakeComponent, {locator: FakeLocator.fakeLocType('new:loc')}); + + expect(actual).toBeDefined(); + expect(actual.locator.input).toEqual('new:loc'); + expect(await actual.parent()).toBe(await compo.getRoot()); + expect(actual.reporter).toBe(compo.reporter); + }); +}); \ No newline at end of file diff --git a/packages/aft-ui/test/configuration/ui-test-platform-spec.ts b/packages/aft-ui/test/configuration/ui-test-platform-spec.ts deleted file mode 100644 index f4bed267..00000000 --- a/packages/aft-ui/test/configuration/ui-test-platform-spec.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { UiPlatform } from "../../src/configuration/ui-platform"; - -describe('UiTestPlatform', () => { - const data: {plt: string, os?: string, osVersion?: string, browser?: string, browserVersion?: string, deviceName?: string}[] = [ - {plt: 'android_11_+_+_Samsung Galaxy S3', os: 'android', osVersion: '11', browser: null, browserVersion: null, deviceName: 'Samsung Galaxy S3'}, - {plt: 'windows_10_chrome_76_Google Pixel 3', os: 'windows', osVersion: '10', browser: 'chrome', browserVersion: '76', deviceName: 'Google Pixel 3'}, - {plt: 'mac_osx_+_+_+', os: 'mac', osVersion: 'osx', browser: null, browserVersion: null, deviceName: null} - ]; - - for (var i=0; i { - const platform: UiPlatform = UiPlatform.parse(d.plt); - - expect(platform).withContext('object').not.toBeUndefined(); - expect(platform.os).withContext('os').toEqual(d.os); - expect(platform.osVersion).withContext('os version').toEqual(d.osVersion); - expect(platform.browser).withContext('browser').toEqual(d.browser); - expect(platform.browserVersion).withContext('browser version').toEqual(d.browserVersion); - expect(platform.deviceName).withContext('device name').toEqual(d.deviceName); - }); - } - - for (var i=0; i { - const platform: UiPlatform = new UiPlatform({ - os: d.os, - osVersion: d.osVersion, - browser: d.browser, - browserVersion: d.browserVersion, - deviceName: d.deviceName - }); - let platformString: string = platform.toString(); - - expect(platformString).toEqual(d.plt); - }); - } - - it('can use UiTestPlatform.ANY as options input', () => { - const platform: UiPlatform = new UiPlatform({ - os: UiPlatform.ANY, - osVersion: UiPlatform.ANY, - browser: UiPlatform.ANY, - browserVersion: UiPlatform.ANY, - deviceName: UiPlatform.ANY - }); - let platformString: string = platform.toString(); - - expect(platformString).toEqual('+_+_+_+_+'); - }); -}); \ No newline at end of file diff --git a/packages/aft-ui/test/facets/fake-facet.ts b/packages/aft-ui/test/facets/fake-facet.ts deleted file mode 100644 index c4c7ab98..00000000 --- a/packages/aft-ui/test/facets/fake-facet.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { FakeWebElement } from "./fake-web-element"; -import { Class, Merge, retry, wait } from "aft-core"; -import { UiElementOptions, UiFacet, UiFacetOptions } from "../../src"; -import { FakeLocator } from "./fake-locator"; -import { FakeSession } from "../sessions/fake-session"; - -export type FakeElementOptions = Merge; - -export type FakeFacetOptions = Merge; - -export class FakeFacet extends UiFacet { - override get parent(): FakeFacet { - return super.parent as FakeFacet; - } - override get locator(): FakeLocator { - return super.locator as FakeLocator; - } - override get session(): FakeSession { - return super.session as FakeSession; - } - override async getRoot(): Promise { - const maxWait = this.maxWaitMs; - const loc = this.locator; - const index = this.index; - const r: FakeWebElement = await retry(() => { - if (this.parent) { - return this.parent.getRoot() - .then(p => p.findElements(loc)[index]); - } - return this.session.driver.findElements(loc)[index]; - }).withStartDelayBetweenAttempts(500) - .withBackOff('linear') - .withMaxDuration(maxWait); - return r; - } - override async getElements(options: FakeElementOptions): Promise { - const duration: number = (options.maxWaitMs === undefined) ? this.maxWaitMs : options.maxWaitMs; - const elements: FakeWebElement[] = await retry(() => { - return this.getRoot() - .then(r => r.findElements(options.locator)); - }).withStartDelayBetweenAttempts(500) - .withBackOff('linear') - .withMaxDuration(duration); - return elements; - } - override async getElement(options: FakeElementOptions): Promise { - const duration: number = (options.maxWaitMs === undefined) ? this.maxWaitMs : options.maxWaitMs; - const element: FakeWebElement = await retry(() => { - return this.getRoot() - .then(r => r.findElement(options.locator)); - }).withStartDelayBetweenAttempts(500) - .withBackOff('linear') - .withMaxDuration(duration); - return element; - } - override async getFacet>(facetType: Class, options?: FakeFacetOptions): Promise { - options = options || {} as FakeFacetOptions; - options.index = options.index || 0; - options.logMgr = options.logMgr || this.logMgr; - options.parent = options.parent || this; - options.session = options.session || this.session; - let facet: F = new facetType(options); - return facet; - } -} \ No newline at end of file diff --git a/packages/aft-ui/test/facets/fake-locator.ts b/packages/aft-ui/test/facets/fake-locator.ts deleted file mode 100644 index 31bc1560..00000000 --- a/packages/aft-ui/test/facets/fake-locator.ts +++ /dev/null @@ -1,20 +0,0 @@ -export class FakeLocator { - readonly using: string; - readonly value: string; - constructor(using: string, value: string) { - this.using = using; - this.value = value; - } - static css(value: string): FakeLocator { - return new FakeLocator('css', value); - } - static id(value: string): FakeLocator { - return new FakeLocator('id', value); - } - static xpath(value: string): FakeLocator { - return new FakeLocator('xpath', value); - } - static magic(value: string): FakeLocator { - return new FakeLocator('magic', value); - } -} \ No newline at end of file diff --git a/packages/aft-ui/test/facets/fake-web-element.ts b/packages/aft-ui/test/facets/fake-web-element.ts deleted file mode 100644 index a75ce09b..00000000 --- a/packages/aft-ui/test/facets/fake-web-element.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { FakeLocator } from "./fake-locator"; - -export class FakeWebElement { - locator: FakeLocator; - enabled: boolean = false; - displayed: boolean = false; - text: string; - elements: FakeWebElement[] = []; - clicks: number = 0; - attributes: Map = new Map(); - async isEnabled(): Promise { - return this.enabled; - } - async isDisplayed(): Promise { - return this.displayed; - } - async getText(): Promise { - return this.text; - } - async sendKeys(input: string): Promise { - this.text = input; - } - async findElements(locator: FakeLocator): Promise { - let elements: FakeWebElement[] = []; - for (var i=0; i { - let elements: FakeWebElement[] = await this.findElements(locator); - if (elements?.length) { - return elements[0]; - } - return Promise.reject('element not found'); - } - async click(): Promise { - this.clicks++; - } - async getAttribute(name: string): Promise { - if (this.attributes.has(name)) { - return this.attributes.get(name); - } - return null; - } -} \ No newline at end of file diff --git a/packages/aft-ui/test/facets/ui-facet-spec.ts b/packages/aft-ui/test/facets/ui-facet-spec.ts deleted file mode 100644 index 7b274bff..00000000 --- a/packages/aft-ui/test/facets/ui-facet-spec.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { LogManager, rand } from "aft-core"; -import { FakeDriver } from "../sessions/fake-driver"; -import { FakeSession } from "../sessions/fake-session"; -import { FakeFacet, FakeFacetOptions } from "./fake-facet"; -import { FakeLocator } from "./fake-locator"; - -describe('UiFacet', () => { - it('can be extended to return specific UiFacet types', async () => { - const options = { - session: new FakeSession({driver: new FakeDriver()}), - index: 0, - locator: FakeLocator.css('fake:loc'), - logMgr: new LogManager({logName: rand.getString(15)}) - } as FakeFacetOptions; - const facet = new FakeFacet(options); - - const actual = await facet.getFacet(FakeFacet, {index: 12, locator: FakeLocator.css('new:loc')}); - - expect(actual).toBeDefined(); - expect(actual.index).toBe(12); - expect(actual.locator).toEqual(FakeLocator.css('new:loc')); - expect(actual.parent).toBe(facet); - expect(actual.session).toBe(facet.session); - expect(actual.logMgr).toBe(facet.logMgr); - }); -}); \ No newline at end of file diff --git a/packages/aft-ui/test/sessions/fake-driver.ts b/packages/aft-ui/test/sessions/fake-driver.ts deleted file mode 100644 index 83a2c018..00000000 --- a/packages/aft-ui/test/sessions/fake-driver.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { FakeWebElement } from "../facets/fake-web-element"; -import { FakeLocator } from "../facets/fake-locator"; - -export class FakeDriver { - elements: FakeWebElement[] = []; - async findElements(locator: FakeLocator): Promise { - let elements: FakeWebElement[] = []; - for (var i=0; i { - let elements: FakeWebElement[] = await this.findElements(locator); - if (elements?.length) { - return elements[0]; - } - return Promise.reject('element not found'); - } - async refresh(): Promise { - return Promise.resolve(); - } - async resize(width: number, height: number): Promise { - return Promise.resolve(); - } - async get(): Promise { - return Promise.resolve(); - } -} \ No newline at end of file diff --git a/packages/aft-ui/test/sessions/fake-session-generator-manager.ts b/packages/aft-ui/test/sessions/fake-session-generator-manager.ts deleted file mode 100644 index 69d1cbde..00000000 --- a/packages/aft-ui/test/sessions/fake-session-generator-manager.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { UiSessionGeneratorManager, UiSessionGeneratorManagerOptions } from "../../src"; -import { FakeSession, FakeSessionOptions } from "./fake-session"; -import { FakeSessionGeneratorPlugin } from "./fake-session-generator-plugin"; - -export type FakeSessionGeneratorManagerOptions = UiSessionGeneratorManagerOptions; - -export class FakeSessionGeneratorManager extends UiSessionGeneratorManager { - async newUiSession(options?: FakeSessionOptions): Promise { - return await this.first() - .then((p: FakeSessionGeneratorPlugin) => p?.newUiSession(options) - .catch(async (err) => { - await this.logMgr().then((l) => l.warn(`unable to call '${p?.constructor.name || 'unknown'}.newUiDriver' due to: ${err}`)); - return null; - })) - .catch(async (err) => { - await this.logMgr().then((l) => l.warn(`unable to call newUiDriver due to: ${err}`)); - return null; - }); - } -} \ No newline at end of file diff --git a/packages/aft-ui/test/sessions/fake-session-generator-plugin-throws.ts b/packages/aft-ui/test/sessions/fake-session-generator-plugin-throws.ts index cc085a10..b6e2ee6c 100644 --- a/packages/aft-ui/test/sessions/fake-session-generator-plugin-throws.ts +++ b/packages/aft-ui/test/sessions/fake-session-generator-plugin-throws.ts @@ -1,9 +1,7 @@ -import { UiSessionGeneratorPlugin } from "../../src/sessions/ui-session-generator-plugin"; -import { FakeSessionGeneratorPluginOptions } from "./fake-session-generator-plugin"; -import { FakeSession, FakeSessionOptions } from "./fake-session"; +import { UiSessionGeneratorPlugin } from "../../src"; -export class FakeSessionGeneratorPluginThrows extends UiSessionGeneratorPlugin { - override async newUiSession(options?: FakeSessionOptions): Promise { - throw new Error(`error in ${this.constructor.name}`); +export class FakeSessionGeneratorPluginThrows extends UiSessionGeneratorPlugin { + override getSession = async (sessionOptions?: Record): Promise => { + throw 'fake-exception'; } } \ No newline at end of file diff --git a/packages/aft-ui/test/sessions/fake-session-generator-plugin.ts b/packages/aft-ui/test/sessions/fake-session-generator-plugin.ts index c9f95c43..97463dc5 100644 --- a/packages/aft-ui/test/sessions/fake-session-generator-plugin.ts +++ b/packages/aft-ui/test/sessions/fake-session-generator-plugin.ts @@ -1,18 +1,11 @@ -import { UiSession, UiSessionGeneratorPlugin, UiSessionGeneratorPluginOptions } from "../../src"; -import { FakeDriver } from "./fake-driver"; -import { FakeSession, FakeSessionOptions } from "./fake-session"; - -export type FakeSessionGeneratorPluginOptions = UiSessionGeneratorPluginOptions; - -export class FakeSessionGeneratorPlugin extends UiSessionGeneratorPlugin { - async getDriver(): Promise { - return new FakeDriver(); - } - - override async newUiSession(options?: FakeSessionOptions): Promise { - options = options || {} as FakeSessionOptions; - options.logMgr = options.logMgr || this.logMgr; - options.driver = options.driver || await this.getDriver(); - return new FakeSession(options); - } +import { UiSessionConfig, UiSessionGeneratorPlugin } from "../../src"; + +export class FakeSessionGeneratorPlugin extends UiSessionGeneratorPlugin { + override getSession = async (sessionOptions?: Record): Promise => { + const uisc = this.aftCfg.getSection(UiSessionConfig); + return { + foo: 'bar', + opts: sessionOptions + }; + } } \ No newline at end of file diff --git a/packages/aft-ui/test/sessions/fake-session.ts b/packages/aft-ui/test/sessions/fake-session.ts deleted file mode 100644 index c996b106..00000000 --- a/packages/aft-ui/test/sessions/fake-session.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { FakeDriver } from "./fake-driver"; -import { Class, Merge } from "aft-core"; -import { UiFacet, UiFacetOptions, UiSession, UiSessionOptions } from "../../src"; - -export type FakeSessionOptions = Merge; - -export class FakeSession extends UiSession { - disposeCount: number; - disposeErrors: Error[]; - goToStrings: string[]; - refreshCount: number; - resizeValues: object[]; - - private _driver: FakeDriver; - - get driver(): FakeDriver { - if (!this._driver) { - this._driver = this.option('driver'); - } - return this._driver; - } - - override async getFacet, Fo extends UiFacetOptions>(facetType: Class, options?: Fo): Promise { - options = options || {} as Fo; - options.index = options.index || 0; - options.session = options.session || this; - options.logMgr = options.logMgr || this.logMgr; - let facet: F = new facetType(options); - return facet; - } - async goTo(url: string): Promise { - this.goToStrings.push(url); - return this; - } - async refresh(): Promise { - this.refreshCount++; - return this; - } - async resize(width: number, height: number): Promise { - this.resizeValues.push({w: width, h: height}); - return this; - } - async dispose(err?: Error): Promise { - this.disposeCount++; - this.disposeErrors.push(err); - } -} \ No newline at end of file diff --git a/packages/aft-ui/test/sessions/test-data-helper.ts b/packages/aft-ui/test/sessions/test-data-helper.ts deleted file mode 100644 index 5e5c1b80..00000000 --- a/packages/aft-ui/test/sessions/test-data-helper.ts +++ /dev/null @@ -1,21 +0,0 @@ -export class TestDataHelper { - private readonly _data: Map; - - constructor() { - this._data = new Map(); - } - - set(key: string, val: any) { - this._data.set(key, val); - } - - get(key: string): T { - return this._data.get(key) as T; - } - - reset(): void { - this._data.clear(); - } -} - -export const testdata = new TestDataHelper(); \ No newline at end of file diff --git a/packages/aft-ui/test/sessions/ui-session-generator-manager-spec.ts b/packages/aft-ui/test/sessions/ui-session-generator-manager-spec.ts index 6a36431c..16383e7f 100644 --- a/packages/aft-ui/test/sessions/ui-session-generator-manager-spec.ts +++ b/packages/aft-ui/test/sessions/ui-session-generator-manager-spec.ts @@ -1,62 +1,54 @@ -import { pluginloader, rand } from "aft-core"; -import { UiPlatform } from "../../src"; -import { FakeSessionGeneratorManager, FakeSessionGeneratorManagerOptions } from "./fake-session-generator-manager"; +import { AftConfig, pluginLoader } from "aft-core"; +import { UiSessionGeneratorManager, UiSessionGeneratorPlugin } from "../../src"; +import { FakeSessionGeneratorPlugin } from "./fake-session-generator-plugin"; + +const consolelog = console.log; describe('UiSessionGeneratorManager', () => { - beforeEach(() => { - pluginloader.clear(); + beforeAll(() => { + console.log = (...args: any[]) => null; }); - it('can be extended by a class instance', async () => { - const config = { - logName: rand.getString(25), - plugins: ['fake-session-generator-plugin'] - }; - const manager = new FakeSessionGeneratorManager(config); - - expect(manager).toBeDefined(); - expect(await manager.logMgr().then((l) => l.logName)).toEqual(config.logName); - expect(await manager.first().then((f) => f.constructor.name)).toEqual('FakeSessionGeneratorPlugin'); - expect(await manager.newUiSession()).toBeDefined(); + beforeEach(() => { + pluginLoader.reset(); }); - it('can handle a defective plugin', async () => { - const config = { - plugins: ['fake-session-generator-plugin-throws'] - } as FakeSessionGeneratorManagerOptions; - const manager = new FakeSessionGeneratorManager(config); - - expect(manager).toBeDefined(); - expect(await manager.logMgr().then((l) => l.logName)).toEqual(manager.constructor.name); - expect(await manager.first().then((f) => f.constructor.name)).toEqual('FakeSessionGeneratorPluginThrows'); - expect(await manager.newUiSession()).toBeNull(); + afterAll(() => { + console.log = consolelog; }); - it('sets the uiplatform if the plugin options does not already set it', async () => { - const plt = UiPlatform.parse('android_12_chrome_79_Google Pixel XL'); - const manager = new FakeSessionGeneratorManager({ - uiplatform: plt.toString(), - plugins: ['fake-session-generator-plugin'] + it('will get only specified plugin for use', async () => { + const aftCfg = new AftConfig({ + pluginNames: [ + 'fake-session-generator-plugin-throws', + 'fake-session-generator-plugin' + ], + UiSessionConfig: { + generatorName: 'fake-session-generator-plugin' + } }); + const manager = new UiSessionGeneratorManager(aftCfg); - const plugin = await manager.first(); - expect(plugin.uiplatform.toString()).toEqual(plt.toString()); + expect(manager).toBeDefined(); + expect(manager.plugins.length).toBe(2); + const enabled: Array = manager.plugins.filter(p => p.enabled); + expect(enabled.length).toBe(1); + expect(enabled[0].constructor.name).toEqual(FakeSessionGeneratorPlugin.name); + expect(await manager.getSession()).not.toBeNull(); }); - it('does not set the uiplatform if the plugin options set it', async () => { - const plt = UiPlatform.parse('android_12_chrome_79_Google Pixel XL'); - const expected = 'windows_10_firefox_88_+'; - const manager = new FakeSessionGeneratorManager({ - uiplatform: plt.toString(), - plugins: [{ - name: 'fake-session-generator-plugin', - options: { - uiplatform: expected - } - }] + it('rejects with error if plugin unable to getSession', async () => { + const aftCfg = new AftConfig({ + pluginNames: ['fake-session-generator-plugin-throws'], + UiSessionConfig: { + generatorName: 'fake-session-generator-plugin-throws' + } }); + const manager = new UiSessionGeneratorManager(aftCfg); - const plugin = await manager.first(); - expect(plugin.uiplatform.toString()).toEqual(expected); + expect(manager).toBeDefined(); + await manager.getSession().catch((err) => { + expect(err).toMatch(/.*(unable to generate UI session due to:).*/); + }); }); }); \ No newline at end of file diff --git a/packages/aft-ui/test/sessions/ui-session-generator-plugin-spec.ts b/packages/aft-ui/test/sessions/ui-session-generator-plugin-spec.ts deleted file mode 100644 index a20099a3..00000000 --- a/packages/aft-ui/test/sessions/ui-session-generator-plugin-spec.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { FakeDriver } from "./fake-driver"; -import { FakeWebElement } from "../facets/fake-web-element"; -import { FakeLocator } from "../facets/fake-locator"; -import { FakeSessionGeneratorPlugin } from "./fake-session-generator-plugin"; -import { FakeSession } from "./fake-session"; - -describe('UiSessionGeneratorPlugin', () => { - it('can return specified type of driver from the driver plugin', async () => { - let fwe: FakeWebElement = new FakeWebElement(); - fwe.locator = FakeLocator.css('fake'); - let fd: FakeDriver = new FakeDriver(); - fd.elements.push(fwe); - let fsp: FakeSessionGeneratorPlugin = new FakeSessionGeneratorPlugin(); - - let actual: FakeSession = await fsp.newUiSession(); - let elements: FakeWebElement[] = await actual.driver.findElements(fwe.locator); - - expect(actual).toBeDefined(); - expect(actual.driver.constructor.name).toEqual('FakeDriver'); - expect(elements).toBeDefined(); - expect(elements.length).toBe(0); - }); -}); \ No newline at end of file diff --git a/packages/aft-ui/test/sessions/ui-session-spec.ts b/packages/aft-ui/test/sessions/ui-session-spec.ts deleted file mode 100644 index 9ab36f00..00000000 --- a/packages/aft-ui/test/sessions/ui-session-spec.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { FakeFacet, FakeFacetOptions } from "../facets/fake-facet"; -import { FakeLocator } from "../facets/fake-locator"; -import { FakeDriver } from "./fake-driver"; -import { FakeSession, FakeSessionOptions } from "./fake-session"; - -describe('UiSession', () => { - it('can be overridden to return specified UiFacet types', async () => { - const fakeDriver = new FakeDriver(); - const options = { - driver: fakeDriver, - } as FakeSessionOptions; - const session = new FakeSession(options); - - const actual = await session.getFacet(FakeFacet, {locator: FakeLocator.css('fake:loc')}); - - expect(actual).toBeDefined(); - expect(actual.constructor.name).toEqual('FakeFacet'); - expect(actual.session).toBe(session); - expect(actual.locator).toBeDefined(); - expect(actual.logMgr).toBe(session.logMgr); - expect(actual.index).toBe(0); - }); -}); \ No newline at end of file diff --git a/packages/aft-web-services/README.md b/packages/aft-web-services/README.md index df0ce6d7..ebf81f3a 100644 --- a/packages/aft-web-services/README.md +++ b/packages/aft-web-services/README.md @@ -21,7 +21,7 @@ let respObj: ListUsersResponse = httpData.as(response); let response: HttpResponse = await httpService.performRequest({ url: 'https://reqres.in/api/users', method: 'POST', - headers: {'content-type':'application/json'}, + headers: {...HttpHeaders.ContentType.get(HttpHeaders.MimeType.applicationJson)}, postData: JSON.stringify({name: 'morpheus', job: 'leader'}) }); @@ -30,7 +30,7 @@ let respObj: CreateUserResponse = httpData.as(response); ``` ## Advantages -- using this package automatically logs the request and response details using a `aft-core.LogManager` that can be passed in as part of the `HttpRequest` to maintain the same `logName` within a single test +- using this package can automatically log the request and response details using a `aft-core.Reporter` that can be passed in as part of the `HttpRequest` to maintain the same `logName` within a single test - the `aft-web-services` classes rely on asynchronous promises meaning no worrying about callbacks - built-in support for redirects (HTTP Status Code 302) and http or https requests - XML and JSON response data can be easily deserialised to objects using the `httpData.as(response: HttpResponse)` function diff --git a/packages/aft-web-services/aftconfig.json b/packages/aft-web-services/aftconfig.json index 26cdc042..efa9b649 100644 --- a/packages/aft-web-services/aftconfig.json +++ b/packages/aft-web-services/aftconfig.json @@ -1,5 +1,5 @@ { - "logmanager": { + "Reporter": { "pluginNames": [], "level": "info" } diff --git a/packages/aft-web-services/package.json b/packages/aft-web-services/package.json index 41b12d2f..95064b52 100644 --- a/packages/aft-web-services/package.json +++ b/packages/aft-web-services/package.json @@ -1,6 +1,6 @@ { "name": "aft-web-services", - "version": "9.0.0", + "version": "10.0.0", "description": "Automated Functional Testing (AFT) module for testing web services over HTTP and HTTPS", "repository": { "type": "git", @@ -11,8 +11,8 @@ "scripts": { "clean": "rimraf ./dist && rimraf ./.nyc_output && rimraf ./coverage", "build": "npm run clean && tsc --build", - "test": "jasmine-ts ./test/**/*-spec.ts", - "coverage": "nyc npm run test" + "test": "npm run build && jasmine-ts ./test/**/*-spec.ts", + "coverage": "npm run build && nyc jasmine-ts ./test/**/*-spec.ts" }, "keywords": [ "aft", @@ -30,7 +30,7 @@ }, "homepage": "https://github.com/bicarbon8/automated-functional-testing#readme", "dependencies": { - "aft-core": "^9.0.0", + "aft-core": "^10.0.0", "form-data": "^4.0.0", "xmldom": "^0.6.0" }, diff --git a/packages/aft-web-services/src/http/http-custom-types.ts b/packages/aft-web-services/src/http/http-custom-types.ts index 62fcb5ca..063113a6 100644 --- a/packages/aft-web-services/src/http/http-custom-types.ts +++ b/packages/aft-web-services/src/http/http-custom-types.ts @@ -1,4 +1,4 @@ -import { LogManager } from "aft-core"; +import { Reporter } from "aft-core"; import { IncomingHttpHeaders, OutgoingHttpHeaders } from "http"; export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'UPDATE' | 'DELETE'; @@ -28,7 +28,7 @@ export type HttpRequest = { method?: HttpMethod; postData?: any; multipart?: boolean; - logMgr?: LogManager; + reporter?: Reporter; }; /** diff --git a/packages/aft-web-services/src/http/http-headers.ts b/packages/aft-web-services/src/http/http-headers.ts new file mode 100644 index 00000000..294ebf87 --- /dev/null +++ b/packages/aft-web-services/src/http/http-headers.ts @@ -0,0 +1,127 @@ +import { convert } from "aft-core"; + +/** + * a module containing helper const and functions to generate + * HTTP headers that can then be appended to your header object using: + * ```typescript + * const headers = { + * ...HttpHeaders.Authorization.basic('myUsername', 'myPassword'), + * ...HttpHeaders.ContentType.get(HttpHeaders.MimeType.applicationJson) + * ...HttpHeaders.Cookies.setCookie({ + * key: 'foo', + * val: 'bar', + * expiration: new Date().toString('u'), + * secure: true, + * httpOnly: true + * }) + * }; + * ``` + */ +export module HttpHeaders { + export module MimeType { + export const applicationOctetstream = 'application/octet-stream'; + export const textPlain = 'text/plain'; + export const textCss = 'text/css'; + export const textHtml = 'text/html'; + export const textXml = 'text/xml'; + export const textJavascript = 'text/javascript'; + export const multipartFormData = 'multipart/form-data'; + export const applicationJson = 'application/json'; + } + export module ContentType { + export type CT = { + "Content-Type": string + }; + export function get(mimeType: string): CT { + return { + "Content-Type": mimeType + }; + } + } + export module Accept { + export type Acc = { + "Accept": string + }; + export function get(mimeType: string): Acc { + return { + Accept: mimeType + }; + } + } + export module Authorization { + export type Auth = { + Authorization: string; + }; + export function basic(username: string, password: string): Auth { + return { + Authorization: `Basic ${convert.toBase64Encoded(`${username}:${password}`)}` + }; + } + export type DigestOptions = { + username: string; + realm: string; + uri: string; + algorithm: string; + nonce: string; + nc: string; + cnonce: string; + qop: string; + response: string; + opaque: string; + } + export function digest(options: Partial): Auth { + const authData = new Array(); + if (options?.username) { authData.push(`username=${options.username}`); } + if (options?.realm) { authData.push(`realm=${options.realm}`); } + if (options?.uri) { authData.push(`uri=${options.uri}`); } + if (options?.algorithm) { authData.push(`algorithm=${options.algorithm}`); } + if (options?.nonce) { authData.push(`nonce=${options.nonce}`); } + if (options?.nc) { authData.push(`nc=${options.nc}`); } + if (options?.cnonce) { authData.push(`cnonce=${options.cnonce}`); } + if (options?.qop) { authData.push(`qop=${options.qop}`); } + if (options?.response) { authData.push(`response=${options.response}`); } + if (options?.opaque) { authData.push(`opaque=${options.opaque}`); } + return { + Authorization: `Digest ${authData.join(', ')}` + }; + } + } + export module Cookies { + export type Cookie = { + Cookie: string + }; + export type SetCookie = { + "Set-Cookie": string + }; + export type SetCookieOptions = { + key: string; + val: string; + expires?: string; + secure?: boolean; + httpOnly?: boolean; + } + export function cookie(...cookies: Array>): Cookie { + const cookieStrings = new Array(); + for (let c of cookies) { + if (c.key && c.val) { + cookieStrings.push(`${c.key}=${c.val}`); + } + } + return { + Cookie: `${cookieStrings.join('; ')}` + } + } + export function setCookie(cookie: SetCookieOptions): SetCookie { + const valsArr = new Array(); + if (cookie.key && cookie.val) { + valsArr.push(`${cookie.key}=${cookie.val}`); + if (cookie.expires) { valsArr.push(`Expires=${cookie.expires}`); } + if (cookie.secure) { valsArr.push('Secure'); } + if (cookie.httpOnly) { valsArr.push('HttpOnly'); } + } + return { + "Set-Cookie": `${valsArr.join('; ')}` + } + } + } +} \ No newline at end of file diff --git a/packages/aft-web-services/src/http/http-service.ts b/packages/aft-web-services/src/http/http-service.ts index ba60e311..de80bde1 100644 --- a/packages/aft-web-services/src/http/http-service.ts +++ b/packages/aft-web-services/src/http/http-service.ts @@ -1,17 +1,18 @@ -import { cfgmgr, IConfigProvider, IHasConfig, IHasOptions, optmgr } from "aft-core"; import * as http from 'http'; import * as https from 'https'; import * as FormData from "form-data"; import { HttpMethod, HttpRequest, HttpResponse } from "./http-custom-types"; +import { AftConfig, aftConfig, aftLogger } from 'aft-core'; +import { OutgoingHttpHeaders } from 'http2'; -export type HttpServiceOptions = { - defaultUrl?: string; - defaultHeaders?: object; - defaultMethod?: string; - defaultAllowRedirect?: boolean; - defaultPostData?: string; - defaultMultipart?: boolean; -}; +export class HttpServiceConfig { + defaultUrl: string = 'http://127.0.0.1'; + defaultHeaders: OutgoingHttpHeaders = {}; + defaultMethod: HttpMethod = 'GET'; + defaultAllowRedirect: boolean = true; + defaultPostData: string; + defaultMultipart: boolean = false; +} /** * supports performing requests over http / https returning the response as a @@ -46,25 +47,11 @@ export type HttpServiceOptions = { * }); * ``` */ -export class HttpService implements IHasConfig, IHasOptions { - private _config: IConfigProvider; - private _opts: HttpServiceOptions; - - constructor(options?: HttpServiceOptions) { - options = options || {} as HttpServiceOptions; - this._opts = optmgr.process(options); - } - - option(key: K, defaultVal?: V): V { - const result: V = this._opts[key] as V; - return (result === undefined) ? defaultVal : result; - } +export class HttpService { + private readonly aftCfg: AftConfig; - config(key: K, defaultVal?: V): Promise { - if (!this._config) { - this._config = cfgmgr.get(this.constructor.name, this._opts); - } - return this._config.get(key, defaultVal); + constructor(aftCfg?: AftConfig) { + this.aftCfg = aftCfg ?? aftConfig; } /** @@ -105,12 +92,30 @@ export class HttpService implements IHasConfig, IHasOptions< try { req = await this.setRequestDefaults(req); - await req.logMgr?.debug(`issuing '${req.method}' request to '${req.url}' with post body '${req.postData}' and headers '${JSON.stringify(req.headers)}'.`); + let logMessage = `issuing '${req.method}' request to '${req.url}' with post body '${req.postData}' and headers '${JSON.stringify(req.headers)}'.`; + if (req.reporter) { + await req.reporter.debug(logMessage); + } else { + aftLogger.log({ + name: this.constructor.name, + level: 'debug', + message: logMessage + }); + } const message = await this._request(req); const resp = await this._response(message, req.allowAutoRedirect); - await req.logMgr?.debug(`received response data of '${resp?.data}' and headers '${JSON.stringify(resp?.headers)}'.`) + logMessage = `received response data of '${resp?.data}' and headers '${JSON.stringify(resp?.headers)}'.`; + if (req.reporter) { + await req.reporter.debug(logMessage); + } else { + aftLogger.log({ + name: this.constructor.name, + level: 'debug', + message: logMessage + }); + } return resp; } catch (e) { @@ -119,13 +124,14 @@ export class HttpService implements IHasConfig, IHasOptions< } private async setRequestDefaults(req?: HttpRequest): Promise { + const hsc = this.aftCfg.getSection(HttpServiceConfig) req ??= {} as HttpRequest; - req.url ??= await this.config('defaultUrl', 'http://127.0.0.1'); - req.headers ??= await this.config('defaultHeaders', {}); - req.method ??= await this.config('defaultMethod', 'GET'); - req.allowAutoRedirect ??= await this.config('defaultAllowRedirect', true); - req.postData ??= await this.config('defaultPostData'); - req.multipart ??= await this.config('defaultMultipart', false); + req.url ??= hsc.defaultUrl; + req.headers ??= hsc.defaultHeaders ?? {}; + req.method ??= hsc.defaultMethod; + req.allowAutoRedirect ??= hsc.defaultAllowRedirect; + req.postData ??= hsc.defaultPostData; + req.multipart ??= hsc.defaultMultipart; return req; } @@ -213,7 +219,7 @@ export class HttpService implements IHasConfig, IHasOptions< * await httpService.performRequest({ * url: 'https://some.domain/path', * allowAutoRedirect: false, - * headers: {"Authorization": "basic AS0978FASLKLJA/=="}, + * headers: {...HttpHeaders.Authorization.basic('myUser', 'myPass')}, * method: 'POST', * postData: someObject, * multipart: false @@ -222,10 +228,11 @@ export class HttpService implements IHasConfig, IHasOptions< * or multipart post as: * ```typescript * let formData = new FormData(); - * formData.append("Authorization": "basic AS0978FASLKLJA/=="); + * formData.append('file', fs.createReadStream('/path/to/file.ext')); * await httpService.performRequest({ * url: 'https://some.domain/path', * allowAutoRedirect: false, + * headers: {...HttpHeaders.Authorization.basic('myUser', 'myPass')} * method: 'POST', * postData: formData, * multipart: true diff --git a/packages/aft-web-services/src/index.ts b/packages/aft-web-services/src/index.ts index 02bb7080..df9827b3 100644 --- a/packages/aft-web-services/src/index.ts +++ b/packages/aft-web-services/src/index.ts @@ -3,4 +3,5 @@ export * from './helpers/xml'; /** http */ export * from './http/http-custom-types'; export * from './http/http-data'; -export { httpService } from './http/http-service'; \ No newline at end of file +export * from './http/http-headers'; +export * from './http/http-service'; \ No newline at end of file diff --git a/packages/aft-web-services/test/http/http-service-spec.ts b/packages/aft-web-services/test/http/http-service-spec.ts index c4768040..e1d548fa 100644 --- a/packages/aft-web-services/test/http/http-service-spec.ts +++ b/packages/aft-web-services/test/http/http-service-spec.ts @@ -1,7 +1,7 @@ -import { convert, rand, retry } from "aft-core"; +import { AftConfig, convert, rand, retry } from "aft-core"; import * as FormData from "form-data"; import { httpService, HttpRequest, HttpResponse, httpData } from "../../src"; -import { HttpService } from "../../src/http/http-service"; +import { HttpService, HttpServiceConfig } from "../../src/http/http-service"; describe('HttpService', () => { it('will set default request values if not passed in to performRequest', async () => { @@ -23,14 +23,16 @@ describe('HttpService', () => { }); it('can override default request values via constructor options if not passed in to performRequest', async () => { - const options = { - defaultUrl: 'https://fake.url/test', - defaultHeaders: {"Authorization": "basic a098dfasd09/=="}, - defaultAllowRedirect: true, - defaultMethod: 'DELETE', - defaultPostData: 'some-fake-post-data' - }; - let svc: HttpService = new HttpService(options); + const aftCfg = new AftConfig({ + HttpServiceConfig: { + defaultUrl: 'https://fake.url/test', + defaultHeaders: {"Authorization": "basic a098dfasd09/=="}, + defaultAllowRedirect: true, + defaultMethod: 'DELETE', + defaultPostData: 'some-fake-post-data' + } + }); + let svc: HttpService = new HttpService(aftCfg); let actual: HttpRequest; spyOn(svc, '_request').and.callFake((req: HttpRequest) => { actual = req; @@ -38,13 +40,13 @@ describe('HttpService', () => { spyOn(svc, '_response').and.returnValue({}); await svc.performRequest(); - + const hsc = aftCfg.getSection(HttpServiceConfig); expect(actual).toBeDefined(); - expect(actual.url).toEqual(options.defaultUrl); - expect(actual.headers).toEqual(options.defaultHeaders); - expect(actual.allowAutoRedirect).toEqual(options.defaultAllowRedirect); - expect(actual.method).toEqual(options.defaultMethod); - expect(actual.postData).toEqual(options.defaultPostData); + expect(actual.url).toEqual(hsc.defaultUrl); + expect(actual.headers).toEqual(hsc.defaultHeaders); + expect(actual.allowAutoRedirect).toEqual(hsc.defaultAllowRedirect); + expect(actual.method).toEqual(hsc.defaultMethod); + expect(actual.postData).toEqual(hsc.defaultPostData); }); it('can send GET request', async () => { diff --git a/tsconfig.json b/tsconfig.json index 59cad8d9..c6552c7a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,14 +3,14 @@ { "path": "./packages/aft-core" }, { "path": "./packages/aft-examples" }, { "path": "./packages/aft-jasmine-reporter" }, - { "path": "./packages/aft-logging-awskinesis" }, - { "path": "./packages/aft-logging-filesystem" }, - { "path": "./packages/aft-logging-html" }, + { "path": "./packages/aft-reporting-aws-kinesis-firehose" }, + { "path": "./packages/aft-reporting-filesystem" }, + { "path": "./packages/aft-reporting-html" }, { "path": "./packages/aft-mocha-reporter" }, { "path": "./packages/aft-testrail" }, { "path": "./packages/aft-ui" }, - { "path": "./packages/aft-ui-browsers" }, - { "path": "./packages/aft-ui-mobile-apps" }, + { "path": "./packages/aft-ui-selenium" }, + { "path": "./packages/aft-ui-webdriverio" }, { "path": "./packages/aft-web-services" } ], "files": []