diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml new file mode 100644 index 0000000..daefe93 --- /dev/null +++ b/.github/workflows/run_tests.yml @@ -0,0 +1,112 @@ +name: run_api_tests + +on: + push: + branches-ignore: + - "**" + # Remove the line above to run when pushing to master + pull_request: + branches: [ main, dev ] + repository_dispatch: + types: [ run_api_tests ] + schedule: + - cron: "0 0 * * 0" # Runs every day at midnight (UTC) + +jobs: + UnitTest: + name: Unit Test Cases + runs-on: ubuntu-latest + + steps: + - name: Checkout Code + uses: actions/checkout@v3 + with: + # Full git history is needed to get a proper list of changed files within `super-linter` + fetch-depth: 0 + + - name: Install npm dependencies + run: npm install + + - name: Determine output folder + id: set_output_folder + run: | + # For pull_request events, use the base branch; otherwise use the current branch reference + if [[ $GITHUB_EVENT_NAME == "pull_request" ]]; then + branch_name=$GITHUB_BASE_REF + else + branch_name=$GITHUB_REF_NAME + fi + + if [[ $branch_name == "main" ]]; then + echo "output_folder=stage" >> $GITHUB_ENV + elif [[ $branch_name == "dev" ]]; then + echo "output_folder=dev" >> $GITHUB_ENV + else + echo "Unknown branch: $branch_name" + exit 1 + fi + + - name: Create env file + run: | + # For pull requests, choose the env file based on the base branch + if [ "${{ github.event_name }}" = "pull_request" ]; then + if [ "${{ github.event.pull_request.base.ref }}" = "main" ]; then + echo "${{ secrets.STAGE_ENV_FILE }}" > .env + else + echo "${{ secrets.ENV_FILE }}" > .env + fi + else + # For non-PR events (push, schedule, repository_dispatch), use the stage env file + echo "${{ secrets.STAGE_ENV_FILE }}" > .env + fi + + - name: Set TIMESTAMP + run: | + # Save the timestamp as an environment variable for reuse in subsequent steps. + echo "TIMESTAMP=$(date '+%d.%m.%Y_%H.%M.%S')" >> $GITHUB_ENV + + - name: Run tests with coverage + run: | + # Use the TIMESTAMP variable from the environment. + mkdir -p test_results + log_file="test_results/${TIMESTAMP}_report.log" + echo -e "\nTest Cases Report\n" >> "$log_file" + # Run the tests and append output to the log file + npm run test >> "$log_file" 2>&1 + # Copy and rename the generated test report with the timestamp + cp test-report.html test_results/test-report_${TIMESTAMP}.html + + - name: Set Date Folder + run: | + DATE_FOLDER=$(date '+%d.%m.%Y') + echo "date_folder=${DATE_FOLDER}" >> $GITHUB_ENV + + - name: Upload report to Azure + uses: LanceMcCarthy/Action-AzureBlobUpload@v2 + with: + source_folder: 'test_results' + destination_folder: '${{ env.date_folder }}' + connection_string: ${{ secrets.AZURE_STORAGE_CONNECTION_STRING }} + container_name: 'api-tester' + clean_destination_folder: false + delete_if_exists: false + + - name: send email notification + if: always() + uses: dawidd6/action-send-mail@v3 + with: + server_address: smtp.gmail.com + server_port: 587 + username: ${{ secrets.EMAIL_USER }} + password: ${{ secrets.EMAIL_PASSWORD }} + subject: ${{ job.status }} - API Testing Report | ${{ github.event_name == 'pull_request' && format('{0}-{1}', 'PR', github.event.pull_request.title) || 'Triggered via Schema Changed' }} + to: gs-tdei-coreteam@gaussiansolutions.com + cc: sureshd@gaussiansolutions.com + bcc: rakeshd@gaussiansolutions.com, sujatam@gaussiansolutions.com + from: Workflow Notification + attachments: test-report.html + html_body: | +

API Testing Report

+

Workflow: ${{ github.workflow }}

+

Repository: ${{ github.repository }}

+ ${{ github.event_name == 'pull_request' && format('

Pull Request: {1}

', github.event.pull_request.html_url, github.event.pull_request.title) || '
' }} diff --git a/.gitignore b/.gitignore index 579afde..e7f1abe 100644 --- a/.gitignore +++ b/.gitignore @@ -81,6 +81,7 @@ typings/ # Nuxt.js build / generate output .nuxt dist +build # Gatsby files .cache/ @@ -104,4 +105,9 @@ dist .tern-port .DS_Store src/test-harness.json -test-report.html \ No newline at end of file +test-report.html +wallaby.js + +jest-html-reporters-attach +seed.data.json +.idea/ diff --git a/README.md b/README.md index 8b9fdff..b85235e 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,126 @@ # TDEI-api-tester -API tester for the client-API received from swagger + +This service repository contains automated test cases for TDEI API endpoints to verify their functionality and generate a comprehensive test report. The API specifications are received from Swagger (OpenAPI), ensuring tests are aligned with the latest API definition and remain reliable, functional, and compliant with their specifications + +1. Automated Testing of API Endpoints + - Executes test cases for all TDEI API endpoints to validate expected responses. +2. Test Case Management + - Covers positive, negative, and edge cases to ensure robustness. +3. Report Generation + - Generates a detailed test report after execution. + - Includes test results for all endpoints, status codes, response validation, and errors. +4. Integration with CI/CD + - Can be integrated into GitHub Workflows or any CI/CD pipeline. + +## System requirements +| Software | Version| +|----|---| +| NodeJS | 18.16.0| +| Typescript | 4.8.2 | + +## Environment variables + +Application configuration is read from .env file. Below are the list of environemnt variables service is dependent on. Description of environment variable is presented in below table + +|Name| Description | +|--|--| +| PROVIDER | Provider for cloud service or local (optional)| +|SEED_BASE_URL | User management portal api url | +|SEED_ADMIN_USER | admin user name| +|SEED_ADMIN_PASSWORD |admin password| +|SYSTEM_BASE_URL | TDEI API url| +|ENVIRONMENT | Environement to run api tester dev, stage, prod| + + +## API Tester Environment Data + +The API Tester requires environment-specific data to execute test cases. This data is essential for ensuring that tests run successfully with the required dependencies. + +Environment Data Dependencies stored in api.input.json. + +Types of Environment Data Included: +1. User Accounts: +- Pre-verified users to bypass email verification in user registration tests. +- Includes credentials for different roles like admin, data generators, API key testers, etc. +2. Dataset IDs: +- Used for testing both positive and negative cases in dataset-related API endpoints. +3. Other API-Specific Dependencies: +- Any additional environment-specific data required by the API test cases. + +By maintaining this structured environment input data, the API Tester can run consistent and reliable test cases across different environments. 🚀 + +## Seeder requirements +- To enhance the testing with different personas and varied systems, it is imperative that we generate some scripts that allow generation of users and other seed data required for testing. + +Here are the requirements for seed data generation + +- Create an project group with random project group data +- Assign the roles to the users for the generated project group +- Create a service +- Assign role to the users. + +When we start test , seeder process will start and start with above seed generation and generate one file with `seed.data.json` which is used while testing the API's with different personas. Json format shown below: + +```json +{ + "project_group": { + "tdei_project_group_id": "", + "name": "" + }, + "services": [ + { + "tdei_service_id": "", + "service_type": "", + "service_name": "", + "tdei_project_group_id": "" + }, + { + "tdei_service_id": "", + "service_type": "", + "service_name": "", + "tdei_project_group_id": "" + }, + { + "tdei_service_id": "", + "service_type": "", + "service_name": "", + "tdei_project_group_id": "" + } + ], + "users": { + "poc": { + "username": "", + "password": "" + }, + "flex_data_generator": { + "username": "", + "password": "" + }, + "pathways_data_generator": { + "username": "", + "password": "" + }, + "osw_data_generator": { + "username": "", + "password": "" + }, + "api_key_tester": { + "username": "", + "password": "" + }, + "default_user": { + "username": "", + "password": "" + } + }, + "api_key": "", + "api_key_tester": "" +} + +``` # Steps -- The testing rig is currently configured based on `test-harness.json` file. -- An example of the file is already given as `test-harness.example.json` +- The testing rig is currently configured based on `.env` file. - `npm i` - `npm run test` @@ -15,6 +132,28 @@ The above code runs the tests and generates a `test-report.html` (already includ - name it in the format `.test.ts` - Write test cases based on [jest](https://jestjs.io/docs/getting-started) +## Important notes on writing tests for better readability +- Consider Adding tests in the below format +> Given +- Setup test data in this step +- Give a line break +> When +- Perform some action +- Give a line break +> Then +- Assert result + +``` +describe('my-awesome-test', () => { + const getTestData => return {}; + it('should validate schema response', () => { + let testData = getTestData(); + let api = new myAwesomeApi(); + + const result = api.getVersions(); -## TODO: - Document on what the component is and where it helps + expect(result.status).toBe(200); + expect(result.myAwesomeField).toBe('valid'); + }); +}); +``` diff --git a/api.input.json b/api.input.json new file mode 100644 index 0000000..e9cb005 --- /dev/null +++ b/api.input.json @@ -0,0 +1,77 @@ +{ + "dev": { + "osw": { + "published_dataset": "40566429d02c4c80aee68c970977bed8", + "pre_release_dataset": "1978d16b-46f6-4d0c-b1d1-78123178a65b", + "test_dataset": "f5fd7445fbbf4f248ea1096f0e17b7b3", + "spatial_target_dataset": "fa8e12ea-6b0c-4d3e-8b38-5b87b268e76b", + "spatial_source_dataset": "0d661b69495d47fb838862edf699fe09" + }, + "flex": { + "published_dataset": "309dea0b-0fb2-4c19-a771-9f3719b48030", + "pre_release_dataset": "8b0cac15-4f96-4ea8-aac7-934dad1e0367" + }, + "pathways": { + "published_dataset": "cb472b40-38cf-4006-abab-5c819682b08c", + "pre_release_dataset": "b8e068b9-67b4-4fe9-8ddb-c1d64d3702ce" + }, + "users": { + "poc": "adella.legros3@gmail.com", + "flex_data_generator": "reilly_connelly@yahoo.com", + "pathways_data_generator": "emiliano.terry@hotmail.com", + "osw_data_generator": "rhianna.runolfsson@yahoo.com", + "api_key_tester": "apikeytester@mailinator.com", + "default_user": "defaultuser@mailinator.com" + } + }, + "stage": { + "osw": { + "published_dataset": "047c8e5f-bfce-48ee-8dd0-3cdc16d72624", + "pre_release_dataset": "42982431-d983-4c0a-aadb-c88b4ef7d2b8", + "test_dataset": "74d2d6fc-db4a-4f72-8042-e521ef5c3520", + "spatial_target_dataset": "892897ec-d75e-47f5-84ed-efc08ca6a8c6", + "spatial_source_dataset": "0c384536b471477db07a4c6e9d8476bf" + }, + "flex": { + "published_dataset": "3cb8a738-b274-4c6c-a8d4-a212de9a7623", + "pre_release_dataset": "80548cc3-0d49-4642-aa40-ec8da7f63fef" + }, + "pathways": { + "published_dataset": "7912bddf-5333-4a6e-9af8-81b1efd01707", + "pre_release_dataset": "cc186aa4-8576-4d6e-bd89-f5df4e2e5851" + }, + "users": { + "poc": "frederic71@gmail.com", + "flex_data_generator": "vern66@gmail.com", + "pathways_data_generator": "elvera.keeling@gmail.com", + "osw_data_generator": "alyce_kilback60@yahoo.com", + "api_key_tester": "apikeytester@mailinator.com", + "default_user": "defaultuser@mailinator.com" + } + }, + "prod": { + "osw": { + "published_dataset": "40566429d02c4c80aee68c970977bed8", + "pre_release_dataset": "26f0ec82-1434-4944-ae8c-dea8aa5e0075", + "test_dataset": "f5fd7445fbbf4f248ea1096f0e17b7b3", + "spatial_target_dataset": "fa8e12ea-6b0c-4d3e-8b38-5b87b268e76b", + "spatial_source_dataset": "0d661b69495d47fb838862edf699fe09" + }, + "flex": { + "published_dataset": "309dea0b-0fb2-4c19-a771-9f3719b48030", + "pre_release_dataset": "8b0cac15-4f96-4ea8-aac7-934dad1e0367" + }, + "pathways": { + "published_dataset": "cb472b40-38cf-4006-abab-5c819682b08c", + "pre_release_dataset": "b8e068b9-67b4-4fe9-8ddb-c1d64d3702ce" + }, + "users": { + "poc": "adella.legros3@gmail.com", + "flex_data_generator": "reilly_connelly@yahoo.com", + "pathways_data_generator": "emiliano.terry@hotmail.com", + "osw_data_generator": "rhianna.runolfsson@yahoo.com", + "api_key_tester": "apikeytester@mailinator.com", + "default_user": "defaultuser@mailinator.com" + } + } +} \ No newline at end of file diff --git a/assets/payloads/gtfs-flex/files/otterexpress-mn-us--flex-v2.zip b/assets/payloads/gtfs-flex/files/otterexpress-mn-us--flex-v2.zip new file mode 100644 index 0000000..8b27717 Binary files /dev/null and b/assets/payloads/gtfs-flex/files/otterexpress-mn-us--flex-v2.zip differ diff --git a/assets/payloads/gtfs-flex/metadata.json b/assets/payloads/gtfs-flex/metadata.json new file mode 100644 index 0000000..6fd6f10 --- /dev/null +++ b/assets/payloads/gtfs-flex/metadata.json @@ -0,0 +1,101 @@ +{ + "data_provenance": { + "full_dataset_name": "Seattle Downtown", + "other_published_locations": "Seattle", + "dataset_update_frequency_months": 2, + "schema_validation_run": true, + "schema_validation_run_description": "automated", + "allow_crowd_contributions": true, + "location_inaccuracy_factors": "0.3" + }, + "dataset_detail": { + "name": "Seattle Downtown", + "description": "Seattle Downtown", + "version": "1.0", + "custom_metadata": null, + "collected_by": "Paul John", + "collection_date": "2023-01-01T00:00:00", + "valid_from": null, + "valid_to": null, + "collection_method": "manual", + "data_source": "3rdParty", + "dataset_area": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "coordinates": [ + [ + [ + -122.15355613777264, + 47.65546781881713 + ], + [ + -122.15403331592054, + 47.624602277728656 + ], + [ + -122.10997386694785, + 47.62567430349651 + ], + [ + -122.1187221329894, + 47.65611065702191 + ], + [ + -122.15355613777264, + 47.65546781881713 + ] + ] + ], + "type": "Polygon" + } + } + ] + }, + "schema_version": "v2.0" + }, + "dataset_summary": { + "collection_name": "tacoma", + "department_name": "DOT", + "city": "Seattle", + "region": "North", + "county": "King", + "key_limitations": "inaccurate", + "release_notes": "NA", + "challenges": null + }, + "maintenance": { + "official_maintainer": [ + "Paul", + "John" + ], + "last_updated": null, + "update_frequency": "weekly", + "authorization_chain": null, + "maintenance_funded": true, + "funding_details": "BOA" + }, + "methodology": { + "point_data_collection_device": "mobile", + "node_locations_and_attributes_editing_software": "global", + "data_collected_by_people": false, + "data_collectors": null, + "data_captured_automatically": true, + "automated_collection": "NA", + "data_collectors_organization": "transit", + "data_collector_compensation": "commision", + "preprocessing_location": "washington", + "preprocessing_by": "govt", + "preprocessing_steps": "automated", + "data_collection_preprocessing_documentation": true, + "documentation_uri": "http://tdei.com", + "validation_process_exists": true, + "validation_process_description": "walking", + "validation_conducted_by": "volantary", + "excluded_data": null, + "excluded_data_reason": "not satisfied" + } +} \ No newline at end of file diff --git a/assets/payloads/gtfs-flex/valid.json b/assets/payloads/gtfs-flex/valid.json deleted file mode 100644 index d2abf36..0000000 --- a/assets/payloads/gtfs-flex/valid.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "tdei_org_id": "66c85a5a-2335-4b97-a0a3-0bb93cba1ae5", - "tdei_service_id": "333", - "collected_by": "testuser", - "collection_date": "2023-03-02T04:22:42.493Z", - "collection_method": "manual", - "valid_from": "2023-03-02T04:22:42.493Z", - "valid_to": "2023-03-02T04:22:42.493Z", - "data_source": "TDEITools", - "polygon": { - "type": "FeatureCollection", - "features": [ - { - "type": "Feature", - "geometry": { - "type": "Polygon", - "coordinates": [ - [ - [ - 77.588807608, - 12.976222962 - ], - [ - 77.589285425, - 12.972094479 - ], - [ - 77.593012392, - 12.974608826 - ], - [ - 77.588839463, - 12.976254003 - ], - [ - 77.588807608, - 12.976222962 - ] - ] - ] - } - } - ] - }, - "flex_schema_version": "v2.0" - } \ No newline at end of file diff --git a/assets/payloads/gtfs-pathways/files/gtfs-pathways-valid-old.zip b/assets/payloads/gtfs-pathways/files/gtfs-pathways-valid-old.zip new file mode 100644 index 0000000..525c66a Binary files /dev/null and b/assets/payloads/gtfs-pathways/files/gtfs-pathways-valid-old.zip differ diff --git a/assets/payloads/gtfs-pathways/files/gtfs-pathways-valid.zip b/assets/payloads/gtfs-pathways/files/gtfs-pathways-valid.zip new file mode 100644 index 0000000..d936578 Binary files /dev/null and b/assets/payloads/gtfs-pathways/files/gtfs-pathways-valid.zip differ diff --git a/assets/payloads/gtfs-pathways/metadata.json b/assets/payloads/gtfs-pathways/metadata.json new file mode 100644 index 0000000..c94eb97 --- /dev/null +++ b/assets/payloads/gtfs-pathways/metadata.json @@ -0,0 +1,101 @@ +{ + "data_provenance": { + "full_dataset_name": "MD MTA Subway GTFS", + "other_published_locations": "MD MTA Subway GTFS", + "dataset_update_frequency_months": 2, + "schema_validation_run": true, + "schema_validation_run_description": "automated", + "allow_crowd_contributions": true, + "location_inaccuracy_factors": "0.3" + }, + "dataset_detail": { + "name": "MD MTA Subway GTFS", + "description": "Seattle Downtown", + "version": "1.0", + "custom_metadata": null, + "collected_by": "Paul John", + "collection_date": "2023-01-01T00:00:00", + "valid_from": null, + "valid_to": null, + "collection_method": "manual", + "data_source": "3rdParty", + "dataset_area": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "coordinates": [ + [ + [ + -122.15355613777264, + 47.65546781881713 + ], + [ + -122.15403331592054, + 47.624602277728656 + ], + [ + -122.10997386694785, + 47.62567430349651 + ], + [ + -122.1187221329894, + 47.65611065702191 + ], + [ + -122.15355613777264, + 47.65546781881713 + ] + ] + ], + "type": "Polygon" + } + } + ] + }, + "schema_version": "v1.0" + }, + "dataset_summary": { + "collection_name": "tacoma", + "department_name": "DOT", + "city": "MD MTA Subway GTFS", + "region": "North", + "county": "King", + "key_limitations": "inaccurate", + "release_notes": "NA", + "challenges": null + }, + "maintenance": { + "official_maintainer": [ + "Paul", + "John" + ], + "last_updated": null, + "update_frequency": "weekly", + "authorization_chain": null, + "maintenance_funded": true, + "funding_details": "BOA" + }, + "methodology": { + "point_data_collection_device": "mobile", + "node_locations_and_attributes_editing_software": "global", + "data_collected_by_people": false, + "data_collectors": null, + "data_captured_automatically": true, + "automated_collection": "NA", + "data_collectors_organization": "transit", + "data_collector_compensation": "commision", + "preprocessing_location": "washington", + "preprocessing_by": "govt", + "preprocessing_steps": "automated", + "data_collection_preprocessing_documentation": true, + "documentation_uri": "http://tdei.com", + "validation_process_exists": true, + "validation_process_description": "walking", + "validation_conducted_by": "volantary", + "excluded_data": null, + "excluded_data_reason": "not satisfied" + } +} \ No newline at end of file diff --git a/assets/payloads/gtfs-pathways/valid.json b/assets/payloads/gtfs-pathways/valid.json deleted file mode 100644 index c02c381..0000000 --- a/assets/payloads/gtfs-pathways/valid.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "tdei_org_id": "5e339544-3b12-40a5-8acd-78c66d1fa981", - "tdei_station_id": "333", - "collected_by": "testuser", - "collection_date": "2023-03-02T04:22:42.493Z", - "collection_method": "manual", - "valid_from": "2023-03-02T04:22:42.493Z", - "valid_to": "2023-03-02T04:22:42.493Z", - "data_source": "TDEITools", - "polygon": { - "coordinates": [ - [ - [ - 77.58700584031209, - 12.97544246408998 - ], - [ - 77.58670678771239, - 12.974635462667848 - ], - [ - 77.58782248394829, - 12.974489753799247 - ], - [ - 77.58813303857153, - 12.97529675569426 - ], - [ - 77.58700584031209, - 12.97544246408998 - ]]] - }, - "pathways_schema_version": "v1.0" - } \ No newline at end of file diff --git a/assets/payloads/osw/files/Archivew.zip b/assets/payloads/osw/files/Archivew.zip new file mode 100644 index 0000000..aacb235 Binary files /dev/null and b/assets/payloads/osw/files/Archivew.zip differ diff --git a/assets/payloads/osw/files/changeset.zip b/assets/payloads/osw/files/changeset.zip new file mode 100644 index 0000000..5bf7452 --- /dev/null +++ b/assets/payloads/osw/files/changeset.zip @@ -0,0 +1 @@ +## Sample changeset \ No newline at end of file diff --git a/assets/payloads/osw/files/osw-la.zip b/assets/payloads/osw/files/osw-la.zip new file mode 100644 index 0000000..35890b0 Binary files /dev/null and b/assets/payloads/osw/files/osw-la.zip differ diff --git a/assets/payloads/osw/files/valid.zip b/assets/payloads/osw/files/valid.zip deleted file mode 100644 index 5282538..0000000 Binary files a/assets/payloads/osw/files/valid.zip and /dev/null differ diff --git a/assets/payloads/osw/metadata.json b/assets/payloads/osw/metadata.json new file mode 100644 index 0000000..5288bbf --- /dev/null +++ b/assets/payloads/osw/metadata.json @@ -0,0 +1,101 @@ +{ + "data_provenance": { + "full_dataset_name": "Seattle Downtown", + "other_published_locations": "Seattle", + "dataset_update_frequency_months": 2, + "schema_validation_run": true, + "schema_validation_run_description": "automated", + "allow_crowd_contributions": true, + "location_inaccuracy_factors": "0.3" + }, + "dataset_detail": { + "name": "Seattle Downtown", + "description": "Seattle Downtown", + "version": "1.0", + "custom_metadata": null, + "collected_by": "Paul John", + "collection_date": "2023-01-01T00:00:00", + "valid_from": null, + "valid_to": null, + "collection_method": "manual", + "data_source": "3rdParty", + "dataset_area": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "coordinates": [ + [ + [ + -122.15355613777264, + 47.65546781881713 + ], + [ + -122.15403331592054, + 47.624602277728656 + ], + [ + -122.10997386694785, + 47.62567430349651 + ], + [ + -122.1187221329894, + 47.65611065702191 + ], + [ + -122.15355613777264, + 47.65546781881713 + ] + ] + ], + "type": "Polygon" + } + } + ] + }, + "schema_version": "v0.2" + }, + "dataset_summary": { + "collection_name": "tacoma", + "department_name": "DOT", + "city": "Seattle", + "region": "North", + "county": "King", + "key_limitations": "inaccurate", + "release_notes": "NA", + "challenges": null + }, + "maintenance": { + "official_maintainer": [ + "Paul", + "John" + ], + "last_updated": null, + "update_frequency": "weekly", + "authorization_chain": null, + "maintenance_funded": true, + "funding_details": "BOA" + }, + "methodology": { + "point_data_collection_device": "mobile", + "node_locations_and_attributes_editing_software": "global", + "data_collected_by_people": false, + "data_collectors": null, + "data_captured_automatically": true, + "automated_collection": "NA", + "data_collectors_organization": "transit", + "data_collector_compensation": "commision", + "preprocessing_location": "washington", + "preprocessing_by": "govt", + "preprocessing_steps": "automated", + "data_collection_preprocessing_documentation": true, + "documentation_uri": "http://tdei.com", + "validation_process_exists": true, + "validation_process_description": "walking", + "validation_conducted_by": "volantary", + "excluded_data": null, + "excluded_data_reason": "not satisfied" + } +} \ No newline at end of file diff --git a/assets/payloads/osw/sub-region.geojson b/assets/payloads/osw/sub-region.geojson new file mode 100644 index 0000000..1e4bc82 --- /dev/null +++ b/assets/payloads/osw/sub-region.geojson @@ -0,0 +1,129 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -122.320233281114923, + 47.619285516250514 + ], + [ + -122.320233281114923, + 47.618626781785451 + ], + [ + -122.321031309685679, + 47.618443255887399 + ], + [ + -122.321141563633006, + 47.619285516250514 + ], + [ + -122.320233281114923, + 47.619285516250514 + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -122.320233281114923, + 47.619285516250514 + ], + [ + -122.321141563633006, + 47.619285516250514 + ], + [ + -122.321251817580332, + 47.620127776613629 + ], + [ + -122.320233281114923, + 47.620103004637258 + ], + [ + -122.320233281114923, + 47.619285516250514 + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -122.320233281114923, + 47.619285516250514 + ], + [ + -122.319235138533656, + 47.619285516250514 + ], + [ + -122.31924624577745, + 47.618853774343563 + ], + [ + -122.320233281114923, + 47.618626781785451 + ], + [ + -122.320233281114923, + 47.619285516250514 + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -122.320233281114923, + 47.619285516250514 + ], + [ + -122.320233281114923, + 47.620103004637258 + ], + [ + -122.3192147446495, + 47.620078232660887 + ], + [ + -122.319235138533656, + 47.619285516250514 + ], + [ + -122.320233281114923, + 47.619285516250514 + ] + ] + ] + } + } + ] +} \ No newline at end of file diff --git a/assets/payloads/osw/tag-quality.json b/assets/payloads/osw/tag-quality.json new file mode 100644 index 0000000..816c2b5 --- /dev/null +++ b/assets/payloads/osw/tag-quality.json @@ -0,0 +1,254 @@ +[ + { + "entity_type": "Footway", + "tags": [ + "surface", + "width", + "incline", + "length", + "description", + "name", + "foot" + ] + }, + { + "entity_type": "Crossing", + "tags": [ + "surface", + "width", + "incline", + "length", + "description", + "name", + "foot", + "crossing:markings" + ] + }, + { + "entity_type": "Sidewalk", + "tags": [ + "surface", + "width", + "incline", + "length", + "description", + "name", + "foot" + ] + }, + { + "entity_type": "TrafficIsland", + "tags": [ + "surface", + "width", + "incline", + "length", + "description", + "name", + "foot" + ] + }, + { + "entity_type": "Pedestrian", + "tags": [ + "surface", + "width", + "incline", + "length", + "description", + "name", + "foot" + ] + }, + { + "entity_type": "Steps", + "tags": [ + "surface", + "width", + "incline", + "length", + "description", + "name", + "foot", + "step_count", + "climb" + ] + }, + { + "entity_type": "LivingStreet", + "tags": [ + "surface", + "width", + "incline", + "length", + "description", + "name", + "foot" + ] + }, + { + "entity_type": "PrimaryStreet", + "tags": [ + "surface", + "width", + "incline", + "length", + "description", + "name", + "foot" + ] + }, + { + "entity_type": "SecondaryStreet", + "tags": [ + "surface", + "width", + "incline", + "length", + "description", + "name", + "foot" + ] + }, + { + "entity_type": "TertiaryStreet", + "tags": [ + "surface", + "width", + "incline", + "length", + "description", + "name", + "foot" + ] + }, + { + "entity_type": "ResidentialStreet", + "tags": [ + "surface", + "width", + "incline", + "length", + "description", + "name", + "foot" + ] + }, + { + "entity_type": "ServiceRoad", + "tags": [ + "surface", + "width", + "incline", + "length", + "description", + "name", + "foot" + ] + }, + { + "entity_type": "Driveway", + "tags": [ + "surface", + "width", + "incline", + "length", + "description", + "name", + "foot" + ] + }, + { + "entity_type": "Alley", + "tags": [ + "surface", + "width", + "incline", + "length", + "description", + "name", + "foot" + ] + }, + { + "entity_type": "ParkingAisle", + "tags": [ + "surface", + "width", + "incline", + "length", + "description", + "name", + "foot" + ] + }, + { + "entity_type": "UnclassifiedRoad", + "tags": [ + "surface", + "width", + "incline", + "length", + "description", + "name", + "foot" + ] + }, + { + "entity_type": "TrunkRoad", + "tags": [ + "surface", + "width", + "incline", + "length", + "description", + "name", + "foot" + ] + }, + { + "entity_type": "GenericCurb", + "tags": [ + "tactile_paving" + ] + }, + { + "entity_type": "FlushCurb", + "tags": [ + "tactile_paving" + ] + }, + { + "entity_type": "RaisedCurb", + "tags": [ + "tactile_paving" + ] + }, + { + "entity_type": "RolledCurb", + "tags": [ + "tactile_paving" + ] + }, + { + "entity_type": "CurbRamp", + "tags": [ + "tactile_paving" + ] + }, + { + "entity_type": "PedestrianZone", + "tags": [ + "surface", + "description", + "name", + "foot" + ] + }, + { + "entity_type": "Fence", + "tags": [ + "length" + ] + } +] \ No newline at end of file diff --git a/assets/payloads/osw/valid.json b/assets/payloads/osw/valid.json deleted file mode 100644 index c12f582..0000000 --- a/assets/payloads/osw/valid.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "tdei_org_id": "5e339544-3b12-40a5-8acd-78c66d1fa981", - "collected_by": "sfsd", - "collection_date": "2023-03-03T02:22:45.374Z", - "collection_method": "manual", - "publication_date": "2023-03-02T04:22:42.493Z", - "data_source": "InHouse", - "polygon": { - "type": "FeatureCollection", - "features": [ - { - "type": "Feature", - "geometry": { - "type": "Polygon", - "coordinates": [ - [ - [ - 77.588807608, - 12.976222962 - ], - [ - 77.589285425, - 12.972094479 - ], - [ - 77.593012392, - 12.974608826 - ], - [ - 77.588839463, - 12.976254003 - ], - [ - 77.588807608, - 12.976222962 - ] - ] - ] - } - } - ] - }, - "osw_schema_version": "v0.1" - } \ No newline at end of file diff --git a/assets/payloads/seed-data/organization.json b/assets/payloads/seed-data/organization.json deleted file mode 100644 index aae8c17..0000000 --- a/assets/payloads/seed-data/organization.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - - "org_name": "Test Organization2", - "phone": "911-111-1122", - "url": "https://tdei.com", - "address": "Test address", - "polygon": { - "type": "FeatureCollection", - "features": [ - { - "type": "Feature", - "geometry": { - "type": "Polygon", - "coordinates": [ - [ - [ - 77.588807600, - 12.976222960 - ], - [ - 77.589285400, - 12.972094479 - ], - [ - 77.593012392, - 12.974608826 - ], - [ - 77.588839463, - 12.976254000 - ], - [ - 77.588807600, - 12.976222960 - ] - ] - ] - } - } - ] - } -} \ No newline at end of file diff --git a/assets/payloads/seed-data/user-data.json b/assets/payloads/seed-data/user-data.json deleted file mode 100644 index 36ae5ce..0000000 --- a/assets/payloads/seed-data/user-data.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "users": [ - { - "role": "poc", - "user": { - "firstName": "Naresh", - "lastName": "Kumar", - "email": "nareshd1@gaussiansolutions.com", - "phone": "8971722511", - "password": "Pa$s1word" - } - }, - { - "role": "flex_data_generator", - "user": { - "firstName": "Flex", - "lastName": "generator", - "email": "flex1@tdei.com", - "phone": "8971722512", - "password": "Pa$s1word" - } - }, - { - "role": "pathways_data_generator", - "user": { - "firstName": "Pathways", - "lastName": "generator", - "email": "pathways1@tdei.com", - "phone": "8971722513", - "password": "Pa$s1word" - } - }, - { - "role": "osw_data_generator", - "user": { - "firstName": "OSW", - "lastName": "generator", - "email": "osw1@tdei.com", - "phone": "8971722514", - "password": "Pa$s1word" - } - } - ] -} \ No newline at end of file diff --git a/assets/postman/TDEI-metadata-validation.postman_collection.json b/assets/postman/TDEI-metadata-validation.postman_collection.json new file mode 100644 index 0000000..bc9644b --- /dev/null +++ b/assets/postman/TDEI-metadata-validation.postman_collection.json @@ -0,0 +1,1311 @@ +{ + "info": { + "_postman_id": "4fb55cc0-9b06-4124-9d8a-519ec0a9094f", + "name": "TDEI-metadata-validation", + "description": "This collection elaborates on how to test the metadata validation for the TDEI system\n\nThere are two folders in this collection. Each folder represents the file type supported.\n\nAll the payloads for each case are put up as collection variables\n\n## Steps to test\n\n1. Authenticate the user using `Authenticate` method\n2. This sets the access_token for the session\n3. Based on the type of file you want to verify, run the corresponding folder.\n4. Only one folder can be run at one time. If you want to run both at the same time, ensure that the user details are correct (User has permission to upload both flex and pathways)\n5. Each of the file type will require a zip file for upload. The files are sent separately or available in /assets/payloads folder", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "23362010" + }, + "item": [ + { + "name": "gtfs-flex", + "item": [ + { + "name": "upload-max-collected-by", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "pm.test(\"Body matches string\", function () {", + " pm.expect(pm.response.text()).to.include(\"collected_by\");", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "meta", + "value": "{{flex-collected-by}}", + "type": "text" + }, + { + "key": "file", + "type": "file", + "src": "success_1_all_attrs.zip" + } + ] + }, + "url": { + "raw": "{{hostUrl}}/api/v1/gtfs-flex", + "host": [ + "{{hostUrl}}" + ], + "path": [ + "api", + "v1", + "gtfs-flex" + ] + }, + "description": "Collected by has a max 50 characters length" + }, + "response": [] + }, + { + "name": "no-collection_date", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "pm.test(\"Body matches string\", function () {", + " pm.expect(pm.response.text()).to.include(\"collectionDate\");", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "meta", + "value": "{{flex-no-collection-date}}", + "type": "text" + }, + { + "key": "file", + "type": "file", + "src": "success_1_all_attrs.zip" + } + ] + }, + "url": { + "raw": "{{hostUrl}}/api/v1/gtfs-flex", + "host": [ + "{{hostUrl}}" + ], + "path": [ + "api", + "v1", + "gtfs-flex" + ] + }, + "description": "No collection date should yield bad request with error containing collectionDate" + }, + "response": [] + }, + { + "name": "collection-date-future", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "pm.test(\"Body matches string\", function () {", + " pm.expect(pm.response.text()).to.include(\"collection_date\");", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "meta", + "value": "{{flex-collection-date-future}}", + "type": "text" + }, + { + "key": "file", + "type": "file", + "src": "success_1_all_attrs.zip" + } + ] + }, + "url": { + "raw": "{{hostUrl}}/api/v1/gtfs-flex", + "host": [ + "{{hostUrl}}" + ], + "path": [ + "api", + "v1", + "gtfs-flex" + ] + }, + "description": "If the collection_date is in future, there should be an error with collection_date invalid" + }, + "response": [] + }, + { + "name": "no-collection-method", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "pm.test(\"Body matches string\", function () {", + " pm.expect(pm.response.text()).to.include(\"collectionMethod\");", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "meta", + "value": "{{flex-no-collection-method}}", + "type": "text" + }, + { + "key": "file", + "type": "file", + "src": "success_1_all_attrs.zip" + } + ] + }, + "url": { + "raw": "{{hostUrl}}/api/v1/gtfs-flex", + "host": [ + "{{hostUrl}}" + ], + "path": [ + "api", + "v1", + "gtfs-flex" + ] + }, + "description": "Should throw a bad request if there is no collection method specified" + }, + "response": [] + }, + { + "name": "invalid-collection-method", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "pm.test(\"Body matches string\", function () {", + " pm.expect(pm.response.text()).to.include(\"collection_method\");", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "meta", + "value": "{{flex-invalid-collection-method}}", + "type": "text" + }, + { + "key": "file", + "type": "file", + "src": "success_1_all_attrs.zip" + } + ] + }, + "url": { + "raw": "{{hostUrl}}/api/v1/gtfs-flex", + "host": [ + "{{hostUrl}}" + ], + "path": [ + "api", + "v1", + "gtfs-flex" + ] + }, + "description": "Should throw a bad request if the collection method is invalid" + }, + "response": [] + }, + { + "name": "no-data-source", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "pm.test(\"Body matches string\", function () {", + " pm.expect(pm.response.text()).to.include(\"dataSource\");", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "meta", + "value": "{{flex-no-data-source}}", + "type": "text" + }, + { + "key": "file", + "type": "file", + "src": "success_1_all_attrs.zip" + } + ] + }, + "url": { + "raw": "{{hostUrl}}/api/v1/gtfs-flex", + "host": [ + "{{hostUrl}}" + ], + "path": [ + "api", + "v1", + "gtfs-flex" + ] + }, + "description": "should throw a bad request if data source is not specified" + }, + "response": [] + }, + { + "name": "invalid-data-source", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "pm.test(\"Body matches string\", function () {", + " pm.expect(pm.response.text()).to.include(\"data_source\");", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "meta", + "value": "{{flex-invalid-data-source}}", + "type": "text" + }, + { + "key": "file", + "type": "file", + "src": "success_1_all_attrs.zip" + } + ] + }, + "url": { + "raw": "{{hostUrl}}/api/v1/gtfs-flex", + "host": [ + "{{hostUrl}}" + ], + "path": [ + "api", + "v1", + "gtfs-flex" + ] + }, + "description": "Should throw a bad request if the data source is invalid and not in the list" + }, + "response": [] + }, + { + "name": "no-flex-schema", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "pm.test(\"Body matches string\", function () {", + " pm.expect(pm.response.text()).to.include(\"flexSchemaVersion\");", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "meta", + "value": "{{flex-no-schema}}", + "type": "text" + }, + { + "key": "file", + "type": "file", + "src": "success_1_all_attrs.zip" + } + ] + }, + "url": { + "raw": "{{hostUrl}}/api/v1/gtfs-flex", + "host": [ + "{{hostUrl}}" + ], + "path": [ + "api", + "v1", + "gtfs-flex" + ] + }, + "description": "should throw a bad request if flex-schema is not added" + }, + "response": [] + }, + { + "name": "invalid-flex-schema", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "pm.test(\"Body matches string\", function () {", + " pm.expect(pm.response.text()).to.include(\"flex_schema_version\");", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "meta", + "value": "{{flex-invalid-schema}}", + "type": "text" + }, + { + "key": "file", + "type": "file", + "src": "success_1_all_attrs.zip" + } + ] + }, + "url": { + "raw": "{{hostUrl}}/api/v1/gtfs-flex", + "host": [ + "{{hostUrl}}" + ], + "path": [ + "api", + "v1", + "gtfs-flex" + ] + }, + "description": "should throw an invalid flex schema error if the flex schema is not in the given list" + }, + "response": [] + }, + { + "name": "flex-success", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 202\", function () {", + " pm.response.to.have.status(202);", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "meta", + "value": "{{flex-valid}}", + "type": "text" + }, + { + "key": "file", + "type": "file", + "src": "success_1_all_attrs.zip" + } + ] + }, + "url": { + "raw": "{{hostUrl}}/api/v1/gtfs-flex", + "host": [ + "{{hostUrl}}" + ], + "path": [ + "api", + "v1", + "gtfs-flex" + ] + }, + "description": "Should give out success if the valid parameters are sent" + }, + "response": [] + } + ], + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{access_token}}", + "type": "string" + } + ] + }, + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ] + }, + { + "name": "gtfs-pathways", + "item": [ + { + "name": "upload-max-collected-by", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "pm.test(\"Body matches string\", function () {", + " pm.expect(pm.response.text()).to.include(\"collected_by\");", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "meta", + "value": "{{pathway-collected-by}}", + "type": "text" + }, + { + "key": "file", + "type": "file", + "src": "success_1_all_attrs.zip" + } + ] + }, + "url": { + "raw": "{{hostUrl}}/api/v1/gtfs-pathways", + "host": [ + "{{hostUrl}}" + ], + "path": [ + "api", + "v1", + "gtfs-pathways" + ] + }, + "description": "Collected by has a max 50 characters length" + }, + "response": [] + }, + { + "name": "no-collection_date", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "pm.test(\"Body matches string\", function () {", + " pm.expect(pm.response.text()).to.include(\"collectionDate\");", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "meta", + "value": "{{pathway-no-collection-date}}", + "type": "text" + }, + { + "key": "file", + "type": "file", + "src": "success_1_all_attrs.zip" + } + ] + }, + "url": { + "raw": "{{hostUrl}}/api/v1/gtfs-pathways", + "host": [ + "{{hostUrl}}" + ], + "path": [ + "api", + "v1", + "gtfs-pathways" + ] + }, + "description": "No collection date should yield bad request with error containing collectionDate" + }, + "response": [] + }, + { + "name": "collection-date-future", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "pm.test(\"Body matches string\", function () {", + " pm.expect(pm.response.text()).to.include(\"collection_date\");", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "meta", + "value": "{{pathway-collection-date-future}}", + "type": "text" + }, + { + "key": "file", + "type": "file", + "src": "success_1_all_attrs.zip" + } + ] + }, + "url": { + "raw": "{{hostUrl}}/api/v1/gtfs-pathways", + "host": [ + "{{hostUrl}}" + ], + "path": [ + "api", + "v1", + "gtfs-pathways" + ] + }, + "description": "If the collection_date is in future, there should be an error with collection_date invalid" + }, + "response": [] + }, + { + "name": "no-collection-method", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "pm.test(\"Body matches string\", function () {", + " pm.expect(pm.response.text()).to.include(\"collectionMethod\");", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "meta", + "value": "{{pathway-no-collection-method}}", + "type": "text" + }, + { + "key": "file", + "type": "file", + "src": "success_1_all_attrs.zip" + } + ] + }, + "url": { + "raw": "{{hostUrl}}/api/v1/gtfs-pathways", + "host": [ + "{{hostUrl}}" + ], + "path": [ + "api", + "v1", + "gtfs-pathways" + ] + }, + "description": "Should throw a bad request if there is no collection method specified" + }, + "response": [] + }, + { + "name": "invalid-collection-method", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "pm.test(\"Body matches string\", function () {", + " pm.expect(pm.response.text()).to.include(\"collection_method\");", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "meta", + "value": "{{pathway-invalid-collection-method}}", + "type": "text" + }, + { + "key": "file", + "type": "file", + "src": "success_1_all_attrs.zip" + } + ] + }, + "url": { + "raw": "{{hostUrl}}/api/v1/gtfs-pathways", + "host": [ + "{{hostUrl}}" + ], + "path": [ + "api", + "v1", + "gtfs-pathways" + ] + }, + "description": "Should throw a bad request if the collection method is invalid" + }, + "response": [] + }, + { + "name": "no-data-source", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "pm.test(\"Body matches string\", function () {", + " pm.expect(pm.response.text()).to.include(\"dataSource\");", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "meta", + "value": "{{pathway-no-data-source}}", + "type": "text" + }, + { + "key": "file", + "type": "file", + "src": "success_1_all_attrs.zip" + } + ] + }, + "url": { + "raw": "{{hostUrl}}/api/v1/gtfs-pathways", + "host": [ + "{{hostUrl}}" + ], + "path": [ + "api", + "v1", + "gtfs-pathways" + ] + }, + "description": "should throw a bad request if data source is not specified" + }, + "response": [] + }, + { + "name": "invalid-data-source", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "pm.test(\"Body matches string\", function () {", + " pm.expect(pm.response.text()).to.include(\"data_source\");", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "meta", + "value": "{{pathway-invalid-data-source}}", + "type": "text" + }, + { + "key": "file", + "type": "file", + "src": "success_1_all_attrs.zip" + } + ] + }, + "url": { + "raw": "{{hostUrl}}/api/v1/gtfs-pathways", + "host": [ + "{{hostUrl}}" + ], + "path": [ + "api", + "v1", + "gtfs-pathways" + ] + }, + "description": "Should throw a bad request if the data source is invalid and not in the list" + }, + "response": [] + }, + { + "name": "no-pathway-schema", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "pm.test(\"Body matches string\", function () {", + " pm.expect(pm.response.text()).to.include(\"pathwaysSchemaVersion\");", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "meta", + "value": "{{pathway-no-schema}}", + "type": "text" + }, + { + "key": "file", + "type": "file", + "src": "success_1_all_attrs.zip" + } + ] + }, + "url": { + "raw": "{{hostUrl}}/api/v1/gtfs-pathways", + "host": [ + "{{hostUrl}}" + ], + "path": [ + "api", + "v1", + "gtfs-pathways" + ] + }, + "description": "should throw a bad request if flex-schema is not added" + }, + "response": [] + }, + { + "name": "invalid-pathway-schema", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 400\", function () {", + " pm.response.to.have.status(400);", + "});", + "pm.test(\"Body matches string\", function () {", + " pm.expect(pm.response.text()).to.include(\"pathways_schema_version\");", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "meta", + "value": "{{pathway-invalid-schema}}", + "type": "text" + }, + { + "key": "file", + "type": "file", + "src": "success_1_all_attrs.zip" + } + ] + }, + "url": { + "raw": "{{hostUrl}}/api/v1/gtfs-pathways", + "host": [ + "{{hostUrl}}" + ], + "path": [ + "api", + "v1", + "gtfs-pathways" + ] + }, + "description": "should throw an invalid flex schema error if the flex schema is not in the given list" + }, + "response": [] + }, + { + "name": "pathway-success", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 202\", function () {", + " pm.response.to.have.status(202);", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "formdata", + "formdata": [ + { + "key": "meta", + "value": "{{pathway-valid}}", + "type": "text" + }, + { + "key": "file", + "type": "file", + "src": "success_1_all_attrs.zip" + } + ] + }, + "url": { + "raw": "{{hostUrl}}/api/v1/gtfs-pathways", + "host": [ + "{{hostUrl}}" + ], + "path": [ + "api", + "v1", + "gtfs-pathways" + ] + }, + "description": "Should give out success if the valid parameters are sent" + }, + "response": [] + } + ], + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{access_token}}", + "type": "string" + } + ] + }, + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ] + }, + { + "name": "Authenticate", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", () => {", + "", + " pm.expect(pm.response.code).to.eql(200);", + "", + " pm.test(\"Access token is valid\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.access_token).to.be.a('string')", + " pm.expect(jsonData.expires_in).to.be.a('number')", + " pm.expect(jsonData.refresh_expires_in).to.be.a('number')", + " pm.expect(jsonData.refresh_token).to.be.a('string')", + " pm.collectionVariables.set('access_token',jsonData.access_token)", + " });", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"username\":\"nareshd@gaussiansolutions.com\",\n \"password\":\"flexdg\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{hostUrl}}/api/v1/authenticate", + "host": [ + "{{hostUrl}}" + ], + "path": [ + "api", + "v1", + "authenticate" + ] + } + }, + "response": [] + }, + { + "name": "Status of file", + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "Bearer {{access_token}}", + "type": "text" + } + ], + "url": { + "raw": "{{hostUrl}}/api/v1/status?tdeiRecordId=691267863e774a27936588c727e27441", + "host": [ + "{{hostUrl}}" + ], + "path": [ + "api", + "v1", + "status" + ], + "query": [ + { + "key": "tdeiRecordId", + "value": "691267863e774a27936588c727e27441" + } + ] + } + }, + "response": [] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ], + "variable": [ + { + "key": "flex-collected-by", + "value": "{\n \"tdei_project_group_id\": \"5e339544-3b12-40a5-8acd-78c66d1fa981\",\n \"tdei_service_id\": \"333\",\n \"collected_by\": \"morethan50charsmorethan50charsmorethan50charsmorethan50charsmorethan50charsmorethan50chars\",\n \"collection_date\": \"2023-03-02T04:22:42.493Z\",\n \"collection_method\": \"manual\",\n \"valid_from\": \"2023-03-02T04:22:42.493Z\",\n \"valid_to\": \"2023-03-02T04:22:42.493Z\",\n \"data_source\": \"TDEITools\",\n \"polygon\": {\n \"coordinates\": [\n [\n [\n 77.58700584031209,\n 12.97544246408998\n ],\n [\n 77.58670678771239,\n 12.974635462667848\n ],\n [\n 77.58782248394829,\n 12.974489753799247\n ],\n [\n 77.58813303857153,\n 12.97529675569426\n ],\n [\n 77.58700584031209,\n 12.97544246408998\n ]]]\n },\n \"flex_schema_version\": \"v2.0\"\n}", + "type": "string" + }, + { + "key": "flex-no-collection-date", + "value": "{\n \"tdei_project_group_id\": \"5e339544-3b12-40a5-8acd-78c66d1fa981\",\n \"tdei_service_id\": \"333\",\n \"collected_by\": \"testuser\",\n \"collection_date\": null,\n \"collection_method\": \"manual\",\n \"valid_from\": \"2023-03-02T04:22:42.493Z\",\n \"valid_to\": \"2023-03-02T04:22:42.493Z\",\n \"data_source\": \"TDEITools\",\n \"polygon\": {\n \"coordinates\": [\n [\n [\n 77.58700584031209,\n 12.97544246408998\n ],\n [\n 77.58670678771239,\n 12.974635462667848\n ],\n [\n 77.58782248394829,\n 12.974489753799247\n ],\n [\n 77.58813303857153,\n 12.97529675569426\n ],\n [\n 77.58700584031209,\n 12.97544246408998\n ]]]\n },\n \"flex_schema_version\": \"v2.0\"\n }", + "type": "string" + }, + { + "key": "flex-collection-date-future", + "value": "{\n \"tdei_project_group_id\": \"5e339544-3b12-40a5-8acd-78c66d1fa981\",\n \"tdei_service_id\": \"333\",\n \"collected_by\": \"testuser\",\n \"collection_date\": \"2025-03-02T04:22:42.493Z\",\n \"collection_method\": \"manual\",\n \"valid_from\": \"2023-03-02T04:22:42.493Z\",\n \"valid_to\": \"2023-03-02T04:22:42.493Z\",\n \"data_source\": \"TDEITools\",\n \"polygon\": {\n \"coordinates\": [\n [\n [\n 77.58700584031209,\n 12.97544246408998\n ],\n [\n 77.58670678771239,\n 12.974635462667848\n ],\n [\n 77.58782248394829,\n 12.974489753799247\n ],\n [\n 77.58813303857153,\n 12.97529675569426\n ],\n [\n 77.58700584031209,\n 12.97544246408998\n ]]]\n },\n \"flex_schema_version\": \"v2.0\"\n }", + "type": "string" + }, + { + "key": "flex-no-collection-method", + "value": "{\n \"tdei_project_group_id\": \"5e339544-3b12-40a5-8acd-78c66d1fa981\",\n \"tdei_service_id\": \"333\",\n \"collected_by\": \"testuser\",\n \"collection_date\": \"2023-03-02T04:22:42.493Z\",\n \"collection_method\": null,\n \"valid_from\": \"2023-03-02T04:22:42.493Z\",\n \"valid_to\": \"2023-03-02T04:22:42.493Z\",\n \"data_source\": \"TDEITools\",\n \"polygon\": {\n \"coordinates\": [\n [\n [\n 77.58700584031209,\n 12.97544246408998\n ],\n [\n 77.58670678771239,\n 12.974635462667848\n ],\n [\n 77.58782248394829,\n 12.974489753799247\n ],\n [\n 77.58813303857153,\n 12.97529675569426\n ],\n [\n 77.58700584031209,\n 12.97544246408998\n ]]]\n },\n \"flex_schema_version\": \"v2.0\"\n }", + "type": "string" + }, + { + "key": "flex-invalid-collection-method", + "value": "{\n \"tdei_project_group_id\": \"5e339544-3b12-40a5-8acd-78c66d1fa981\",\n \"tdei_service_id\": \"333\",\n \"collected_by\": \"testuser\",\n \"collection_date\": \"2023-03-02T04:22:42.493Z\",\n \"collection_method\": \"planted\",\n \"valid_from\": \"2023-03-02T04:22:42.493Z\",\n \"valid_to\": \"2023-03-02T04:22:42.493Z\",\n \"data_source\": \"TDEITools\",\n \"polygon\": {\n \"coordinates\": [\n [\n [\n 77.58700584031209,\n 12.97544246408998\n ],\n [\n 77.58670678771239,\n 12.974635462667848\n ],\n [\n 77.58782248394829,\n 12.974489753799247\n ],\n [\n 77.58813303857153,\n 12.97529675569426\n ],\n [\n 77.58700584031209,\n 12.97544246408998\n ]]]\n },\n \"flex_schema_version\": \"v2.0\"\n }", + "type": "string" + }, + { + "key": "flex-no-data-source", + "value": "{\n \"tdei_project_group_id\": \"5e339544-3b12-40a5-8acd-78c66d1fa981\",\n \"tdei_service_id\": \"333\",\n \"collected_by\": \"testuser\",\n \"collection_date\": \"2023-03-02T04:22:42.493Z\",\n \"collection_method\": \"manual\",\n \"valid_from\": \"2023-03-02T04:22:42.493Z\",\n \"valid_to\": \"2023-03-02T04:22:42.493Z\",\n \"data_source\": null,\n \"polygon\": {\n \"coordinates\": [\n [\n [\n 77.58700584031209,\n 12.97544246408998\n ],\n [\n 77.58670678771239,\n 12.974635462667848\n ],\n [\n 77.58782248394829,\n 12.974489753799247\n ],\n [\n 77.58813303857153,\n 12.97529675569426\n ],\n [\n 77.58700584031209,\n 12.97544246408998\n ]]]\n },\n \"flex_schema_version\": \"v2.0\"\n }", + "type": "string" + }, + { + "key": "flex-invalid-data-source", + "value": "{\n \"tdei_project_group_id\": \"5e339544-3b12-40a5-8acd-78c66d1fa981\",\n \"tdei_service_id\": \"333\",\n \"collected_by\": \"testuser\",\n \"collection_date\": \"2023-03-02T04:22:42.493Z\",\n \"collection_method\": \"manual\",\n \"valid_from\": \"2023-03-02T04:22:42.493Z\",\n \"valid_to\": \"2023-03-02T04:22:42.493Z\",\n \"data_source\": \"webapp\",\n \"polygon\": {\n \"coordinates\": [\n [\n [\n 77.58700584031209,\n 12.97544246408998\n ],\n [\n 77.58670678771239,\n 12.974635462667848\n ],\n [\n 77.58782248394829,\n 12.974489753799247\n ],\n [\n 77.58813303857153,\n 12.97529675569426\n ],\n [\n 77.58700584031209,\n 12.97544246408998\n ]]]\n },\n \"flex_schema_version\": \"v2.0\"\n }", + "type": "string" + }, + { + "key": "flex-no-schema", + "value": "{\n \"tdei_project_group_id\": \"5e339544-3b12-40a5-8acd-78c66d1fa981\",\n \"tdei_service_id\": \"333\",\n \"collected_by\": \"testuser\",\n \"collection_date\": \"2023-03-02T04:22:42.493Z\",\n \"collection_method\": \"manual\",\n \"valid_from\": \"2023-03-02T04:22:42.493Z\",\n \"valid_to\": \"2023-03-02T04:22:42.493Z\",\n \"data_source\": \"TDEITools\",\n \"polygon\": {\n \"coordinates\": [\n [\n [\n 77.58700584031209,\n 12.97544246408998\n ],\n [\n 77.58670678771239,\n 12.974635462667848\n ],\n [\n 77.58782248394829,\n 12.974489753799247\n ],\n [\n 77.58813303857153,\n 12.97529675569426\n ],\n [\n 77.58700584031209,\n 12.97544246408998\n ]]]\n },\n \"flex_schema_version\": null\n }", + "type": "string" + }, + { + "key": "flex-invalid-schema", + "value": "{\n \"tdei_project_group_id\": \"5e339544-3b12-40a5-8acd-78c66d1fa981\",\n \"tdei_service_id\": \"333\",\n \"collected_by\": \"testuser\",\n \"collection_date\": \"2023-03-02T04:22:42.493Z\",\n \"collection_method\": \"manual\",\n \"valid_from\": \"2023-03-02T04:22:42.493Z\",\n \"valid_to\": \"2023-03-02T04:22:42.493Z\",\n \"data_source\": \"TDEITools\",\n \"polygon\": {\n \"coordinates\": [\n [\n [\n 77.58700584031209,\n 12.97544246408998\n ],\n [\n 77.58670678771239,\n 12.974635462667848\n ],\n [\n 77.58782248394829,\n 12.974489753799247\n ],\n [\n 77.58813303857153,\n 12.97529675569426\n ],\n [\n 77.58700584031209,\n 12.97544246408998\n ]]]\n },\n \"flex_schema_version\": \"2.0.0\"\n }", + "type": "string" + }, + { + "key": "flex-valid", + "value": "{\n \"tdei_project_group_id\": \"5e339544-3b12-40a5-8acd-78c66d1fa981\",\n \"tdei_service_id\": \"333\",\n \"collected_by\": \"testuser\",\n \"collection_date\": \"2023-03-02T04:22:42.493Z\",\n \"collection_method\": \"manual\",\n \"valid_from\": \"2023-03-02T04:22:42.493Z\",\n \"valid_to\": \"2023-03-02T04:22:42.493Z\",\n \"data_source\": \"TDEITools\",\n \"polygon\": {\n \"coordinates\": [\n [\n [\n 77.58700584031209,\n 12.97544246408998\n ],\n [\n 77.58670678771239,\n 12.974635462667848\n ],\n [\n 77.58782248394829,\n 12.974489753799247\n ],\n [\n 77.58813303857153,\n 12.97529675569426\n ],\n [\n 77.58700584031209,\n 12.97544246408998\n ]]]\n },\n \"flex_schema_version\": \"v2.0\"\n }", + "type": "string" + }, + { + "key": "pathway-collected-by", + "value": "{\n \"tdei_project_group_id\": \"5e339544-3b12-40a5-8acd-78c66d1fa981\",\n \"tdei_station_id\": \"333\",\n \"collected_by\": \"morethan50charsmorethan50charsmorethan50charsmorethan50charsmorethan50charsmorethan50chars\",\n \"collection_date\": \"2023-03-02T04:22:42.493Z\",\n \"collection_method\": \"manual\",\n \"valid_from\": \"2023-03-02T04:22:42.493Z\",\n \"valid_to\": \"2023-03-02T04:22:42.493Z\",\n \"data_source\": \"TDEITools\",\n \"polygon\": {\n \"coordinates\": [\n [\n [\n 77.58700584031209,\n 12.97544246408998\n ],\n [\n 77.58670678771239,\n 12.974635462667848\n ],\n [\n 77.58782248394829,\n 12.974489753799247\n ],\n [\n 77.58813303857153,\n 12.97529675569426\n ],\n [\n 77.58700584031209,\n 12.97544246408998\n ]]]\n },\n \"pathways_schema_version\": \"v1.0\"\n}", + "type": "string" + }, + { + "key": "pathway-no-collection-date", + "value": "{\n \"tdei_project_group_id\": \"5e339544-3b12-40a5-8acd-78c66d1fa981\",\n \"tdei_station_id\": \"333\",\n \"collected_by\": \"testuser\",\n \"collection_date\": null,\n \"collection_method\": \"manual\",\n \"valid_from\": \"2023-03-02T04:22:42.493Z\",\n \"valid_to\": \"2023-03-02T04:22:42.493Z\",\n \"data_source\": \"TDEITools\",\n \"polygon\": {\n \"coordinates\": [\n [\n [\n 77.58700584031209,\n 12.97544246408998\n ],\n [\n 77.58670678771239,\n 12.974635462667848\n ],\n [\n 77.58782248394829,\n 12.974489753799247\n ],\n [\n 77.58813303857153,\n 12.97529675569426\n ],\n [\n 77.58700584031209,\n 12.97544246408998\n ]]]\n },\n \"pathways_schema_version\": \"v1.0\"\n }", + "type": "string" + }, + { + "key": "pathway-collection-date-future", + "value": "{\n \"tdei_project_group_id\": \"5e339544-3b12-40a5-8acd-78c66d1fa981\",\n \"tdei_station_id\": \"333\",\n \"collected_by\": \"testuser\",\n \"collection_date\": \"2025-03-02T04:22:42.493Z\",\n \"collection_method\": \"manual\",\n \"valid_from\": \"2023-03-02T04:22:42.493Z\",\n \"valid_to\": \"2023-03-02T04:22:42.493Z\",\n \"data_source\": \"TDEITools\",\n \"polygon\": {\n \"coordinates\": [\n [\n [\n 77.58700584031209,\n 12.97544246408998\n ],\n [\n 77.58670678771239,\n 12.974635462667848\n ],\n [\n 77.58782248394829,\n 12.974489753799247\n ],\n [\n 77.58813303857153,\n 12.97529675569426\n ],\n [\n 77.58700584031209,\n 12.97544246408998\n ]]]\n },\n \"pathways_schema_version\": \"v1.0\"\n }", + "type": "string" + }, + { + "key": "pathway-no-collection-method", + "value": "{\n \"tdei_project_group_id\": \"5e339544-3b12-40a5-8acd-78c66d1fa981\",\n \"tdei_station_id\": \"333\",\n \"collected_by\": \"testuser\",\n \"collection_date\": \"2023-03-02T04:22:42.493Z\",\n \"collection_method\": null,\n \"valid_from\": \"2023-03-02T04:22:42.493Z\",\n \"valid_to\": \"2023-03-02T04:22:42.493Z\",\n \"data_source\": \"TDEITools\",\n \"polygon\": {\n \"coordinates\": [\n [\n [\n 77.58700584031209,\n 12.97544246408998\n ],\n [\n 77.58670678771239,\n 12.974635462667848\n ],\n [\n 77.58782248394829,\n 12.974489753799247\n ],\n [\n 77.58813303857153,\n 12.97529675569426\n ],\n [\n 77.58700584031209,\n 12.97544246408998\n ]]]\n },\n \"pathways_schema_version\": \"v1.0\"\n }", + "type": "string" + }, + { + "key": "pathway-invalid-collection-method", + "value": "{\n \"tdei_project_group_id\": \"5e339544-3b12-40a5-8acd-78c66d1fa981\",\n \"tdei_station_id\": \"333\",\n \"collected_by\": \"testuser\",\n \"collection_date\": \"2023-03-02T04:22:42.493Z\",\n \"collection_method\": \"planted\",\n \"valid_from\": \"2023-03-02T04:22:42.493Z\",\n \"valid_to\": \"2023-03-02T04:22:42.493Z\",\n \"data_source\": \"TDEITools\",\n \"polygon\": {\n \"coordinates\": [\n [\n [\n 77.58700584031209,\n 12.97544246408998\n ],\n [\n 77.58670678771239,\n 12.974635462667848\n ],\n [\n 77.58782248394829,\n 12.974489753799247\n ],\n [\n 77.58813303857153,\n 12.97529675569426\n ],\n [\n 77.58700584031209,\n 12.97544246408998\n ]]]\n },\n \"pathways_schema_version\": \"v1.0\"\n }", + "type": "string" + }, + { + "key": "pathway-no-data-source", + "value": "{\n \"tdei_project_group_id\": \"5e339544-3b12-40a5-8acd-78c66d1fa981\",\n \"tdei_station_id\": \"333\",\n \"collected_by\": \"testuser\",\n \"collection_date\": \"2023-03-02T04:22:42.493Z\",\n \"collection_method\": \"manual\",\n \"valid_from\": \"2023-03-02T04:22:42.493Z\",\n \"valid_to\": \"2023-03-02T04:22:42.493Z\",\n \"data_source\": null,\n \"polygon\": {\n \"coordinates\": [\n [\n [\n 77.58700584031209,\n 12.97544246408998\n ],\n [\n 77.58670678771239,\n 12.974635462667848\n ],\n [\n 77.58782248394829,\n 12.974489753799247\n ],\n [\n 77.58813303857153,\n 12.97529675569426\n ],\n [\n 77.58700584031209,\n 12.97544246408998\n ]]]\n },\n \"pathways_schema_version\": \"v1.0\"\n }", + "type": "string" + }, + { + "key": "pathway-invalid-data-source", + "value": "{\n \"tdei_project_group_id\": \"5e339544-3b12-40a5-8acd-78c66d1fa981\",\n \"tdei_station_id\": \"333\",\n \"collected_by\": \"testuser\",\n \"collection_date\": \"2023-03-02T04:22:42.493Z\",\n \"collection_method\": \"manual\",\n \"valid_from\": \"2023-03-02T04:22:42.493Z\",\n \"valid_to\": \"2023-03-02T04:22:42.493Z\",\n \"data_source\": \"webapp\",\n \"polygon\": {\n \"coordinates\": [\n [\n [\n 77.58700584031209,\n 12.97544246408998\n ],\n [\n 77.58670678771239,\n 12.974635462667848\n ],\n [\n 77.58782248394829,\n 12.974489753799247\n ],\n [\n 77.58813303857153,\n 12.97529675569426\n ],\n [\n 77.58700584031209,\n 12.97544246408998\n ]]]\n },\n \"pathways_schema_version\": \"v1.0\"\n }", + "type": "string" + }, + { + "key": "pathway-no-schema", + "value": "{\n \"tdei_project_group_id\": \"5e339544-3b12-40a5-8acd-78c66d1fa981\",\n \"tdei_station_id\": \"333\",\n \"collected_by\": \"testuser\",\n \"collection_date\": \"2023-03-02T04:22:42.493Z\",\n \"collection_method\": \"manual\",\n \"valid_from\": \"2023-03-02T04:22:42.493Z\",\n \"valid_to\": \"2023-03-02T04:22:42.493Z\",\n \"data_source\": \"TDEITools\",\n \"polygon\": {\n \"coordinates\": [\n [\n [\n 77.58700584031209,\n 12.97544246408998\n ],\n [\n 77.58670678771239,\n 12.974635462667848\n ],\n [\n 77.58782248394829,\n 12.974489753799247\n ],\n [\n 77.58813303857153,\n 12.97529675569426\n ],\n [\n 77.58700584031209,\n 12.97544246408998\n ]]]\n },\n \"pathways_schema_version\": null\n }", + "type": "string" + }, + { + "key": "pathway-invalid-schema", + "value": "{\n \"tdei_project_group_id\": \"5e339544-3b12-40a5-8acd-78c66d1fa981\",\n \"tdei_station_id\": \"333\",\n \"collected_by\": \"testuser\",\n \"collection_date\": \"2023-03-02T04:22:42.493Z\",\n \"collection_method\": \"manual\",\n \"valid_from\": \"2023-03-02T04:22:42.493Z\",\n \"valid_to\": \"2023-03-02T04:22:42.493Z\",\n \"data_source\": \"TDEITools\",\n \"polygon\": {\n \"coordinates\": [\n [\n [\n 77.58700584031209,\n 12.97544246408998\n ],\n [\n 77.58670678771239,\n 12.974635462667848\n ],\n [\n 77.58782248394829,\n 12.974489753799247\n ],\n [\n 77.58813303857153,\n 12.97529675569426\n ],\n [\n 77.58700584031209,\n 12.97544246408998\n ]]]\n },\n \"pathways_schema_version\": \"1.0.0\"\n }", + "type": "string" + }, + { + "key": "pathway-valid", + "value": "{\n \"tdei_project_group_id\": \"5e339544-3b12-40a5-8acd-78c66d1fa981\",\n \"tdei_station_id\": \"333\",\n \"collected_by\": \"testuser\",\n \"collection_date\": \"2023-03-02T04:22:42.493Z\",\n \"collection_method\": \"manual\",\n \"valid_from\": \"2023-03-02T04:22:42.493Z\",\n \"valid_to\": \"2023-03-02T04:22:42.493Z\",\n \"data_source\": \"TDEITools\",\n \"polygon\": {\n \"coordinates\": [\n [\n [\n 77.58700584031209,\n 12.97544246408998\n ],\n [\n 77.58670678771239,\n 12.974635462667848\n ],\n [\n 77.58782248394829,\n 12.974489753799247\n ],\n [\n 77.58813303857153,\n 12.97529675569426\n ],\n [\n 77.58700584031209,\n 12.97544246408998\n ]]]\n },\n \"pathways_schema_version\": \"v1.0\"\n }", + "type": "string" + }, + { + "key": "hostUrl", + "value": "https://tdei-gateway-dev.azurewebsites.net", + "type": "string" + }, + { + "key": "access_token", + "value": "", + "type": "string" + } + ] +} \ No newline at end of file diff --git a/assets/postman/how-to-test.md b/assets/postman/how-to-test.md new file mode 100644 index 0000000..d09a69a --- /dev/null +++ b/assets/postman/how-to-test.md @@ -0,0 +1,16 @@ +# Testing the metadata validation postman +- Import the collection to your postman +- Pre-run the `Authenticate` call to ensure that there is access token +- The .zip files needed for upload are available in [payloads](../payloads/) folder +- For flex, use [valid-flex-zip-file](../payloads/gtfs-flex/files/otterexpress-mn-us--flex-v2.zip) +- For pathways, use [valid-pathway-file](../payloads/gtfs-pathways/files/gtfs-pathways-valid.zip) +- Run either of the folders to run all the tests of that specific file type of files + + +# Testing with different credentials +- If you are testing with different credentials, change the following variables in the collection variables payloads + - tdei_project_group_id + - station_id + - service_id + +- To know the status of the succesfully uploaded file, call `Status of file` API to know the actual status of the file. \ No newline at end of file diff --git a/assets/tdei_logo.png b/assets/tdei_logo.png new file mode 100644 index 0000000..9369d69 Binary files /dev/null and b/assets/tdei_logo.png differ diff --git a/global.d.ts b/global.d.ts new file mode 100644 index 0000000..36c37a4 --- /dev/null +++ b/global.d.ts @@ -0,0 +1,10 @@ +// global.d.ts +declare global { + namespace NodeJS { + interface Global { + seedData: SeedData; // Replace 'any' with the actual type of your seed data + } + } +} + +export { }; \ No newline at end of file diff --git a/jest.config.ts b/jest.config.ts index af4a4ca..bdb17a2 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -1,18 +1,31 @@ -import type {Config} from 'jest'; +import type { Config } from 'jest'; -export default async (): Promise=>{ +export default async (): Promise => { return { - verbose:true, - preset:'ts-jest', - testEnvironment:'node', - reporters:[ + globalSetup: './src/global.setup.ts', + maxWorkers: 1, + verbose: false, + preset: 'ts-jest', + testEnvironment: 'node', + testTimeout: 15000, + setupFilesAfterEnv: ["./jest.setup.ts"], + reporters: [ "default", - ["./node_modules/jest-html-reporter",{ - "pageTitle":"Test Report" + ["jest-html-reporters", { + "filename": "test-report.html", + "urlForTestFiles": "https://github.com/TaskarCenterAtUW/TDEI-api-tester/tree/dev", + "enableMergeData": true, + "inlineSource": true, + "pageTitle": `TDEI API Test Report - ${new Date().toLocaleString()}`, + "logoImgPath": "assets/tdei_logo.png", + "customInfos": [{ + "title": "Project", + "value": "TDEI API Tester" + }] }] ], - transform:{ - '^.+\\.(ts|tsx)?$':'ts-jest' + transform: { + '^.+\\.(ts|tsx)?$': 'ts-jest' } } } \ No newline at end of file diff --git a/jest.setup.ts b/jest.setup.ts new file mode 100644 index 0000000..7e7a389 --- /dev/null +++ b/jest.setup.ts @@ -0,0 +1,47 @@ +import * as matchers from 'jest-extended'; + +expect.extend(matchers); +expect.extend({ + toBeNullOrString(received) { + const pass = received === undefined || received === null || typeof received === 'string'; + if (pass) { + return { + message: () => `expected ${received} not to be absent, null, or a string`, + pass: true, + }; + } else { + return { + message: () => `expected ${received} to be absent, null, or a string`, + pass: false, + }; + } + }, +}); + +expect.extend({ + toBeAbsentOrNullOrString(received) { + const pass = received === undefined || received === null || typeof received === 'string'; + if (pass) { + return { + message: () => `expected ${received} not to be absent, null, or a string`, + pass: true, + }; + } else { + return { + message: () => `expected ${received} to be absent, null, or a string`, + pass: false, + }; + } + }, +}); + +process.on('unhandledRejection', (reason, promise) => { + console.error('Unhandled Rejection at:', promise, 'reason:', reason); + // Optionally, you can fail the test if there's an unhandled rejection + throw reason; +}); + +process.on('uncaughtException', (error) => { + console.error('Uncaught Exception thrown', error); + process.exit(1); +}); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index cefd9a1..7a1cc7e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,13 +9,21 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "axios": "1.3.5", - "tdei-client": "git+https://github.com/TaskarCenterAtUW/TDEI-api-client.git", + "@faker-js/faker": "^7.6.0", + "axios": "^1.7.7", + "dotenv": "^16.3.1", + "jest": "^29.7.0", + "jest-html-reporters": "^3.1.7", + "puppeteer": "^22.6.5", + "tdei-client": "git+https://github.com/TaskarCenterAtUW/TDEI-api-client.git#1b646f12d6d6f14378395d8ee9fa54cff30dfe07", "typescript": "5.0.4" }, "devDependencies": { + "@types/adm-zip": "0.5.0", "@types/jest": "29.5.0", "@types/node": "18.15.11", + "adm-zip": "0.5.10", + "jest-extended": "^4.0.2", "jest-html-reporter": "3.7.1", "rimraf": "^3.0.2", "ts-jest": "29.1.0", @@ -26,7 +34,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", - "dev": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" @@ -36,47 +43,46 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", - "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", - "dev": true, + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", "dependencies": { - "@babel/highlight": "^7.18.6" + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.4.tgz", - "integrity": "sha512-/DYyDpeCfaVinT40FPGdkkb+lYSKvsVuMjDAG7jPOWWiM1ibOaB9CXJAlc4d1QpP/U2q2P9jbrSlClKSErd55g==", - "dev": true, + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz", + "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.4.tgz", - "integrity": "sha512-qt/YV149Jman/6AfmlxJ04LMIu8bMoyl3RB91yTFrxQmgbrSvQMy7cI8Q62FHx1t8wJ8B5fu0UDoLwHAhUo1QA==", - "dev": true, + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz", + "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.21.4", - "@babel/helper-compilation-targets": "^7.21.4", - "@babel/helper-module-transforms": "^7.21.2", - "@babel/helpers": "^7.21.0", - "@babel/parser": "^7.21.4", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.4", - "@babel/types": "^7.21.4", - "convert-source-map": "^1.7.0", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.10", + "@babel/helper-compilation-targets": "^7.26.5", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.10", + "@babel/parser": "^7.26.10", + "@babel/template": "^7.26.9", + "@babel/traverse": "^7.26.10", + "@babel/types": "^7.26.10", + "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", - "semver": "^6.3.0" + "json5": "^2.2.3", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -86,22 +92,16 @@ "url": "https://opencollective.com/babel" } }, - "node_modules/@babel/core/node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true - }, "node_modules/@babel/generator": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.4.tgz", - "integrity": "sha512-NieM3pVIYW2SwGzKoqfPrQsf4xGs9M9AIG3ThppsSRmO+m7eQhmI6amajKMUeIO37wFfsvnvcxQFx6x6iqxDnA==", - "dev": true, + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.10.tgz", + "integrity": "sha512-rRHT8siFIXQrAYOYqZQVsAr8vJ+cBNqcVAY6m5V8/4QqzaPl+zDBe6cLEPRDuNOUf3ww8RfJVlOyQMoSI+5Ang==", "dependencies": { - "@babel/types": "^7.21.4", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" + "@babel/parser": "^7.26.10", + "@babel/types": "^7.26.10", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" }, "engines": { "node": ">=6.9.0" @@ -120,51 +120,47 @@ } }, "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz", - "integrity": "sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.21.5.tgz", + "integrity": "sha512-uNrjKztPLkUk7bpCNC0jEKDJzzkvel/W+HguzbN8krA+LPfC1CEobJEvAvGka2A/M+ViOqXdcRL0GqPUJSjx9g==", "dev": true, "dependencies": { - "@babel/helper-explode-assignable-expression": "^7.18.6", - "@babel/types": "^7.18.9" + "@babel/types": "^7.21.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.21.4.tgz", - "integrity": "sha512-Fa0tTuOXZ1iL8IeDFUWCzjZcn+sJGd9RZdH9esYVjEejGmzf+FFYQpMi/kZUk2kPy/q1H3/GPw7np8qar/stfg==", - "dev": true, + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz", + "integrity": "sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==", "dependencies": { - "@babel/compat-data": "^7.21.4", - "@babel/helper-validator-option": "^7.21.0", - "browserslist": "^4.21.3", + "@babel/compat-data": "^7.26.5", + "@babel/helper-validator-option": "^7.25.9", + "browserslist": "^4.24.0", "lru-cache": "^5.1.1", - "semver": "^6.3.0" + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.21.4.tgz", - "integrity": "sha512-46QrX2CQlaFRF4TkwfTt6nJD7IHq8539cCL7SDpqWSDeJKY1xylKKY5F/33mJhLZ3mFvKv2gGrVS6NkyF6qs+Q==", + "version": "7.21.8", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.21.8.tgz", + "integrity": "sha512-+THiN8MqiH2AczyuZrnrKL6cAxFRRQDKW9h1YkBvbgKmAm6mwiacig1qT73DHIWMGo40GRnsEfN3LA+E6NtmSw==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-environment-visitor": "^7.21.5", "@babel/helper-function-name": "^7.21.0", - "@babel/helper-member-expression-to-functions": "^7.21.0", + "@babel/helper-member-expression-to-functions": "^7.21.5", "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/helper-replace-supers": "^7.20.7", + "@babel/helper-replace-supers": "^7.21.5", "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", - "@babel/helper-split-export-declaration": "^7.18.6" + "@babel/helper-split-export-declaration": "^7.18.6", + "semver": "^6.3.0" }, "engines": { "node": ">=6.9.0" @@ -174,13 +170,14 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.21.4.tgz", - "integrity": "sha512-M00OuhU+0GyZ5iBBN9czjugzWrEq2vDpf/zCYHxxf93ul/Q5rv+a5h+/+0WnI1AebHNVtl5bFV0qsJoH23DbfA==", + "version": "7.21.8", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.21.8.tgz", + "integrity": "sha512-zGuSdedkFtsFHGbexAvNuipg1hbtitDLo2XE8/uf6Y9sOQV1xsYX/2pNbtedp/X0eU1pIt+kGvaqHCowkRbS5g==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.18.6", - "regexpu-core": "^5.3.1" + "regexpu-core": "^5.3.1", + "semver": "^6.3.0" }, "engines": { "node": ">=6.9.0" @@ -207,92 +204,77 @@ } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-explode-assignable-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz", - "integrity": "sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", - "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dev": true, "dependencies": { - "@babel/template": "^7.20.7", - "@babel/types": "^7.21.0" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", "dev": true, "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.21.0.tgz", - "integrity": "sha512-Muu8cdZwNN6mRRNG6lAYErJ5X3bRevgYR2O8wN0yn7jJSnGDu6eG59RfT29JHxGUovyfrh6Pj0XzmR7drNVL3Q==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.21.5.tgz", + "integrity": "sha512-nIcGfgwpH2u4n9GG1HpStW5Ogx7x7ekiFHbjjFRKXbn5zUvqO9ZgotCO4x1aNbKn/x/xOUaXEhyNHCwtFCpxWg==", "dev": true, "dependencies": { - "@babel/types": "^7.21.0" + "@babel/types": "^7.21.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz", - "integrity": "sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", "dependencies": { - "@babel/types": "^7.21.4" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz", - "integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==", - "dev": true, + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.20.2", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.2", - "@babel/types": "^7.21.2" + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-optimise-call-expression": { @@ -308,10 +290,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", - "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==", - "dev": true, + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.21.5.tgz", + "integrity": "sha512-0WDaIlXKOX/3KfBK/dwP1oQGiPh6rjMkT7HIRv7i5RR2VUMwrx5ZL0dwBkKx7+SW1zwNdgjHd34IMk5ZjTeHVg==", "engines": { "node": ">=6.9.0" } @@ -335,29 +316,29 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.20.7.tgz", - "integrity": "sha512-vujDMtB6LVfNW13jhlCrp48QNslK6JXi7lQG736HVbHz/mbf4Dc7tIRh1Xf5C0rF7BP8iiSxGMCmY6Ci1ven3A==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.21.5.tgz", + "integrity": "sha512-/y7vBgsr9Idu4M6MprbOVUfH3vs7tsIfnVWv/Ml2xgwvyH6LTngdfbf5AdsKwkJy4zgy1X/kuNrEKvhhK28Yrg==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-member-expression-to-functions": "^7.20.7", + "@babel/helper-environment-visitor": "^7.21.5", + "@babel/helper-member-expression-to-functions": "^7.21.5", "@babel/helper-optimise-call-expression": "^7.18.6", "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.7", - "@babel/types": "^7.20.7" + "@babel/traverse": "^7.21.5", + "@babel/types": "^7.21.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-simple-access": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", - "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.21.5.tgz", + "integrity": "sha512-ENPDAMC1wAjR0uaCUwliBdiSl1KBJAVnMTzXqi64c2MG8MPR6ii4qf7bSXDqSFbr4W6W028/rf5ivoHop5/mkg==", "dev": true, "dependencies": { - "@babel/types": "^7.20.2" + "@babel/types": "^7.21.5" }, "engines": { "node": ">=6.9.0" @@ -376,40 +357,37 @@ } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", "dev": true, "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz", - "integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==", - "dev": true, + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", "engines": { "node": ">=6.9.0" } @@ -430,109 +408,24 @@ } }, "node_modules/@babel/helpers": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz", - "integrity": "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==", - "dev": true, - "dependencies": { - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.0", - "@babel/types": "^7.21.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", - "dev": true, + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.10.tgz", + "integrity": "sha512-UPYc3SauzZ3JGgj87GgZ89JVdC5dj0AoetR5Bw6wj4niittNyFh6+eOGonYvJ1ao6B8lEa3Q3klS7ADZ53bc5g==", "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" + "@babel/template": "^7.26.9", + "@babel/types": "^7.26.10" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, + "node_modules/@babel/parser": { + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.10.tgz", + "integrity": "sha512-6aQR2zGE/QFi8JpDLjUZEPYOs7+mhKXm86VaKFiLP35JQwQb6bwUE+XbvkH0EptsYhbNBSUGaUBLKqxH1xSgsA==", "dependencies": { - "has-flag": "^3.0.0" + "@babel/types": "^7.26.10" }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/parser": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.4.tgz", - "integrity": "sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==", - "dev": true, "bin": { "parser": "bin/babel-parser.js" }, @@ -825,7 +718,6 @@ "version": "7.8.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -837,8 +729,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "dev": true, - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -850,7 +740,6 @@ "version": "7.12.13", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.12.13" }, @@ -916,8 +805,6 @@ "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -929,7 +816,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -941,7 +827,6 @@ "version": "7.21.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.21.4.tgz", "integrity": "sha512-5hewiLct5OKyh6PLKEYaFclcqtIgCb6bmELouxjF6up5q3Sov7rOayW4RwhbaBL0dit8rA80GNfY+UuDp2mBbQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.20.2" }, @@ -956,7 +841,6 @@ "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -968,7 +852,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -980,7 +863,6 @@ "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, @@ -992,7 +874,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -1004,7 +885,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -1016,7 +896,6 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -1043,7 +922,6 @@ "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -1058,7 +936,6 @@ "version": "7.21.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.21.4.tgz", "integrity": "sha512-xz0D39NvhQn4t4RNsHmDnnsaQizIlUkdtYvLs8La1BlfjQ6JEwxkJGeqJMW2tAXx+q6H+WFuUTXNdYVpEya0YA==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.20.2" }, @@ -1070,12 +947,12 @@ } }, "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.20.7.tgz", - "integrity": "sha512-3poA5E7dzDomxj9WXWwuD6A5F3kc7VXwIJO+E+J8qtDtS+pXPAhrgEyh+9GBwBgPq1Z+bB+/JD60lp5jsN7JPQ==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.21.5.tgz", + "integrity": "sha512-wb1mhwGOCaXHDTcsRYMKF9e5bbMgqwxtqa2Y1ifH96dXJPwbuLX9qHy3clhrxVqgMz7nyNXs8VkxdH8UBcjKqA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" + "@babel/helper-plugin-utils": "^7.21.5" }, "engines": { "node": ">=6.9.0" @@ -1155,12 +1032,12 @@ } }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.20.7.tgz", - "integrity": "sha512-Lz7MvBK6DTjElHAmfu6bfANzKcxpyNPeYBGEafyA6E5HtRpjpZwU+u7Qrgz/2OR0z+5TvKYbPdphfSaAcZBrYQ==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.21.5.tgz", + "integrity": "sha512-TR653Ki3pAwxBxUe8srfF3e4Pe3FTA46uaNHYyQwIoM4oWKSoOZiDNyHJ0oIoDIUPSRQbQG7jzgVBX3FPVne1Q==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-plugin-utils": "^7.21.5", "@babel/template": "^7.20.7" }, "engines": { @@ -1233,12 +1110,12 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.21.0.tgz", - "integrity": "sha512-LlUYlydgDkKpIY7mcBWvyPPmMcOphEyYA27Ef4xpbh1IiDNLr0kZsos2nf92vz3IccvJI25QUwp86Eo5s6HmBQ==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.21.5.tgz", + "integrity": "sha512-nYWpjKW/7j/I/mZkGVgHJXh4bA1sfdFnJoOXwJuj4m3Q2EraO/8ZyrkCau9P5tbHQk01RMSt6KYLCsW7730SXQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" + "@babel/helper-plugin-utils": "^7.21.5" }, "engines": { "node": ">=6.9.0" @@ -1311,14 +1188,14 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.21.2.tgz", - "integrity": "sha512-Cln+Yy04Gxua7iPdj6nOV96smLGjpElir5YwzF0LBPKoPlLDNJePNlrGGaybAJkd0zKRnOVXOgizSqPYMNYkzA==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.21.5.tgz", + "integrity": "sha512-OVryBEgKUbtqMoB7eG2rs6UFexJi6Zj6FDXx+esBLPTCxCNxAY9o+8Di7IsUGJ+AVhp5ncK0fxWUBd0/1gPhrQ==", "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.21.2", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-simple-access": "^7.20.2" + "@babel/helper-module-transforms": "^7.21.5", + "@babel/helper-plugin-utils": "^7.21.5", + "@babel/helper-simple-access": "^7.21.5" }, "engines": { "node": ">=6.9.0" @@ -1439,12 +1316,12 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.20.5.tgz", - "integrity": "sha512-kW/oO7HPBtntbsahzQ0qSE3tFvkFwnbozz3NWFhLGqH75vLEg+sCGngLlhVkePlCs3Jv0dBBHDzCHxNiFAQKCQ==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.21.5.tgz", + "integrity": "sha512-ZoYBKDb6LyMi5yCsByQ5jmXsHAQDDYeexT1Szvlmui+lADvfSecr5Dxd/PkrTC3pAD182Fcju1VQkB4oCp9M+w==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-plugin-utils": "^7.21.5", "regenerator-transform": "^0.15.1" }, "engines": { @@ -1564,12 +1441,12 @@ } }, "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz", - "integrity": "sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.21.5.tgz", + "integrity": "sha512-LYm/gTOwZqsYohlvFUe/8Tujz75LqqVC2w+2qPHLR+WyWHGCZPN1KBpJCJn+4Bk4gOkQy/IXKIge6az5MqwlOg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" + "@babel/helper-plugin-utils": "^7.21.5" }, "engines": { "node": ">=6.9.0" @@ -1595,14 +1472,14 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.21.4.tgz", - "integrity": "sha512-2W57zHs2yDLm6GD5ZpvNn71lZ0B/iypSdIeq25OurDKji6AdzV07qp4s3n1/x5BqtiGaTrPN3nerlSCaC5qNTw==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.21.5.tgz", + "integrity": "sha512-wH00QnTTldTbf/IefEVyChtRdw5RJvODT/Vb4Vcxq1AZvtXj6T0YeX0cAcXhI6/BdGuiP3GcNIL4OQbI2DVNxg==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.21.4", - "@babel/helper-compilation-targets": "^7.21.4", - "@babel/helper-plugin-utils": "^7.20.2", + "@babel/compat-data": "^7.21.5", + "@babel/helper-compilation-targets": "^7.21.5", + "@babel/helper-plugin-utils": "^7.21.5", "@babel/helper-validator-option": "^7.21.0", "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6", "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.20.7", @@ -1627,6 +1504,7 @@ "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-namespace-from": "^7.8.3", "@babel/plugin-syntax-import-assertions": "^7.20.0", + "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-syntax-json-strings": "^7.8.3", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", @@ -1636,22 +1514,22 @@ "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-syntax-private-property-in-object": "^7.14.5", "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-transform-arrow-functions": "^7.20.7", + "@babel/plugin-transform-arrow-functions": "^7.21.5", "@babel/plugin-transform-async-to-generator": "^7.20.7", "@babel/plugin-transform-block-scoped-functions": "^7.18.6", "@babel/plugin-transform-block-scoping": "^7.21.0", "@babel/plugin-transform-classes": "^7.21.0", - "@babel/plugin-transform-computed-properties": "^7.20.7", + "@babel/plugin-transform-computed-properties": "^7.21.5", "@babel/plugin-transform-destructuring": "^7.21.3", "@babel/plugin-transform-dotall-regex": "^7.18.6", "@babel/plugin-transform-duplicate-keys": "^7.18.9", "@babel/plugin-transform-exponentiation-operator": "^7.18.6", - "@babel/plugin-transform-for-of": "^7.21.0", + "@babel/plugin-transform-for-of": "^7.21.5", "@babel/plugin-transform-function-name": "^7.18.9", "@babel/plugin-transform-literals": "^7.18.9", "@babel/plugin-transform-member-expression-literals": "^7.18.6", "@babel/plugin-transform-modules-amd": "^7.20.11", - "@babel/plugin-transform-modules-commonjs": "^7.21.2", + "@babel/plugin-transform-modules-commonjs": "^7.21.5", "@babel/plugin-transform-modules-systemjs": "^7.20.11", "@babel/plugin-transform-modules-umd": "^7.18.6", "@babel/plugin-transform-named-capturing-groups-regex": "^7.20.5", @@ -1659,17 +1537,17 @@ "@babel/plugin-transform-object-super": "^7.18.6", "@babel/plugin-transform-parameters": "^7.21.3", "@babel/plugin-transform-property-literals": "^7.18.6", - "@babel/plugin-transform-regenerator": "^7.20.5", + "@babel/plugin-transform-regenerator": "^7.21.5", "@babel/plugin-transform-reserved-words": "^7.18.6", "@babel/plugin-transform-shorthand-properties": "^7.18.6", "@babel/plugin-transform-spread": "^7.20.7", "@babel/plugin-transform-sticky-regex": "^7.18.6", "@babel/plugin-transform-template-literals": "^7.18.9", "@babel/plugin-transform-typeof-symbol": "^7.18.9", - "@babel/plugin-transform-unicode-escapes": "^7.18.10", + "@babel/plugin-transform-unicode-escapes": "^7.21.5", "@babel/plugin-transform-unicode-regex": "^7.18.6", "@babel/preset-modules": "^0.1.5", - "@babel/types": "^7.21.4", + "@babel/types": "^7.21.5", "babel-plugin-polyfill-corejs2": "^0.3.3", "babel-plugin-polyfill-corejs3": "^0.6.0", "babel-plugin-polyfill-regenerator": "^0.4.1", @@ -1700,15 +1578,15 @@ } }, "node_modules/@babel/preset-typescript": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.21.4.tgz", - "integrity": "sha512-sMLNWY37TCdRH/bJ6ZeeOH1nPuanED7Ai9Y/vH31IPqalioJ6ZNFUWONsakhv4r4n+I6gm5lmoE0olkgib/j/A==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.21.5.tgz", + "integrity": "sha512-iqe3sETat5EOrORXiQ6rWfoOg2y68Cs75B9wNxdPW4kixJxh7aXQE1KPdWLDniC24T/6dSnguF33W9j/ZZQcmA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-plugin-utils": "^7.21.5", "@babel/helper-validator-option": "^7.21.0", "@babel/plugin-syntax-jsx": "^7.21.4", - "@babel/plugin-transform-modules-commonjs": "^7.21.2", + "@babel/plugin-transform-modules-commonjs": "^7.21.5", "@babel/plugin-transform-typescript": "^7.21.3" }, "engines": { @@ -1725,9 +1603,9 @@ "dev": true }, "node_modules/@babel/runtime": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz", - "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.5.tgz", + "integrity": "sha512-8jI69toZqqcsnqGGqwGS4Qb1VwLOEp4hz+CXPywcvjs60u3B4Pom/U/7rm4W8tMOYEB+E9wgD0mW1l3r8qlI9Q==", "dev": true, "dependencies": { "regenerator-runtime": "^0.13.11" @@ -1737,34 +1615,29 @@ } }, "node_modules/@babel/template": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", - "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", - "dev": true, + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.26.9.tgz", + "integrity": "sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==", "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7" + "@babel/code-frame": "^7.26.2", + "@babel/parser": "^7.26.9", + "@babel/types": "^7.26.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.4.tgz", - "integrity": "sha512-eyKrRHKdyZxqDm+fV1iqL9UAHMoIg0nDaGqfIOd8rKH17m5snv7Gn4qgjBoFfLz9APvjFU/ICT00NVCv1Epp8Q==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.21.4", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.21.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.21.4", - "@babel/types": "^7.21.4", - "debug": "^4.1.0", + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.10.tgz", + "integrity": "sha512-k8NuDrxr0WrPH5Aupqb2LCVURP/S0vBEn5mK6iH+GIYob66U5EtoZvcdudR2jQ4cmTwhEwW1DLB+Yyas9zjF6A==", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.10", + "@babel/parser": "^7.26.10", + "@babel/template": "^7.26.9", + "@babel/types": "^7.26.10", + "debug": "^4.3.1", "globals": "^11.1.0" }, "engines": { @@ -1772,14 +1645,12 @@ } }, "node_modules/@babel/types": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.4.tgz", - "integrity": "sha512-rU2oY501qDxE8Pyo7i/Orqma4ziCOrby0/9mvbDUGEfvZjb279Nk9k19e2fiCxHbRRpY2ZyrgW1eq22mvmOIzA==", - "dev": true, + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.10.tgz", + "integrity": "sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==", "dependencies": { - "@babel/helper-string-parser": "^7.19.4", - "@babel/helper-validator-identifier": "^7.19.1", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1788,15 +1659,13 @@ "node_modules/@bcoe/v8-coverage": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true, - "peer": true + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==" }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, + "devOptional": true, "dependencies": { "@jridgewell/trace-mapping": "0.3.9" }, @@ -1808,18 +1677,25 @@ "version": "0.3.9", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, + "devOptional": true, "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@faker-js/faker": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-7.6.0.tgz", + "integrity": "sha512-XK6BTq1NDMo9Xqw/YkYyGjSsg44fbNwYRx7QK2CuoQgyy+f1rrTDHoExVM5PsyXCtfl2vs2vVJ0MN0yN6LppRw==", + "engines": { + "node": ">=14.0.0", + "npm": ">=6.0.0" + } + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, - "peer": true, "dependencies": { "camelcase": "^5.3.1", "find-up": "^4.1.0", @@ -1835,23 +1711,20 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true, - "peer": true, "engines": { "node": ">=8" } }, "node_modules/@jest/console": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.5.0.tgz", - "integrity": "sha512-NEpkObxPwyw/XxZVLPmAGKE89IQRp4puc6IQRPru6JKd1M3fW9v1xM1AnzIJE65hbCkzQAdnL8P47e9hzhiYLQ==", - "dev": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", "slash": "^3.0.0" }, "engines": { @@ -1859,38 +1732,36 @@ } }, "node_modules/@jest/core": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.5.0.tgz", - "integrity": "sha512-28UzQc7ulUrOQw1IsN/kv1QES3q2kkbl/wGslyhAclqZ/8cMdB5M68BffkIdSJgKBUt50d3hbwJ92XESlE7LiQ==", - "dev": true, - "peer": true, - "dependencies": { - "@jest/console": "^29.5.0", - "@jest/reporters": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.5.0", - "jest-config": "^29.5.0", - "jest-haste-map": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-resolve-dependencies": "^29.5.0", - "jest-runner": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", - "jest-watcher": "^29.5.0", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", "micromatch": "^4.0.4", - "pretty-format": "^29.5.0", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, @@ -1907,94 +1778,83 @@ } }, "node_modules/@jest/environment": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.5.0.tgz", - "integrity": "sha512-5FXw2+wD29YU1d4I2htpRX7jYnAyTRjP2CsXQdo9SAM8g3ifxWPSV0HnClSn71xwctr0U3oZIIH+dtbfmnbXVQ==", - "dev": true, - "peer": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", "dependencies": { - "@jest/fake-timers": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", - "jest-mock": "^29.5.0" + "jest-mock": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.5.0.tgz", - "integrity": "sha512-PueDR2HGihN3ciUNGr4uelropW7rqUfTiOn+8u0leg/42UhblPxHkfoh0Ruu3I9Y1962P3u2DY4+h7GVTSVU6g==", - "dev": true, - "peer": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", "dependencies": { - "expect": "^29.5.0", - "jest-snapshot": "^29.5.0" + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect-utils": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.5.0.tgz", - "integrity": "sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg==", - "dev": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", "dependencies": { - "jest-get-type": "^29.4.3" + "jest-get-type": "^29.6.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/fake-timers": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.5.0.tgz", - "integrity": "sha512-9ARvuAAQcBwDAqOnglWq2zwNIRUDtk/SCkp/ToGEhFv5r86K21l+VEs0qNTaXtyiY0lEePl3kylijSYJQqdbDg==", - "dev": true, - "peer": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.3", "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", - "jest-message-util": "^29.5.0", - "jest-mock": "^29.5.0", - "jest-util": "^29.5.0" + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/globals": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.5.0.tgz", - "integrity": "sha512-S02y0qMWGihdzNbUiqSAiKSpSozSuHX5UYc7QbnHP+D9Lyw8DgGGCinrN9uSuHPeKgSSzvPom2q1nAtBvUsvPQ==", - "dev": true, - "peer": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", "dependencies": { - "@jest/environment": "^29.5.0", - "@jest/expect": "^29.5.0", - "@jest/types": "^29.5.0", - "jest-mock": "^29.5.0" + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/reporters": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.5.0.tgz", - "integrity": "sha512-D05STXqj/M8bP9hQNSICtPqz97u7ffGzZu+9XLucXhkOFBqKcXe04JLZOgIekOxdb73MAoBUFnqvf7MCpKk5OA==", - "dev": true, - "peer": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", "dependencies": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@jridgewell/trace-mapping": "^0.3.15", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", "@types/node": "*", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", @@ -2002,13 +1862,13 @@ "glob": "^7.1.3", "graceful-fs": "^4.2.9", "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-instrument": "^6.0.0", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", - "jest-worker": "^29.5.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", @@ -2026,26 +1886,49 @@ } } }, + "node_modules/@jest/reporters/node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@jest/reporters/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@jest/schemas": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", - "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", - "dev": true, + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dependencies": { - "@sinclair/typebox": "^0.25.16" + "@sinclair/typebox": "^0.27.8" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/source-map": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.4.3.tgz", - "integrity": "sha512-qyt/mb6rLyd9j1jUts4EQncvS6Yy3PM9HghnNv86QBlV+zdL2inCdK1tuVlL+J+lpiw2BI67qXOrX3UurBqQ1w==", - "dev": true, - "peer": true, + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.15", + "@jridgewell/trace-mapping": "^0.3.18", "callsites": "^3.0.0", "graceful-fs": "^4.2.9" }, @@ -2054,13 +1937,12 @@ } }, "node_modules/@jest/test-result": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.5.0.tgz", - "integrity": "sha512-fGl4rfitnbfLsrfx1uUpDEESS7zM8JdgZgOCQuxQvL1Sn/I6ijeAVQWGfXI9zb1i9Mzo495cIpVZhA0yr60PkQ==", - "dev": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", "dependencies": { - "@jest/console": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" }, @@ -2069,15 +1951,13 @@ } }, "node_modules/@jest/test-sequencer": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.5.0.tgz", - "integrity": "sha512-yPafQEcKjkSfDXyvtgiV4pevSeyuA6MQr6ZIdVkWJly9vkqjnFfcfhRQqpD5whjoU8EORki752xQmjaqoFjzMQ==", - "dev": true, - "peer": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", "dependencies": { - "@jest/test-result": "^29.5.0", + "@jest/test-result": "^29.7.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", + "jest-haste-map": "^29.7.0", "slash": "^3.0.0" }, "engines": { @@ -2085,23 +1965,21 @@ } }, "node_modules/@jest/transform": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.5.0.tgz", - "integrity": "sha512-8vbeZWqLJOvHaDfeMuoHITGKSz5qWc9u04lnWrQE3VyuSw604PzQM824ZeX9XSjUCeDiE3GuxZe5UKa8J61NQw==", - "dev": true, - "peer": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "dependencies": { "@babel/core": "^7.11.6", - "@jest/types": "^29.5.0", - "@jridgewell/trace-mapping": "^0.3.15", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", - "jest-regex-util": "^29.4.3", - "jest-util": "^29.5.0", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", @@ -2112,12 +1990,11 @@ } }, "node_modules/@jest/types": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz", - "integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==", - "dev": true, + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dependencies": { - "@jest/schemas": "^29.4.3", + "@jest/schemas": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -2129,14 +2006,13 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "dev": true, + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", "dependencies": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" @@ -2146,16 +2022,14 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "engines": { "node": ">=6.0.0" } @@ -2163,49 +2037,68 @@ "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.15", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", - "dev": true, + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true + "node_modules/@puppeteer/browsers": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.2.4.tgz", + "integrity": "sha512-BdG2qiI1dn89OTUUsx2GZSpUzW+DRffR1wlMJyKxVHYrhnKoELSDxDd+2XImUkuWPEKk76H5FcM/gPFrEK1Tfw==", + "dependencies": { + "debug": "^4.3.5", + "extract-zip": "^2.0.1", + "progress": "^2.0.3", + "proxy-agent": "^6.4.0", + "semver": "^7.6.2", + "tar-fs": "^3.0.6", + "unbzip2-stream": "^1.4.3", + "yargs": "^17.7.2" + }, + "bin": { + "browsers": "lib/cjs/main-cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@puppeteer/browsers/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } }, "node_modules/@sinclair/typebox": { - "version": "0.25.24", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", - "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==", - "dev": true + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==" }, "node_modules/@sinonjs/commons": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", - "dev": true, - "peer": true, + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", "dependencies": { "type-detect": "4.0.8" } }, "node_modules/@sinonjs/fake-timers": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.0.2.tgz", - "integrity": "sha512-SwUDyjWnah1AaNl7kxsa7cfLhlTYoiyhDAIgyh+El30YvXs/o7OLXpYH88Zdhyx9JExKrmHDJ+10bwIcY80Jmw==", - "dev": true, - "peer": true, + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", "dependencies": { - "@sinonjs/commons": "^2.0.0" + "@sinonjs/commons": "^3.0.0" } }, "node_modules/@sinonjs/samsam": { @@ -2234,36 +2127,48 @@ "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", "dev": true }, + "node_modules/@tootallnate/quickjs-emscripten": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==" + }, "node_modules/@tsconfig/node10": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "dev": true + "devOptional": true }, "node_modules/@tsconfig/node12": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true + "devOptional": true }, "node_modules/@tsconfig/node14": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true + "devOptional": true }, "node_modules/@tsconfig/node16": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", - "dev": true + "devOptional": true }, - "node_modules/@types/babel__core": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.0.tgz", - "integrity": "sha512-+n8dL/9GWblDO0iU6eZAwEIJVr5DWigtle+Q6HLOrh/pdbXOhOtqzq8VPPE2zvNJzSKY4vH/z3iT3tn0A3ypiQ==", + "node_modules/@types/adm-zip": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@types/adm-zip/-/adm-zip-0.5.0.tgz", + "integrity": "sha512-FCJBJq9ODsQZUNURo5ILAQueuA8WJhRvuihS3ke2iI25mJlfV2LK8jG2Qj2z2AWg8U0FtWWqBHVRetceLskSaw==", "dev": true, - "peer": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", @@ -2273,42 +2178,34 @@ } }, "node_modules/@types/babel__generator": { - "version": "7.6.4", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", - "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", - "dev": true, - "peer": true, + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", "dependencies": { "@babel/types": "^7.0.0" } }, "node_modules/@types/babel__template": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", - "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", - "dev": true, - "peer": true, + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" } }, "node_modules/@types/babel__traverse": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.3.tgz", - "integrity": "sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w==", - "dev": true, - "peer": true, + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", "dependencies": { - "@babel/types": "^7.3.0" + "@babel/types": "^7.20.7" } }, "node_modules/@types/graceful-fs": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", - "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", - "dev": true, - "peer": true, + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", "dependencies": { "@types/node": "*" } @@ -2316,14 +2213,12 @@ "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", - "dev": true + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==" }, "node_modules/@types/istanbul-lib-report": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", - "dev": true, "dependencies": { "@types/istanbul-lib-coverage": "*" } @@ -2332,7 +2227,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", - "dev": true, "dependencies": { "@types/istanbul-lib-report": "*" } @@ -2350,27 +2244,17 @@ "node_modules/@types/node": { "version": "18.15.11", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.11.tgz", - "integrity": "sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==", - "dev": true - }, - "node_modules/@types/prettier": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz", - "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==", - "dev": true, - "peer": true + "integrity": "sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==" }, "node_modules/@types/stack-utils": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", - "dev": true + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" }, "node_modules/@types/yargs": { "version": "17.0.24", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", - "dev": true, "dependencies": { "@types/yargs-parser": "*" } @@ -2378,14 +2262,22 @@ "node_modules/@types/yargs-parser": { "version": "21.0.0", "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", - "dev": true + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==" + }, + "node_modules/@types/yauzl": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "optional": true, + "dependencies": { + "@types/node": "*" + } }, "node_modules/acorn": { "version": "8.8.2", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", - "dev": true, + "devOptional": true, "bin": { "acorn": "bin/acorn" }, @@ -2397,17 +2289,35 @@ "version": "8.2.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.4.0" } }, + "node_modules/adm-zip": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.10.tgz", + "integrity": "sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "peer": true, "dependencies": { "type-fest": "^0.21.3" }, @@ -2422,7 +2332,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "engines": { "node": ">=8" } @@ -2431,7 +2340,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -2446,8 +2354,6 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "peer": true, "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -2460,44 +2366,56 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true + "devOptional": true }, "node_modules/argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "peer": true, "dependencies": { "sprintf-js": "~1.0.2" } }, + "node_modules/ast-types": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/axios": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.5.tgz", - "integrity": "sha512-glL/PvG/E+xCWwV8S6nCHcrfg1exGx7vxyUIivIA1iL7BIh6bePylCfVHwp6k13ao7SATxB6imau2kqY+I67kw==", + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", "dependencies": { - "follow-redirects": "^1.15.0", + "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } }, + "node_modules/b4a": { + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.6.tgz", + "integrity": "sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==" + }, "node_modules/babel-jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.5.0.tgz", - "integrity": "sha512-mA4eCDh5mSo2EcA9xQjVTpmbbNk32Zb3Q3QFQsNhaK56Q+yoXowzFodLux30HRgyOho5rsQ6B0P9QpMkvvnJ0Q==", - "dev": true, - "peer": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", "dependencies": { - "@jest/transform": "^29.5.0", + "@jest/transform": "^29.7.0", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.5.0", + "babel-preset-jest": "^29.6.3", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "slash": "^3.0.0" @@ -2513,8 +2431,6 @@ "version": "6.1.1", "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, - "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@istanbuljs/load-nyc-config": "^1.0.0", @@ -2527,11 +2443,9 @@ } }, "node_modules/babel-plugin-jest-hoist": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.5.0.tgz", - "integrity": "sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w==", - "dev": true, - "peer": true, + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", "dependencies": { "@babel/template": "^7.3.3", "@babel/types": "^7.3.3", @@ -2585,8 +2499,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", - "dev": true, - "peer": true, "dependencies": { "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-bigint": "^7.8.3", @@ -2606,13 +2518,11 @@ } }, "node_modules/babel-preset-jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.5.0.tgz", - "integrity": "sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg==", - "dev": true, - "peer": true, + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", "dependencies": { - "babel-plugin-jest-hoist": "^29.5.0", + "babel-plugin-jest-hoist": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0" }, "engines": { @@ -2625,36 +2535,100 @@ "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/bare-events": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.4.2.tgz", + "integrity": "sha512-qMKFd2qG/36aA4GwvKq8MxnPgCQAmBWmSyLWsJcbn8v03wvIPQ/hG1Ms8bPzndZxMDoHpxez5VOS+gC9Yi24/Q==", + "optional": true + }, + "node_modules/bare-fs": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-2.3.1.tgz", + "integrity": "sha512-W/Hfxc/6VehXlsgFtbB5B4xFcsCl+pAh30cYhoFyXErf6oGrwjh8SwiPAdHgpmWonKuYpZgGywN0SXt7dgsADA==", + "optional": true, + "dependencies": { + "bare-events": "^2.0.0", + "bare-path": "^2.0.0", + "bare-stream": "^2.0.0" + } + }, + "node_modules/bare-os": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-2.4.0.tgz", + "integrity": "sha512-v8DTT08AS/G0F9xrhyLtepoo9EJBJ85FRSMbu1pQUlAf6A8T0tEEQGMVObWeqpjhSPXsE0VGlluFBJu2fdoTNg==", + "optional": true + }, + "node_modules/bare-path": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-2.1.3.tgz", + "integrity": "sha512-lh/eITfU8hrj9Ru5quUp0Io1kJWIk1bTjzo7JH1P5dWmQ2EL4hFUlfI8FonAhSlgIfhn63p84CDY/x+PisgcXA==", + "optional": true, + "dependencies": { + "bare-os": "^2.1.0" + } + }, + "node_modules/bare-stream": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.1.3.tgz", + "integrity": "sha512-tiDAH9H/kP+tvNO5sczyn9ZAA7utrSMobyDchsnyyXBuUe2FSQWbxhtuHB8jwpHYYevVo2UJpcmvvjrbHboUUQ==", + "optional": true, + "dependencies": { + "streamx": "^2.18.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/basic-ftp": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz", + "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==", + "engines": { + "node": ">=10.0.0" + } }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" } }, "node_modules/browserslist": { - "version": "4.21.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", - "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", - "dev": true, + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", + "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", "funding": [ { "type": "opencollective", @@ -2663,13 +2637,17 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { - "caniuse-lite": "^1.0.30001449", - "electron-to-chromium": "^1.4.284", - "node-releases": "^2.0.8", - "update-browserslist-db": "^1.0.10" + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" @@ -2694,25 +2672,50 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dev": true, - "peer": true, "dependencies": { "node-int64": "^0.4.0" } }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "engines": { + "node": "*" + } + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true, - "peer": true + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "peer": true, "engines": { "node": ">=6" } @@ -2721,17 +2724,14 @@ "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "peer": true, "engines": { "node": ">=6" } }, "node_modules/caniuse-lite": { - "version": "1.0.30001478", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001478.tgz", - "integrity": "sha512-gMhDyXGItTHipJj2ApIvR+iVB5hd0KP3svMWWXDvZOmjzJJassGLMfxRkQCSYgGd2gtdL/ReeiyvMSFD1Ss6Mw==", - "dev": true, + "version": "1.0.30001706", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001706.tgz", + "integrity": "sha512-3ZczoTApMAZwPKYWmwVbQMFpXBDds3/0VciVoUwPUbldlYyVLmRVuRs/PcUZtHpbLRpzzDvrvnFuREsGt6lUug==", "funding": [ { "type": "opencollective", @@ -2751,7 +2751,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -2767,17 +2766,27 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true, - "peer": true, "engines": { "node": ">=10" } }, + "node_modules/chromium-bidi": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.6.1.tgz", + "integrity": "sha512-kSxJRj0VgtUKz6nmzc2JPfyfJGzwzt65u7PqhPHtgGQUZLF5oG+ST6l6e5ONfStUMAlhSutFCjaGKllXZa16jA==", + "dependencies": { + "mitt": "3.0.1", + "urlpattern-polyfill": "10.0.0", + "zod": "3.23.8" + }, + "peerDependencies": { + "devtools-protocol": "*" + } + }, "node_modules/ci-info": { "version": "3.8.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", - "dev": true, "funding": [ { "type": "github", @@ -2789,18 +2798,14 @@ } }, "node_modules/cjs-module-lexer": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", - "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", - "dev": true, - "peer": true + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==" }, "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, - "peer": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -2814,8 +2819,6 @@ "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "dev": true, - "peer": true, "engines": { "iojs": ">= 1.0.0", "node": ">= 0.12.0" @@ -2824,14 +2827,12 @@ "node_modules/collect-v8-coverage": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", - "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", - "dev": true + "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==" }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -2842,8 +2843,7 @@ "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/combined-stream": { "version": "1.0.8", @@ -2859,20 +2859,17 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "peer": true + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" }, "node_modules/core-js-compat": { - "version": "3.30.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.30.1.tgz", - "integrity": "sha512-d690npR7MC6P0gq4npTl5n2VQeNAmUrJ90n+MHiKS7W2+xno4o3F5GDEuylSdi6EJ3VssibSGXOa1r3YXD3Mhw==", + "version": "3.30.2", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.30.2.tgz", + "integrity": "sha512-nriW1nuJjUgvkEjIot1Spwakz52V9YkYHZAQG6A1eCgC8AA1p0zngrQEP9R0+V6hji5XilWKG1Bd0YRppmGimA==", "dev": true, "dependencies": { "browserslist": "^4.21.5" @@ -2882,18 +2879,77 @@ "url": "https://opencollective.com/core-js" } }, + "node_modules/cosmiconfig": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", + "dependencies": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cosmiconfig/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/cosmiconfig/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true + "devOptional": true }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "peer": true, + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -2903,6 +2959,14 @@ "node": ">= 8" } }, + "node_modules/data-uri-to-buffer": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", + "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", + "engines": { + "node": ">= 14" + } + }, "node_modules/dateformat": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.2.tgz", @@ -2913,10 +2977,9 @@ } }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "dependencies": { "ms": "2.1.2" }, @@ -2930,22 +2993,47 @@ } }, "node_modules/dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", - "dev": true, - "peer": true + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } }, "node_modules/deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "dev": true, - "peer": true, "engines": { "node": ">=0.10.0" } }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "engines": { + "node": ">=8" + } + }, + "node_modules/degenerator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", + "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", + "dependencies": { + "ast-types": "^0.13.4", + "escodegen": "^2.1.0", + "esprima": "^4.0.1" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -2958,42 +3046,52 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "dev": true, - "peer": true, "engines": { "node": ">=8" } }, + "node_modules/devtools-protocol": { + "version": "0.0.1299070", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1299070.tgz", + "integrity": "sha512-+qtL3eX50qsJ7c+qVyagqi7AWMoQCBGNfoyJZMwm/NSXVqLYbuitrWEEIzxfUmTNy7//Xe8yhMmQ+elj3uAqSg==" + }, "node_modules/diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.3.1" } }, "node_modules/diff-sequences": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", - "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==", - "dev": true, + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/dotenv": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", + "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" + } + }, "node_modules/electron-to-chromium": { - "version": "1.4.363", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.363.tgz", - "integrity": "sha512-ReX5qgmSU7ybhzMuMdlJAdYnRhT90UB3k9M05O5nF5WH3wR5wgdJjXw0uDeFyKNhmglmQiOxkAbzrP0hMKM59g==", - "dev": true + "version": "1.5.120", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.120.tgz", + "integrity": "sha512-oTUp3gfX1gZI+xfD2djr2rzQdHCwHzPQrrK0CD7WpTdF0nPdQ/INcRVjWgLdCT4a9W3jFObR9DAfsuyFQnI8CQ==" }, "node_modules/emittery": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", - "dev": true, - "peer": true, "engines": { "node": ">=12" }, @@ -3004,25 +3102,36 @@ "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "peer": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "engines": { + "node": ">=6" + } }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "peer": true, "dependencies": { "is-arrayish": "^0.2.1" } }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "engines": { "node": ">=6" } @@ -3031,17 +3140,34 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true, "engines": { "node": ">=8" } }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, "node_modules/esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "peer": true, "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -3050,11 +3176,18 @@ "node": ">=4" } }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "engines": { + "node": ">=4.0" + } + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -3063,8 +3196,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "peer": true, "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", @@ -3087,49 +3218,88 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", - "dev": true, - "peer": true, "engines": { "node": ">= 0.8.0" } }, "node_modules/expect": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.5.0.tgz", - "integrity": "sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg==", - "dev": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", "dependencies": { - "@jest/expect-utils": "^29.5.0", - "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0" + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/extract-zip/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==" + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, "node_modules/fb-watchman": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", - "dev": true, - "peer": true, "dependencies": { "bser": "2.1.1" } }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dependencies": { + "pend": "~1.2.0" + } + }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -3141,8 +3311,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "peer": true, "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -3152,9 +3320,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "funding": [ { "type": "individual", @@ -3183,23 +3351,33 @@ "node": ">= 6" } }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "hasInstallScript": true, "optional": true, "os": [ "darwin" ], - "peer": true, "engines": { "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } @@ -3207,14 +3385,12 @@ "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/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -3223,8 +3399,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "peer": true, "engines": { "node": "6.* || 8.* || >= 10.*" } @@ -3233,8 +3407,6 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true, - "peer": true, "engines": { "node": ">=8.0.0" } @@ -3243,8 +3415,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "peer": true, "engines": { "node": ">=10" }, @@ -3252,11 +3422,37 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/get-uri": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.3.tgz", + "integrity": "sha512-BzUrJBS9EcUb4cFol8r4W3v1cPsSyajLSthNkz5BxbpDcHN5tIrM10E2eNvfnvBn3DaT3DUgx0OpsBKkaOpanw==", + "dependencies": { + "basic-ftp": "^5.0.2", + "data-uri-to-buffer": "^6.0.2", + "debug": "^4.3.4", + "fs-extra": "^11.2.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/get-uri/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -3276,7 +3472,6 @@ "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, "engines": { "node": ">=4" } @@ -3284,14 +3479,12 @@ "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, "node_modules/has": { "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" }, @@ -3303,7 +3496,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -3311,26 +3503,86 @@ "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true, - "peer": true + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==" + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "peer": true, "engines": { "node": ">=10.17.0" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "engines": { + "node": ">=4" + } + }, "node_modules/import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", - "dev": true, - "peer": true, + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", "dependencies": { "pkg-dir": "^4.2.0", "resolve-cwd": "^3.0.0" @@ -3349,8 +3601,6 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "peer": true, "engines": { "node": ">=0.8.19" } @@ -3359,7 +3609,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -3368,21 +3617,34 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/ip-address/node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==" }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true, - "peer": true + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" }, "node_modules/is-core-module": { "version": "2.12.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.0.tgz", "integrity": "sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==", - "dev": true, "dependencies": { "has": "^1.0.3" }, @@ -3390,12 +3652,24 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "peer": true, "engines": { "node": ">=8" } @@ -3404,8 +3678,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "dev": true, - "peer": true, "engines": { "node": ">=6" } @@ -3414,7 +3686,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, "engines": { "node": ">=0.12.0" } @@ -3423,8 +3694,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "peer": true, "engines": { "node": ">=8" }, @@ -3432,6 +3701,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", @@ -3441,16 +3721,12 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "peer": true + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "node_modules/istanbul-lib-coverage": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true, - "peer": true, "engines": { "node": ">=8" } @@ -3459,8 +3735,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "dev": true, - "peer": true, "dependencies": { "@babel/core": "^7.12.3", "@babel/parser": "^7.14.7", @@ -3473,26 +3747,22 @@ } }, "node_modules/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", - "dev": true, - "peer": true, + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dependencies": { "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", + "make-dir": "^4.0.0", "supports-color": "^7.1.0" }, "engines": { - "node": ">=8" + "node": ">=10" } }, "node_modules/istanbul-lib-source-maps": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "peer": true, "dependencies": { "debug": "^4.1.1", "istanbul-lib-coverage": "^3.0.0", @@ -3503,11 +3773,9 @@ } }, "node_modules/istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", - "dev": true, - "peer": true, + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" @@ -3517,16 +3785,14 @@ } }, "node_modules/jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.5.0.tgz", - "integrity": "sha512-juMg3he2uru1QoXX078zTa7pO85QyB9xajZc6bU+d9yEGwrKX6+vGmJQ3UdVZsvTEUARIdObzH68QItim6OSSQ==", - "dev": true, - "peer": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dependencies": { - "@jest/core": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", "import-local": "^3.0.2", - "jest-cli": "^29.5.0" + "jest-cli": "^29.7.0" }, "bin": { "jest": "bin/jest.js" @@ -3544,13 +3810,12 @@ } }, "node_modules/jest-changed-files": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.5.0.tgz", - "integrity": "sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag==", - "dev": true, - "peer": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", "dependencies": { "execa": "^5.0.0", + "jest-util": "^29.7.0", "p-limit": "^3.1.0" }, "engines": { @@ -3558,29 +3823,27 @@ } }, "node_modules/jest-circus": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.5.0.tgz", - "integrity": "sha512-gq/ongqeQKAplVxqJmbeUOJJKkW3dDNPY8PjhJ5G0lBRvu0e3EWGxGy5cI4LAGA7gV2UHCtWBI4EMXK8c9nQKA==", - "dev": true, - "peer": true, - "dependencies": { - "@jest/environment": "^29.5.0", - "@jest/expect": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", - "dedent": "^0.7.0", + "dedent": "^1.0.0", "is-generator-fn": "^2.0.0", - "jest-each": "^29.5.0", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", "p-limit": "^3.1.0", - "pretty-format": "^29.5.0", + "pretty-format": "^29.7.0", "pure-rand": "^6.0.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" @@ -3590,23 +3853,20 @@ } }, "node_modules/jest-cli": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.5.0.tgz", - "integrity": "sha512-L1KcP1l4HtfwdxXNFCL5bmUbLQiKrakMUriBEcc1Vfz6gx31ORKdreuWvmQVBit+1ss9NNR3yxjwfwzZNdQXJw==", - "dev": true, - "peer": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", "dependencies": { - "@jest/core": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", "chalk": "^4.0.0", + "create-jest": "^29.7.0", "exit": "^0.1.2", - "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", - "prompts": "^2.0.1", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", "yargs": "^17.3.1" }, "bin": { @@ -3625,32 +3885,30 @@ } }, "node_modules/jest-config": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.5.0.tgz", - "integrity": "sha512-kvDUKBnNJPNBmFFOhDbm59iu1Fii1Q6SxyhXfvylq3UTHbg6o7j/g8k2dZyXWLvfdKB1vAPxNZnMgtKJcmu3kA==", - "dev": true, - "peer": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", "dependencies": { "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.5.0", - "@jest/types": "^29.5.0", - "babel-jest": "^29.5.0", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-circus": "^29.5.0", - "jest-environment-node": "^29.5.0", - "jest-get-type": "^29.4.3", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-runner": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", "micromatch": "^4.0.4", "parse-json": "^5.2.0", - "pretty-format": "^29.5.0", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, @@ -3671,26 +3929,23 @@ } }, "node_modules/jest-diff": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.5.0.tgz", - "integrity": "sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==", - "dev": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "dependencies": { "chalk": "^4.0.0", - "diff-sequences": "^29.4.3", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-docblock": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.4.3.tgz", - "integrity": "sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg==", - "dev": true, - "peer": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", "dependencies": { "detect-newline": "^3.0.0" }, @@ -3699,65 +3954,79 @@ } }, "node_modules/jest-each": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.5.0.tgz", - "integrity": "sha512-HM5kIJ1BTnVt+DQZ2ALp3rzXEl+g726csObrW/jpEGl+CDSSQpOJJX2KE/vEg8cxcMXdyEPu6U4QX5eruQv5hA==", - "dev": true, - "peer": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.3", "chalk": "^4.0.0", - "jest-get-type": "^29.4.3", - "jest-util": "^29.5.0", - "pretty-format": "^29.5.0" + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-environment-node": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.5.0.tgz", - "integrity": "sha512-ExxuIK/+yQ+6PRGaHkKewYtg6hto2uGCgvKdb2nfJfKXgZ17DfXjvbZ+jA1Qt9A8EQSfPnt5FKIfnOO3u1h9qw==", - "dev": true, - "peer": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", "dependencies": { - "@jest/environment": "^29.5.0", - "@jest/fake-timers": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", - "jest-mock": "^29.5.0", - "jest-util": "^29.5.0" + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-get-type": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", - "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", + "node_modules/jest-extended": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/jest-extended/-/jest-extended-4.0.2.tgz", + "integrity": "sha512-FH7aaPgtGYHc9mRjriS0ZEHYM5/W69tLrFTIdzm+yJgeoCmmrSB/luSfMSqWP9O29QWHPEmJ4qmU6EwsZideog==", "dev": true, + "dependencies": { + "jest-diff": "^29.0.0", + "jest-get-type": "^29.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "jest": ">=27.2.5" + }, + "peerDependenciesMeta": { + "jest": { + "optional": true + } + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-haste-map": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.5.0.tgz", - "integrity": "sha512-IspOPnnBro8YfVYSw6yDRKh/TiCdRngjxeacCps1cQ9cgVN6+10JUcuJ1EabrgYLOATsIAigxA0rLR9x/YlrSA==", - "dev": true, - "peer": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.3", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.4.3", - "jest-util": "^29.5.0", - "jest-worker": "^29.5.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", "micromatch": "^4.0.4", "walker": "^1.0.8" }, @@ -3794,48 +4063,53 @@ "typescript": "^3.7.x || ^4.3.x || ^5.x" } }, + "node_modules/jest-html-reporters": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/jest-html-reporters/-/jest-html-reporters-3.1.7.tgz", + "integrity": "sha512-GTmjqK6muQ0S0Mnksf9QkL9X9z2FGIpNSxC52E0PHDzjPQ1XDu2+XTI3B3FS43ZiUzD1f354/5FfwbNIBzT7ew==", + "dependencies": { + "fs-extra": "^10.0.0", + "open": "^8.0.3" + } + }, "node_modules/jest-leak-detector": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.5.0.tgz", - "integrity": "sha512-u9YdeeVnghBUtpN5mVxjID7KbkKE1QU4f6uUwuxiY0vYRi9BUCLKlPEZfDGR67ofdFmDz9oPAy2G92Ujrntmow==", - "dev": true, - "peer": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", "dependencies": { - "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-matcher-utils": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.5.0.tgz", - "integrity": "sha512-lecRtgm/rjIK0CQ7LPQwzCs2VwW6WAahA55YBuI+xqmhm7LAaxokSB8C97yJeYyT+HvQkH741StzpU41wohhWw==", - "dev": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", "dependencies": { "chalk": "^4.0.0", - "jest-diff": "^29.5.0", - "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-message-util": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.5.0.tgz", - "integrity": "sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA==", - "dev": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", "dependencies": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.3", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.5.0", + "pretty-format": "^29.7.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, @@ -3844,15 +4118,13 @@ } }, "node_modules/jest-mock": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.5.0.tgz", - "integrity": "sha512-GqOzvdWDE4fAV2bWQLQCkujxYWL7RxjCnj71b5VhDAGOevB3qj3Ovg26A5NI84ZpODxyzaozXLOh2NCgkbvyaw==", - "dev": true, - "peer": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.3", "@types/node": "*", - "jest-util": "^29.5.0" + "jest-util": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -3862,8 +4134,6 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", - "dev": true, - "peer": true, "engines": { "node": ">=6" }, @@ -3877,28 +4147,24 @@ } }, "node_modules/jest-regex-util": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.4.3.tgz", - "integrity": "sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg==", - "dev": true, - "peer": true, + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-resolve": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.5.0.tgz", - "integrity": "sha512-1TzxJ37FQq7J10jPtQjcc+MkCkE3GBpBecsSUWJ0qZNJpmg6m0D9/7II03yJulm3H/fvVjgqLh/k2eYg+ui52w==", - "dev": true, - "peer": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", + "jest-haste-map": "^29.7.0", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", "resolve": "^1.20.0", "resolve.exports": "^2.0.0", "slash": "^3.0.0" @@ -3908,45 +4174,41 @@ } }, "node_modules/jest-resolve-dependencies": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.5.0.tgz", - "integrity": "sha512-sjV3GFr0hDJMBpYeUuGduP+YeCRbd7S/ck6IvL3kQ9cpySYKqcqhdLLC2rFwrcL7tz5vYibomBrsFYWkIGGjOg==", - "dev": true, - "peer": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", "dependencies": { - "jest-regex-util": "^29.4.3", - "jest-snapshot": "^29.5.0" + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runner": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.5.0.tgz", - "integrity": "sha512-m7b6ypERhFghJsslMLhydaXBiLf7+jXy8FwGRHO3BGV1mcQpPbwiqiKUR2zU2NJuNeMenJmlFZCsIqzJCTeGLQ==", - "dev": true, - "peer": true, - "dependencies": { - "@jest/console": "^29.5.0", - "@jest/environment": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.13.1", "graceful-fs": "^4.2.9", - "jest-docblock": "^29.4.3", - "jest-environment-node": "^29.5.0", - "jest-haste-map": "^29.5.0", - "jest-leak-detector": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-resolve": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-util": "^29.5.0", - "jest-watcher": "^29.5.0", - "jest-worker": "^29.5.0", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", "p-limit": "^3.1.0", "source-map-support": "0.5.13" }, @@ -3955,32 +4217,30 @@ } }, "node_modules/jest-runtime": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.5.0.tgz", - "integrity": "sha512-1Hr6Hh7bAgXQP+pln3homOiEZtCDZFqwmle7Ew2j8OlbkIu6uE3Y/etJQG8MLQs3Zy90xrp2C0BRrtPHG4zryw==", - "dev": true, - "peer": true, - "dependencies": { - "@jest/environment": "^29.5.0", - "@jest/fake-timers": "^29.5.0", - "@jest/globals": "^29.5.0", - "@jest/source-map": "^29.4.3", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-mock": "^29.5.0", - "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", "slash": "^3.0.0", "strip-bom": "^4.0.0" }, @@ -3989,62 +4249,39 @@ } }, "node_modules/jest-snapshot": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.5.0.tgz", - "integrity": "sha512-x7Wolra5V0tt3wRs3/ts3S6ciSQVypgGQlJpz2rsdQYoUKxMxPNaoHMGJN6qAuPJqS+2iQ1ZUn5kl7HCyls84g==", - "dev": true, - "peer": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", "dependencies": { "@babel/core": "^7.11.6", "@babel/generator": "^7.7.2", "@babel/plugin-syntax-jsx": "^7.7.2", "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/traverse": "^7.7.2", "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/babel__traverse": "^7.0.6", - "@types/prettier": "^2.1.5", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^29.5.0", + "expect": "^29.7.0", "graceful-fs": "^4.2.9", - "jest-diff": "^29.5.0", - "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", "natural-compare": "^1.4.0", - "pretty-format": "^29.5.0", - "semver": "^7.3.5" + "pretty-format": "^29.7.0", + "semver": "^7.5.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-snapshot/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "peer": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/jest-snapshot/node_modules/semver": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.4.0.tgz", - "integrity": "sha512-RgOxM8Mw+7Zus0+zcLEUn8+JfoLpj/huFTItQy2hsM4khuC1HYRDp0cU482Ewn/Fcy6bCjufD8vAj7voC66KQw==", - "dev": true, - "peer": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", "bin": { "semver": "bin/semver.js" }, @@ -4052,20 +4289,12 @@ "node": ">=10" } }, - "node_modules/jest-snapshot/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "peer": true - }, "node_modules/jest-util": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.5.0.tgz", - "integrity": "sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ==", - "dev": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -4077,18 +4306,16 @@ } }, "node_modules/jest-validate": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.5.0.tgz", - "integrity": "sha512-pC26etNIi+y3HV8A+tUGr/lph9B18GnzSRAkPaaZJIE1eFdiYm6/CewuiJQ8/RlfHd1u/8Ioi8/sJ+CmbA+zAQ==", - "dev": true, - "peer": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.3", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^29.4.3", + "jest-get-type": "^29.6.3", "leven": "^3.1.0", - "pretty-format": "^29.5.0" + "pretty-format": "^29.7.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -4098,8 +4325,6 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "peer": true, "engines": { "node": ">=10" }, @@ -4108,19 +4333,17 @@ } }, "node_modules/jest-watcher": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.5.0.tgz", - "integrity": "sha512-KmTojKcapuqYrKDpRwfqcQ3zjMlwu27SYext9pt4GlF5FUgB+7XE1mcCnSm6a4uUpFyQIkb6ZhzZvHl+jiBCiA==", - "dev": true, - "peer": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", "dependencies": { - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "emittery": "^0.13.1", - "jest-util": "^29.5.0", + "jest-util": "^29.7.0", "string-length": "^4.0.1" }, "engines": { @@ -4128,14 +4351,12 @@ } }, "node_modules/jest-worker": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.5.0.tgz", - "integrity": "sha512-NcrQnevGoSp4b5kg+akIpthoAFHxPBcb5P6mYPY0fUNT+sSvmtu6jlkEle3anczUKIKEbMxFimk9oTP/tpIPgA==", - "dev": true, - "peer": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", "dependencies": { "@types/node": "*", - "jest-util": "^29.5.0", + "jest-util": "^29.7.0", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -4147,8 +4368,6 @@ "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "peer": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -4162,15 +4381,12 @@ "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "node_modules/js-yaml": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "peer": true, "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -4179,30 +4395,31 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==" + }, "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "bin": { "jsesc": "bin/jsesc" }, "engines": { - "node": ">=4" + "node": ">=6" } }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true, - "peer": true + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, "bin": { "json5": "lib/cli.js" }, @@ -4210,6 +4427,17 @@ "node": ">=6" } }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, "node_modules/just-extend": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", @@ -4220,8 +4448,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true, - "peer": true, "engines": { "node": ">=6" } @@ -4230,8 +4456,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true, - "peer": true, "engines": { "node": ">=6" } @@ -4239,16 +4463,12 @@ "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true, - "peer": true + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" }, "node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "peer": true, "dependencies": { "p-locate": "^4.1.0" }, @@ -4278,39 +4498,45 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, "dependencies": { "yallist": "^3.0.2" } }, "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "peer": true, + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dependencies": { - "semver": "^6.0.0" + "semver": "^7.5.3" }, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/make-dir/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true + "devOptional": true }, "node_modules/makeerror": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dev": true, - "peer": true, "dependencies": { "tmpl": "1.0.5" } @@ -4318,17 +4544,14 @@ "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true, - "peer": true + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -4358,8 +4581,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "peer": true, "engines": { "node": ">=6" } @@ -4368,7 +4589,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -4376,6 +4596,11 @@ "node": "*" } }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==" + }, "node_modules/mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", @@ -4391,15 +4616,20 @@ "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true, - "peer": true + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" + }, + "node_modules/netmask": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", + "engines": { + "node": ">= 0.4.0" + } }, "node_modules/nise": { "version": "4.1.0", @@ -4435,22 +4665,17 @@ "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true, - "peer": true + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==" }, "node_modules/node-releases": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", - "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", - "dev": true + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==" }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "peer": true, "engines": { "node": ">=0.10.0" } @@ -4459,8 +4684,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "peer": true, "dependencies": { "path-key": "^3.0.0" }, @@ -4472,7 +4695,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, "dependencies": { "wrappy": "1" } @@ -4481,8 +4703,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "peer": true, "dependencies": { "mimic-fn": "^2.1.0" }, @@ -4493,12 +4713,26 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "peer": true, "dependencies": { "yocto-queue": "^0.1.0" }, @@ -4513,8 +4747,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "peer": true, "dependencies": { "p-limit": "^2.2.0" }, @@ -4526,8 +4758,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "peer": true, "dependencies": { "p-try": "^2.0.0" }, @@ -4542,8 +4772,47 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pac-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.2.tgz", + "integrity": "sha512-BFi3vZnO9X5Qt6NRz7ZOaPja3ic0PhlsmCRYLOpN11+mWBCR6XJDqW5RF3j8jm4WGGQZtBA+bTfxYzeKW73eHg==", + "dependencies": { + "@tootallnate/quickjs-emscripten": "^0.23.0", + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "get-uri": "^6.0.1", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.5", + "pac-resolver": "^7.0.1", + "socks-proxy-agent": "^8.0.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-resolver": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", + "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", + "dependencies": { + "degenerator": "^5.0.0", + "netmask": "^2.0.2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dependencies": { + "callsites": "^3.0.0" + }, "engines": { "node": ">=6" } @@ -4552,8 +4821,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "peer": true, "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", @@ -4571,8 +4838,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "peer": true, "engines": { "node": ">=8" } @@ -4581,7 +4846,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -4590,8 +4854,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "peer": true, "engines": { "node": ">=8" } @@ -4599,29 +4861,31 @@ "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "node_modules/path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.9.0.tgz", + "integrity": "sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==", "dev": true, "dependencies": { "isarray": "0.0.1" } }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==" + }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, "engines": { "node": ">=8.6" }, @@ -4633,8 +4897,6 @@ "version": "4.0.5", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", - "dev": true, - "peer": true, "engines": { "node": ">= 6" } @@ -4643,8 +4905,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "peer": true, "dependencies": { "find-up": "^4.0.0" }, @@ -4653,12 +4913,11 @@ } }, "node_modules/pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", - "dev": true, + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dependencies": { - "@jest/schemas": "^29.4.3", + "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -4670,7 +4929,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, "engines": { "node": ">=10" }, @@ -4678,12 +4936,18 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dev": true, - "peer": true, "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" @@ -4692,16 +4956,83 @@ "node": ">= 6" } }, + "node_modules/proxy-agent": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz", + "integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "http-proxy-agent": "^7.0.1", + "https-proxy-agent": "^7.0.3", + "lru-cache": "^7.14.1", + "pac-proxy-agent": "^7.0.1", + "proxy-from-env": "^1.1.0", + "socks-proxy-agent": "^8.0.2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-agent/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "engines": { + "node": ">=12" + } + }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/puppeteer": { + "version": "22.13.1", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-22.13.1.tgz", + "integrity": "sha512-PwXLDQK5u83Fm5A7TGMq+9BR7iHDJ8a3h21PSsh/E6VfhxiKYkU7+tvGZNSCap6k3pCNDd9oNteVBEctcBalmQ==", + "hasInstallScript": true, + "dependencies": { + "@puppeteer/browsers": "2.2.4", + "cosmiconfig": "^9.0.0", + "devtools-protocol": "0.0.1299070", + "puppeteer-core": "22.13.1" + }, + "bin": { + "puppeteer": "lib/esm/puppeteer/node/cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/puppeteer-core": { + "version": "22.13.1", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-22.13.1.tgz", + "integrity": "sha512-NmhnASYp51QPRCAf9n0OPxuPMmzkKd8+2sB9Q+BjwwCG25gz6iuNc3LQDWa+cH2tyivmJppLhNNFt6Q3HmoOpw==", + "dependencies": { + "@puppeteer/browsers": "2.2.4", + "chromium-bidi": "0.6.1", + "debug": "^4.3.5", + "devtools-protocol": "0.0.1299070", + "ws": "^8.18.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/pure-rand": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.1.tgz", - "integrity": "sha512-t+x1zEHDjBwkDGY5v5ApnZ/utcd4XYDiJsaQQoptTXgUXX95sDg1elCdJghzicm7n2mbCBJ3uYWr6M22SO19rg==", - "dev": true, + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", "funding": [ { "type": "individual", @@ -4711,14 +5042,17 @@ "type": "opencollective", "url": "https://opencollective.com/fast-check" } - ], - "peer": true + ] + }, + "node_modules/queue-tick": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", + "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==" }, "node_modules/react-is": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, "node_modules/regenerate": { "version": "1.4.2", @@ -4795,8 +5129,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "peer": true, "engines": { "node": ">=0.10.0" } @@ -4805,7 +5137,6 @@ "version": "1.22.2", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", - "dev": true, "dependencies": { "is-core-module": "^2.11.0", "path-parse": "^1.0.7", @@ -4822,8 +5153,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "peer": true, "dependencies": { "resolve-from": "^5.0.0" }, @@ -4835,18 +5164,14 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "peer": true, "engines": { "node": ">=8" } }, "node_modules/resolve.exports": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", - "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", - "dev": true, - "peer": true, + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", "engines": { "node": ">=10" } @@ -4867,10 +5192,9 @@ } }, "node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "bin": { "semver": "bin/semver.js" } @@ -4879,8 +5203,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "peer": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -4892,8 +5214,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "peer": true, "engines": { "node": ">=8" } @@ -4901,9 +5221,7 @@ "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "peer": true + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "node_modules/sinon": { "version": "9.2.4", @@ -4944,25 +5262,55 @@ "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true, - "peer": true + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, "engines": { "node": ">=8" } }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", + "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "dependencies": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", + "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", + "dependencies": { + "agent-base": "^7.1.1", + "debug": "^4.3.4", + "socks": "^2.8.3" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "peer": true, "engines": { "node": ">=0.10.0" } @@ -4971,8 +5319,6 @@ "version": "0.5.13", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", - "dev": true, - "peer": true, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -4981,15 +5327,12 @@ "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true, - "peer": true + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" }, "node_modules/stack-utils": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", - "dev": true, "dependencies": { "escape-string-regexp": "^2.0.0" }, @@ -4997,12 +5340,23 @@ "node": ">=10" } }, + "node_modules/streamx": { + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.18.0.tgz", + "integrity": "sha512-LLUC1TWdjVdn1weXGcSxyTR3T4+acB6tVGXT95y0nGbca4t4o/ng1wKAGTljm9VicuCVLvRlqFYXYy5GwgM7sQ==", + "dependencies": { + "fast-fifo": "^1.3.2", + "queue-tick": "^1.0.1", + "text-decoder": "^1.1.0" + }, + "optionalDependencies": { + "bare-events": "^2.2.0" + } + }, "node_modules/string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "dev": true, - "peer": true, "dependencies": { "char-regex": "^1.0.2", "strip-ansi": "^6.0.0" @@ -5015,8 +5369,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "peer": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -5030,7 +5382,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -5042,8 +5393,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true, - "peer": true, "engines": { "node": ">=8" } @@ -5052,8 +5401,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "peer": true, "engines": { "node": ">=6" } @@ -5062,8 +5409,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "peer": true, "engines": { "node": ">=8" }, @@ -5075,7 +5420,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -5087,7 +5431,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -5095,20 +5438,42 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/tar-fs": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.6.tgz", + "integrity": "sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w==", + "dependencies": { + "pump": "^3.0.0", + "tar-stream": "^3.1.5" + }, + "optionalDependencies": { + "bare-fs": "^2.1.1", + "bare-path": "^2.1.0" + } + }, + "node_modules/tar-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "dependencies": { + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, "node_modules/tdei-client": { - "version": "1.1.1", - "resolved": "git+ssh://git@github.com/TaskarCenterAtUW/TDEI-api-client.git#be4b1ba800fac3165d8165879bf56cd4c031cbac", + "version": "1.1.83", + "resolved": "git+ssh://git@github.com/TaskarCenterAtUW/TDEI-api-client.git#1b646f12d6d6f14378395d8ee9fa54cff30dfe07", + "integrity": "sha512-DwDiw8EknM3r9T0mtosIslYgUZ/K1QluCVjUWzTQq9feqBk9uZ9YbWDiyK1iFChwcLSCHaBJYfiMET1chL4h3A==", "license": "Unlicense", "dependencies": { - "axios": "1.3.5" + "axios": "^1.6.5" } }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "peer": true, "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", @@ -5118,27 +5483,28 @@ "node": ">=8" } }, + "node_modules/text-decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.1.1.tgz", + "integrity": "sha512-8zll7REEv4GDD3x4/0pW+ppIxSNs7H1J10IKFZsuOMscumCdM2a+toDGLPA3T+1+fLBql4zbt5z83GEQGGV5VA==", + "dependencies": { + "b4a": "^1.6.4" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" + }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true, - "peer": true - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "engines": { - "node": ">=4" - } + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==" }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "dependencies": { "is-number": "^7.0.0" }, @@ -5202,9 +5568,9 @@ } }, "node_modules/ts-jest/node_modules/semver": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.4.0.tgz", - "integrity": "sha512-RgOxM8Mw+7Zus0+zcLEUn8+JfoLpj/huFTItQy2hsM4khuC1HYRDp0cU482Ewn/Fcy6bCjufD8vAj7voC66KQw==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -5226,7 +5592,7 @@ "version": "10.9.1", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", - "dev": true, + "devOptional": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -5265,11 +5631,15 @@ } } }, + "node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" + }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, "engines": { "node": ">=4" } @@ -5278,8 +5648,6 @@ "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "peer": true, "engines": { "node": ">=10" }, @@ -5299,6 +5667,15 @@ "node": ">=12.20" } }, + "node_modules/unbzip2-stream": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "dependencies": { + "buffer": "^5.2.1", + "through": "^2.3.8" + } + }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", @@ -5339,11 +5716,18 @@ "node": ">=4" } }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/update-browserslist-db": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", - "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", - "dev": true, + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", "funding": [ { "type": "opencollective", @@ -5352,53 +5736,51 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.2.0", + "picocolors": "^1.1.1" }, "bin": { - "browserslist-lint": "cli.js" + "update-browserslist-db": "cli.js" }, "peerDependencies": { "browserslist": ">= 4.21.0" } }, + "node_modules/urlpattern-polyfill": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz", + "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==" + }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true + "devOptional": true }, "node_modules/v8-to-istanbul": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", - "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", - "dev": true, - "peer": true, + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0" + "convert-source-map": "^2.0.0" }, "engines": { "node": ">=10.12.0" } }, - "node_modules/v8-to-istanbul/node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true, - "peer": true - }, "node_modules/walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "dev": true, - "peer": true, "dependencies": { "makeerror": "1.0.12" } @@ -5407,8 +5789,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "peer": true, "dependencies": { "isexe": "^2.0.0" }, @@ -5423,8 +5803,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "peer": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -5440,15 +5818,12 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "node_modules/write-file-atomic": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", - "dev": true, - "peer": true, "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^3.0.7" @@ -5457,6 +5832,26 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/xmlbuilder": { "version": "15.0.0", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.0.0.tgz", @@ -5470,8 +5865,6 @@ "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "peer": true, "engines": { "node": ">=10" } @@ -5479,15 +5872,12 @@ "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" }, "node_modules/yargs": { - "version": "17.7.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", - "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", - "dev": true, - "peer": true, + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -5505,16 +5895,24 @@ "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/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, + "devOptional": true, "engines": { "node": ">=6" } @@ -5523,14 +5921,20 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "peer": true, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zod": { + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } } } } diff --git a/package.json b/package.json index 86110d8..5b41409 100644 --- a/package.json +++ b/package.json @@ -4,25 +4,35 @@ "description": "", "main": "index.js", "scripts": { - "test": "jest", + "test": "jest --runInBand", "build": "rimraf ./build && tsc", - "start": "npm run build && node build/index.js" + "start": "npm run build && node build/index.js", + "e2e-tests": "jest --testRegex src/**/*.e2e.test.ts", + "integration-tests": "jest --testRegex src/**/*.it.test.ts", + "regression-tests": "jest --testRegex src/**/*.rt.test.ts" }, "keywords": [], "author": "Naresh Kumar", "license": "ISC", "devDependencies": { - "@types/node": "18.15.11", + "@types/adm-zip": "0.5.0", "@types/jest": "29.5.0", + "@types/node": "18.15.11", + "adm-zip": "0.5.10", + "jest-extended": "^4.0.2", + "jest-html-reporter": "3.7.1", "rimraf": "^3.0.2", - "ts-node": "^10.9.1", - "ts-jest":"29.1.0", - "jest-html-reporter": "3.7.1" + "ts-jest": "29.1.0", + "ts-node": "^10.9.1" }, "dependencies": { - "axios":"1.3.5", - "typescript":"5.0.4", - "tdei-client":"git+https://github.com/TaskarCenterAtUW/TDEI-api-client.git" - + "@faker-js/faker": "^7.6.0", + "axios": "^1.7.7", + "dotenv": "^16.3.1", + "jest": "^29.7.0", + "jest-html-reporters": "^3.1.7", + "puppeteer": "^22.6.5", + "tdei-client": "git+https://github.com/TaskarCenterAtUW/TDEI-api-client.git#1b646f12d6d6f14378395d8ee9fa54cff30dfe07", + "typescript": "5.0.4" } } diff --git a/performance-test/TDEI _Test_Plan.jmx b/performance-test/TDEI _Test_Plan.jmx new file mode 100644 index 0000000..2672a17 --- /dev/null +++ b/performance-test/TDEI _Test_Plan.jmx @@ -0,0 +1,4286 @@ + + + + + + false + true + true + + + + + + + + + + adminUserName + ${__P(adminId, admin@tdei.com)} + = + + + adminUserPwd + ${__P(adminPwd, admin)} + = + + + usermanagementhost + ${__P(host,tdei-usermanagement-ts-dev.azurewebsites.net)} + = + + + defaultPassword + ${__P(password,Password01*)} + = + + + gatewayhost + ${__P(host,tdei-gateway-dev.azurewebsites.net)} + = + + + + + + + + 200 + 0 + 5 + 60 + 10 + + + + false + -1 + + continue + + + + + + + tdei-gateway-dev.azurewebsites.net + + https + + /api/v1/osw?page_no=1&page_size=10 + GET + true + false + true + false + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + + + content-type + application/json + + + x-api-key + 67AF1DAC088C42D5BBF806D010D9DFC1 + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 1000 + 2 + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 1000 + false + + + + + false + false + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 500 + true + + + + + false + false + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 1000 + false + + + + + false + false + + + + + + + + 50 + 0 + 5 + 60 + 10 + + + + false + -1 + + continue + + + + + + + tdei-gateway-dev.azurewebsites.net + + https + + /api/v1/gtfs-pathways?page_no=1&page_size=10 + GET + true + false + true + false + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + true + true + true + true + true + false + true + true + true + false + true + 0 + true + true + true + true + true + true + true + true + true + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + + + content-type + application/json + + + x-api-key + 67AF1DAC088C42D5BBF806D010D9DFC1 + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 1000 + 2 + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 1000 + false + + + + + false + false + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 500 + true + + + + + false + false + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 1000 + false + + + + + false + false + + + + + + + + tdei-gateway-dev.azurewebsites.net + + https + + /api/v1/gtfs-pathways/stations?page_no=1&page_size=10 + GET + true + false + true + false + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + true + true + true + true + true + false + true + true + true + false + true + 0 + true + true + true + true + true + true + true + true + true + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + + + content-type + application/json + + + x-api-key + 67AF1DAC088C42D5BBF806D010D9DFC1 + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 1000 + 2 + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 1000 + false + + + + + false + false + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 500 + true + + + + + false + false + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 1000 + false + + + + + false + false + + + + + + + + 50 + 0 + 5 + 60 + 10 + + + + false + -1 + + continue + + + + + + + tdei-gateway-dev.azurewebsites.net + + https + + /api/v1/gtfs-flex?page_no=1&page_size=10 + GET + true + false + true + false + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + + + content-type + application/json + + + x-api-key + 67AF1DAC088C42D5BBF806D010D9DFC1 + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 1000 + 2 + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 1000 + false + + + + + false + false + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 500 + true + + + + + false + false + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 1000 + false + + + + + false + false + + + + + + + + tdei-gateway-dev.azurewebsites.net + + https + + /api/v1/gtfs-flex/services?page_no=1&page_size=10 + GET + true + false + true + false + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + + + content-type + application/json + + + x-api-key + 67AF1DAC088C42D5BBF806D010D9DFC1 + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 1000 + 2 + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 1000 + false + + + + + false + false + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 500 + true + + + + + false + false + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 1000 + false + + + + + false + false + + + + + + + + 50 + 0 + 5 + 60 + 10 + + + + false + -1 + + continue + + + + + + + tdei-gateway-dev.azurewebsites.net + + https + + /api/v1/organizations?page_no=1&page_size=10 + GET + true + false + true + false + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + /Users/mahesh/Downloads/Performance Test/Org-Gateway-Test + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + + + content-type + application/json + + + x-api-key + 67AF1DAC088C42D5BBF806D010D9DFC1 + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 1000 + 2 + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 1000 + false + + + + + false + false + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 500 + true + + + + + false + false + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 1000 + false + + + + + false + false + + + + + + + + 50 + 0 + 5 + 60 + 10 + + + + false + -1 + + continue + + + + + + + localhost + 8080 + http + + /api/v1/organization?page_no=1&page_size=10 + GET + true + false + true + false + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + + + content-type + application/json + + + x-api-key + 67AF1DAC088C42D5BBF806D010D9DFC1 + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 1000 + 2 + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 1000 + false + + + + + false + false + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 500 + true + + + + + false + false + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 1000 + false + + + + + false + false + + + + + + continue + + false + 1 + + 1 + 1 + false + + + true + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + true + true + true + false + + + + true + + + + false + { + "firstName": "Test_${__RandomString(5,qwertyuiopasdfghjklzxcvbnm,)}", + "lastName": "Test_${__RandomString(5,qwertyuiopasdfghjklzxcvbnm,)}", + "email": "USER_${__RandomString(5,qwertyuiopasdfghjklzxcvbnm,NEW_USER_EMAIL)}@gmail.com", + "phone": "${__RandomString(10,1234567890,)}", + "password": "${defaultPassword}" +} + = + + + + ${usermanagementhost} + + https + + /api/v1/register + POST + true + false + true + false + + + + Registers the new user + + + + newUserName + $.data.username + 1 + NOTFOUND + + + + + + Content-Type + application/json + + + + + + props.put("p_newUserName", vars.get("newUserName")); + + + false + + + + + true + + + + false + { + "username": "${adminUserName}", + "password": "${adminUserPwd}" +} + = + + + + ${usermanagementhost} + + https + + /api/v1/authenticate + POST + true + false + true + false + + + + + + + adminToken + $.access_token + 1 + TokenNotFound + + + + + + Content-Type + application/json + + + + + + props.put("p_adminToken", vars.get("adminToken")); + + + false + + + + + true + + + + false + { + "org_name": "Org_${__RandomString(5,qwertyuiopasdfghjklzxcvbnm,)}", + "phone": "${__RandomString(10,1234567890,)}", + "url": "https://${__RandomString(5,qwertyuiopasdfghjklzxcvbnm,)}.com", + "address": "${__RandomString(5,qwertyuiopasdfghjklzxcvbnm,)}, Seattle, QA, USA", + "polygon": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + 77.588807608, + 12.976222962 + ], + [ + 77.589285425, + 12.972094479 + ], + [ + 77.593012392, + 12.974608826 + ], + [ + 77.588839463, + 12.976254003 + ], + [ + 77.588807608, + 12.976222962 + ] + ] + ] + }, + "properties": {} + } + ] + } +} + = + + + + ${usermanagementhost} + + https + + /api/v1/organization + POST + true + false + true + false + + + + Admin creates new organization + + + + + + Content-Type + application/json + + + + + + newOrgId + $.data + 1 + RecordNotFound + + + + + + false + import org.apache.jmeter.protocol.http.control.Header; +sampler.getHeaderManager().add(new Header("Authorization", "Bearer " + props.get("p_adminToken"))); + + + + props.put("p_newOrgId", vars.get("newOrgId")); + + + false + + + + + true + + + + false + { + "tdei_org_id": "${newOrgId}", + "user_name": "${newUserName}", + "roles": [ + "poc" + ] +} + = + + + + ${usermanagementhost} + + https + + /api/v1/permission + POST + true + false + true + false + + + + + + + + + Content-Type + application/json + + + + + + + + false + import org.apache.jmeter.protocol.http.control.Header; +sampler.getHeaderManager().add(new Header("Authorization", "Bearer " + props.get("p_adminToken"))); + + + + + true + + + + false + { + "username": "${newUserName}", + "password": "${defaultPassword}" +} + = + + + + ${usermanagementhost} + + https + + /api/v1/authenticate + POST + true + false + true + false + + + + + + + newUserToken + $.access_token + 1 + TokenNotFound + + + + + + Content-Type + application/json + + + + + + props.put("p_newUserToken", vars.get("newUserToken")); + + + false + + + + + true + + + + false + { + "tdei_org_id": "${newOrgId}", + "station_name": "Test__${__RandomString(5,qwertyuiopasdfghjklzxcvbnm,)}", + "polygon": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + 77.588807608, + 12.976222962 + ], + [ + 77.589285425, + 12.972094479 + ], + [ + 77.593012392, + 12.974608826 + ], + [ + 77.588839463, + 12.976254003 + ], + [ + 77.588807608, + 12.976222962 + ] + ] + ] + }, + "properties": {} + } + ] + } +} + = + + + + ${usermanagementhost} + + https + + /api/v1/station + POST + true + false + true + false + + + + Create station for the new organization + + + + + + Content-Type + application/json + + + + + + stationId + $.data + 1 + StationNotFound + + + + + + false + import org.apache.jmeter.protocol.http.control.Header; +sampler.getHeaderManager().add(new Header("Authorization", "Bearer " + props.get("p_newUserToken"))); + + + + props.put("p_stationId", vars.get("stationId")); + + + false + + + + + true + + + + false + { + "tdei_org_id": "${newOrgId}", + "service_name": "Test__${__RandomString(5,qwertyuiopasdfghjklzxcvbnm,)}", + "polygon": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + 77.588807608, + 12.976222962 + ], + [ + 77.589285425, + 12.972094479 + ], + [ + 77.593012392, + 12.974608826 + ], + [ + 77.588839463, + 12.976254003 + ], + [ + 77.588807608, + 12.976222962 + ] + ] + ] + }, + "properties": {} + } + ] + } +} + = + + + + ${usermanagementhost} + + https + + /api/v1/service + POST + true + false + true + false + + + + Create service for the new organization + + + + + + Content-Type + application/json + + + + + + serviceId + $.data + 1 + ServiceNotFound + + + + + + false + import org.apache.jmeter.protocol.http.control.Header; +sampler.getHeaderManager().add(new Header("Authorization", "Bearer " + props.get("p_newUserToken"))); + + + + props.put("p_serviceId", vars.get("serviceId")); + + + false + + + + + + + + 25 + 0 + 30 + 60 + 10 + + + + false + -1 + + continue + + + + + + + application/zip + pathways_success.zip + file + + + + + + + false + { "tdei_org_id": "${__property(p_newOrgId)}", "tdei_station_id": "${__property(p_stationId)}", "collected_by": "6D3E5B8C-FB16-4B6A-9436-72FD24756CC9", "collection_date": "2022-12-29T06:02:34.343Z", "collection_method": "manual", "valid_from": "2022-12-29T06:02:34.343Z", "valid_to": "2022-12-29T06:02:34.343Z", "data_source": "InHouse", "pathways_schema_version": "v1.0", "polygon": {"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[77.588807608,12.976222962],[77.589285425,12.972094479],[77.593012392,12.974608826],[77.588839463,12.976254003],[77.588807608,12.976222962]]]}}]} } + = + true + meta + application/json + + + + ${gatewayhost} + + https + + /api/v1/gtfs-pathways + POST + true + false + true + true + + + + + + + + + false + import org.apache.jmeter.protocol.http.control.Header; +sampler.getHeaderManager().removeHeaderNamed("Authorization"); +sampler.getHeaderManager().add(new Header("Authorization", "Bearer " + props.get("p_newUserToken"))); + + + + + + Content-Type + multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW + + + + + + false + recordId + (?s)(^.*) + $1$ + + 1 + true + + + + + 202 + + Authentication error + Assertion.response_code + false + 8 + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 1000 + 2 + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 1000 + false + + + + + false + false + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 500 + true + + + + + false + false + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 1000 + false + + + + + false + false + + + + + + + + 25 + 0 + 30 + 60 + 10 + + + + false + -1 + + continue + + + + + + + application/zip + flex_success.zip + file + + + + + + + false + { "tdei_org_id": "${__property(p_newOrgId)}", "tdei_service_id": "${__property(p_serviceId)}", "collected_by": "6D3E5B8C-FB16-4B6A-9436-72FD24756CC9", "collection_date": "2022-12-29T06:02:34.343Z", "collection_method": "manual", "valid_from": "2022-12-29T06:02:34.343Z", "valid_to": "2022-12-29T06:02:34.343Z", "data_source": "InHouse", "flex_schema_version": "v2.0", "polygon": {"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[77.588807608,12.976222962],[77.589285425,12.972094479],[77.593012392,12.974608826],[77.588839463,12.976254003],[77.588807608,12.976222962]]]}}]} } + = + true + meta + application/json + + + + ${gatewayhost} + + https + + /api/v1/gtfs-flex + POST + true + false + true + true + + + + + + + + + false + import org.apache.jmeter.protocol.http.control.Header; +sampler.getHeaderManager().removeHeaderNamed("Authorization"); +sampler.getHeaderManager().add(new Header("Authorization", "Bearer " + props.get("p_newUserToken"))); + + + + + + Content-Type + multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW + + + + + + false + recordId + (?s)(^.*) + $1$ + + 1 + true + + + + + 202 + + Authentication error + Assertion.response_code + false + 8 + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 1000 + 2 + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 1000 + false + + + + + false + false + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 500 + true + + + + + false + false + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 1000 + false + + + + + false + false + + + + + + + + 25 + 0 + 10 + 60 + 10 + + + + false + -1 + + continue + + + + + + + application/zip + osw-valid.zip + file + + + + + + + false + { "tdei_org_id": "${__property(p_newOrgId)}", "collected_by": "testUser", "collection_date": "2022-12-29T06:02:34.343Z", "collection_method": "manual", "publication_date": "2022-12-29T06:02:34.343Z","data_source": "InHouse", "osw_schema_version": "v0.1", "polygon": {"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[77.588807608,12.976222962],[77.589285425,12.972094479],[77.593012392,12.974608826],[77.588839463,12.976254003],[77.588807608,12.976222962]]]}}]} } + = + true + meta + application/json + + + + ${gatewayhost} + + https + + /api/v1/osw + POST + true + false + true + true + + + + + + + + + false + import org.apache.jmeter.protocol.http.control.Header; +sampler.getHeaderManager().removeHeaderNamed("Authorization"); +sampler.getHeaderManager().add(new Header("Authorization", "Bearer " + props.get("p_newUserToken"))); + + + + + + Content-Type + multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW + + + + + + false + recordId + (?s)(^.*) + $1$ + + 1 + true + + + + + 202 + + Authentication error + Assertion.response_code + false + 8 + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 1000 + 2 + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 1000 + false + + + + + false + false + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 500 + true + + + + + false + false + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + 1000 + false + + + + + false + false + + + + + + + + 100 + 0 + 30 + 60 + 10 + + + + false + -1 + + continue + + + + true + + + + false + { + "username": "${adminUserName}", + "password": "${adminUserPwd}" +} + = + + + + ${usermanagementhost} + + https + + /api/v1/authenticate + POST + true + false + true + false + + + + + + + + + Content-Type + application/json + + + + + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + true + true + true + false + + + + false + + saveConfig + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + true + false + false + false + true + 0 + true + true + true + true + true + true + + + + + + + + diff --git a/assets/payloads/gtfs-flex/files/success_1_all_attrs.zip b/performance-test/payload/flex_success.zip similarity index 100% rename from assets/payloads/gtfs-flex/files/success_1_all_attrs.zip rename to performance-test/payload/flex_success.zip diff --git a/performance-test/payload/osw-valid.zip b/performance-test/payload/osw-valid.zip new file mode 100644 index 0000000..ec132bd Binary files /dev/null and b/performance-test/payload/osw-valid.zip differ diff --git a/assets/payloads/gtfs-pathways/files/success_1_all_attrs.zip b/performance-test/payload/pathways_success.zip similarity index 100% rename from assets/payloads/gtfs-pathways/files/success_1_all_attrs.zip rename to performance-test/payload/pathways_success.zip diff --git a/performance-test/readme.md b/performance-test/readme.md new file mode 100644 index 0000000..27f2a81 --- /dev/null +++ b/performance-test/readme.md @@ -0,0 +1,41 @@ +# JMeter Performance Test + +## Prerequisites +- [Apache JMeter](https://jmeter.apache.org/download_jmeter.cgi) installed on your system. +- Ensure Java is installed and properly configured. + +## Running the Test + +1. Clone this repository or download the `performance-test` folder. + +2. Open a terminal and navigate to the directory where the `TDEI _Test_Plan.jmx` file is located. + +3. Execute the JMeter test in non-GUI mode: + + ```bash + jmeter -n -t TDEI _Test_Plan.jmx -l results.jtl + ``` + + - `-n`: Non-GUI mode + - `-t`: Path to the JMX file (test plan) + - `-l`: Path to save the test results (output file) + +4. To view the results: + + You can view the results using JMeter GUI or generate a report: + + ```bash + jmeter -g results.jtl -o /path/to/output/report + ``` + +5. Open the generated report in your browser: + + ```bash + open /path/to/output/report/index.html + ``` + +## Notes + +- Customize the `TDEI _Test_Plan.jmx` file as needed before running. +- Ensure that all required dependencies and test data are available for the test plan. +- Use JMeter desktop application for easy modification. Navigate to bin folder of jmeter and run `./jmeter` \ No newline at end of file diff --git a/performance-test/screenshots/Gateway-Perf-10-07.png b/performance-test/screenshots/Gateway-Perf-10-07.png new file mode 100644 index 0000000..2461459 Binary files /dev/null and b/performance-test/screenshots/Gateway-Perf-10-07.png differ diff --git a/performance-test/screenshots/Gtaeway-P1.png b/performance-test/screenshots/Gtaeway-P1.png new file mode 100644 index 0000000..8fde65e Binary files /dev/null and b/performance-test/screenshots/Gtaeway-P1.png differ diff --git a/performance-test/screenshots/Gtaeway-P2.png b/performance-test/screenshots/Gtaeway-P2.png new file mode 100644 index 0000000..9a4aef1 Binary files /dev/null and b/performance-test/screenshots/Gtaeway-P2.png differ diff --git a/performance-test/screenshots/Gtaeway-P3.png b/performance-test/screenshots/Gtaeway-P3.png new file mode 100644 index 0000000..e4a86b4 Binary files /dev/null and b/performance-test/screenshots/Gtaeway-P3.png differ diff --git a/performance-test/screenshots/Kraken-P1.png b/performance-test/screenshots/Kraken-P1.png new file mode 100644 index 0000000..2c7c28f Binary files /dev/null and b/performance-test/screenshots/Kraken-P1.png differ diff --git a/performance-test/screenshots/Kraken-P2.png b/performance-test/screenshots/Kraken-P2.png new file mode 100644 index 0000000..5bd7a46 Binary files /dev/null and b/performance-test/screenshots/Kraken-P2.png differ diff --git a/performance-test/screenshots/Kraken-P3.png b/performance-test/screenshots/Kraken-P3.png new file mode 100644 index 0000000..b5dc501 Binary files /dev/null and b/performance-test/screenshots/Kraken-P3.png differ diff --git a/performance-test/screenshots/Krakend-Gateway-Perf-10-07.png b/performance-test/screenshots/Krakend-Gateway-Perf-10-07.png new file mode 100644 index 0000000..cce42db Binary files /dev/null and b/performance-test/screenshots/Krakend-Gateway-Perf-10-07.png differ diff --git a/src/__tests__/general.test.ts b/src/__tests__/general.test.ts index 2707256..d3f3a51 100644 --- a/src/__tests__/general.test.ts +++ b/src/__tests__/general.test.ts @@ -1,42 +1,2310 @@ -// import { describe } from "node:test"; +import { Configuration, DatasetItemProjectGroup, DatasetItem, DatasetItemStatusEnum, CommonAPIsApi, VersionSpec, DatasetItemService, MetadataModelDatasetDetailCollectionMethodEnum, MetadataModelDatasetDetailDataSourceEnum, JobDetails, JobProgress, ServiceModel, AuthenticationApi, MetricsApi } from "tdei-client"; +import { Utility } from "../utils"; +import axios, { InternalAxiosRequestConfig } from "axios"; -import { Configuration, GeneralApi } from "tdei-client"; -// import { HarnessTester } from "../harness-tester"; -import testHarness from "../test-harness.json"; +const NULL_PARAM = void 0; +let defaultUserConfiguration: Configuration = {}; +let adminConfiguration: Configuration = {}; +let apiKeyConfiguration: Configuration = {}; +let pocConfiguration: Configuration = {}; +let flexDgConfiguration: Configuration = {}; +let pathwaysDgConfiguration: Configuration = {}; +let oswDgConfiguration: Configuration = {}; +let tdei_project_group_id: string = ""; +let tdei_service_id_osw: string = ""; +let tdei_service_id_flex: string = ""; +let tdei_service_id_pathways: string = ""; +let apiInput: any = {}; +let apiTesterConfiguration: Configuration = {}; +let apiTesterKeyConfiguration: Configuration = {}; -describe('General API', () =>{ +const cloneDatasetRequestInterceptor = (request: InternalAxiosRequestConfig, tdei_dataset_id: string, tdei_project_group_id: string, tdei_service_id: string, datasetName: string) => { + if ( + request.url === `${adminConfiguration.basePath}/api/v1/dataset/clone/${tdei_dataset_id}/${tdei_project_group_id}/${tdei_service_id}` + ) { + let data = request.data as FormData; + let metaFile = data.get("file") as File; + delete data['file']; + data.set('file', metaFile, datasetName); + } + return request; +}; - let configuration = new Configuration({ - username: testHarness.system.username, - password: testHarness.system.password, - basePath: testHarness.system.baseUrl - +beforeAll(async () => { + adminConfiguration = Utility.getAdminConfiguration(); + defaultUserConfiguration = Utility.getDefaultUserConfiguration(); + apiKeyConfiguration = Utility.getApiKeyConfiguration(); + pocConfiguration = Utility.getPocConfiguration(); + flexDgConfiguration = Utility.getFlexDataGeneratorConfiguration(); + pathwaysDgConfiguration = Utility.getPathwaysDataGeneratorConfiguration(); + oswDgConfiguration = Utility.getOSWDataGeneratorConfiguration(); + apiTesterConfiguration = Utility.getAPITesterConfiguration(); + apiTesterKeyConfiguration = Utility.getApiTesterKeyConfiguration(); + + + await Utility.setAuthToken(adminConfiguration); + await Utility.setAuthToken(defaultUserConfiguration); + await Utility.setAuthToken(pocConfiguration); + await Utility.setAuthToken(flexDgConfiguration); + await Utility.setAuthToken(pathwaysDgConfiguration); + await Utility.setAuthToken(oswDgConfiguration); + await Utility.setAuthToken(apiTesterConfiguration); + + + let seedData = Utility.seedData; + tdei_project_group_id = seedData.project_group.tdei_project_group_id; + tdei_service_id_osw = seedData.services.find(x => x.service_type == "osw")!.tdei_service_id; + tdei_service_id_flex = seedData.services.find(x => x.service_type == "flex")!.tdei_service_id; + tdei_service_id_pathways = seedData.services.find(x => x.service_type == "pathways")!.tdei_service_id; + apiInput = Utility.getApiInput(); + +}, 30000); + +describe('List Datasets', () => { + //MAN-05, MAN-06 + it('Default-User | Authenticated , When request made with Pre-Release filter, should return empty list', async () => { + let oswAPI = new CommonAPIsApi(defaultUserConfiguration); + + const datasetFiles = await oswAPI.listDatasetFiles( + NULL_PARAM, + // data_type, + "Pre-Release",// status, + ); + + expect(datasetFiles.status).toBe(200); + + expect(Array.isArray(datasetFiles.data)).toBe(true); + expect(datasetFiles.data).toBeEmpty(); + }); + + it('Default-User | Authenticated , When request made with Pre-Release dataset id filter which user does not have access, should return empty list', async () => { + let oswAPI = new CommonAPIsApi(defaultUserConfiguration); + + const datasetFiles = await oswAPI.listDatasetFiles( + NULL_PARAM,// data_type, + "All",// status, + NULL_PARAM,// name, + NULL_PARAM,// version, + NULL_PARAM,// data_source, + NULL_PARAM,// collection_method, + NULL_PARAM,// collected_by, + NULL_PARAM,// derived_from_dataset_id, + NULL_PARAM,// collection_date, + NULL_PARAM,// confidence_level, + NULL_PARAM,// schema_version, + NULL_PARAM,// tdei_project_group_id, + NULL_PARAM,// service_id, + NULL_PARAM,// valid_from, + NULL_PARAM,// valid_to, + apiInput.osw.pre_release_dataset + ); + + expect(datasetFiles.status).toBe(200); + + expect(Array.isArray(datasetFiles.data)).toBe(true); + expect(datasetFiles.data).toBeEmpty(); + }); + + it('POC | Authenticated , When request made with Pre-Release dataset id filter which user group owns, should return dataset list with details', async () => { + let oswAPI = new CommonAPIsApi(pocConfiguration); + + const datasetFiles = await oswAPI.listDatasetFiles( + NULL_PARAM,// data_type, + "All",// status, + NULL_PARAM,// name, + NULL_PARAM,// version, + NULL_PARAM,// data_source, + NULL_PARAM,// collection_method, + NULL_PARAM,// collected_by, + NULL_PARAM,// derived_from_dataset_id, + NULL_PARAM,// collection_date, + NULL_PARAM,// confidence_level, + NULL_PARAM,// schema_version, + NULL_PARAM,// tdei_project_group_id, + NULL_PARAM,// service_id, + NULL_PARAM,// valid_from, + NULL_PARAM,// valid_to, + apiInput.osw.pre_release_dataset + ); + + expect(datasetFiles.status).toBe(200); + + expect(Array.isArray(datasetFiles.data)).toBe(true); + expect(datasetFiles.data).not.toBeEmpty(); + }); + + it('API-Key | Authenticated , When request made with no filters, should return list of dataset', async () => { + let oswAPI = new CommonAPIsApi(apiKeyConfiguration); + + const datasetFiles = await oswAPI.listDatasetFiles(); + + expect(datasetFiles.status).toBe(200); + + expect(Array.isArray(datasetFiles.data)).toBe(true); + + datasetFiles.data.forEach(file => { + expect(file).toMatchObject({ + status: expect.toBeOneOf([DatasetItemStatusEnum.PreRelease.toString(), DatasetItemStatusEnum.Publish.toString()]), + derived_from_dataset_id: expect.toBeOneOf([null, expect.any(String)]), + uploaded_timestamp: expect.any(String), + project_group: expect.objectContaining({ + tdei_project_group_id: expect.any(String), + name: expect.any(String) + }), + service: expect.objectContaining({ + tdei_service_id: expect.any(String), + name: expect.any(String) + }), + tdei_dataset_id: expect.any(String), + download_url: expect.any(String) + }); + + // Special handling for metadata field which can be null or undefined + if (file.metadata.data_provenance && Object.keys(file.metadata.data_provenance).length > 0) { + expect.toBeAbsentOrNullOrString(file.metadata.data_provenance.full_dataset_name); + expect.toBeAbsentOrNullOrString(file.metadata.data_provenance.other_published_locations); + expect.toBeAbsentOrNullOrString(file.metadata.data_provenance.dataset_update_frequency_months); + expect.toBeAbsentOrNullOrString(file.metadata.data_provenance.schema_validation_run); + expect.toBeAbsentOrNullOrString(file.metadata.data_provenance.schema_validation_run_description); + expect.toBeAbsentOrNullOrString(file.metadata.data_provenance.allow_crowd_contributions); + expect.toBeAbsentOrNullOrString(file.metadata.data_provenance.location_inaccuracy_factors); + + } + if (file.metadata.dataset_detail) { + expect(file.metadata.dataset_detail).toEqual( + { + name: expect.toBeOneOf([null, expect.any(String)]), + description: expect.toBeOneOf([null, expect.any(String)]), + version: expect.toBeOneOf([null, expect.any(String)]), + custom_metadata: expect.toBeOneOf([null, expect.anything()]), + collected_by: expect.toBeOneOf([null, expect.any(String)]), + collection_date: expect.toBeOneOf([null, expect.any(String)]), + valid_from: expect.toBeOneOf([null, expect.any(String)]), + valid_to: expect.toBeOneOf([null, expect.toBeOneOf([null, expect.any(String)]),]), + collection_method: expect.toBeOneOf([ + null, + MetadataModelDatasetDetailCollectionMethodEnum.Generated.toString(), + MetadataModelDatasetDetailCollectionMethodEnum.Other.toString(), "others", + MetadataModelDatasetDetailCollectionMethodEnum.Transform.toString(), + MetadataModelDatasetDetailCollectionMethodEnum.Manual.toString()]), + data_source: expect.toBeOneOf([ + null, + MetadataModelDatasetDetailDataSourceEnum.InHouse.toString(), + MetadataModelDatasetDetailDataSourceEnum.TDEITools.toString(), + MetadataModelDatasetDetailDataSourceEnum._3rdParty.toString()]), + dataset_area: expect.toBeOneOf([null, expect.toBeObject()]), + schema_version: expect.toBeOneOf([null, expect.any(String)]), + } + ); + } + if (file.metadata.dataset_summary && Object.keys(file.metadata.dataset_summary).length > 0) { + expect.toBeAbsentOrNullOrString(file.metadata.dataset_summary.key_limitations); + expect.toBeAbsentOrNullOrString(file.metadata.dataset_summary.release_notes); + expect.toBeAbsentOrNullOrString(file.metadata.dataset_summary.collection_name); + expect.toBeAbsentOrNullOrString(file.metadata.dataset_summary.department_name); + expect.toBeAbsentOrNullOrString(file.metadata.dataset_summary.city); + expect.toBeAbsentOrNullOrString(file.metadata.dataset_summary.region); + expect.toBeAbsentOrNullOrString(file.metadata.dataset_summary.county); + expect.toBeAbsentOrNullOrString(file.metadata.dataset_summary.challenges); + } + if (file.metadata.maintenance && Object.keys(file.metadata.maintenance).length > 0) { + expect.toBeAbsentOrNullOrString(file.metadata.maintenance.official_maintainer); + expect.toBeAbsentOrNullOrString(file.metadata.maintenance.last_updated); + expect.toBeAbsentOrNullOrString(file.metadata.maintenance.update_frequency); + expect.toBeAbsentOrNullOrString(file.metadata.maintenance.authorization_chain); + expect.toBeAbsentOrNullOrString(file.metadata.maintenance.funding_details); + + } + if (file.metadata.methodology && Object.keys(file.metadata.methodology).length > 0) { + expect.toBeAbsentOrNullOrString(file.metadata.methodology.point_data_collection_device); + expect.toBeAbsentOrNullOrString(file.metadata.methodology.node_locations_and_attributes_editing_software); + expect.toBeAbsentOrNullOrString(file.metadata.methodology.data_collected_by_people); + expect.toBeAbsentOrNullOrString(file.metadata.methodology.data_collectors); + expect.toBeAbsentOrNullOrString(file.metadata.methodology.data_captured_automatically); + expect.toBeAbsentOrNullOrString(file.metadata.methodology.automated_collection); + expect.toBeAbsentOrNullOrString(file.metadata.methodology.data_collectors_organization); + expect.toBeAbsentOrNullOrString(file.metadata.methodology.data_collector_compensation); + expect.toBeAbsentOrNullOrString(file.metadata.methodology.preprocessing_location); + expect.toBeAbsentOrNullOrString(file.metadata.methodology.preprocessing_by); + expect.toBeAbsentOrNullOrString(file.metadata.methodology.preprocessing_steps); + expect.toBeAbsentOrNullOrString(file.metadata.methodology.data_collection_preprocessing_documentation); + expect.toBeAbsentOrNullOrString(file.metadata.methodology.documentation_uri); + expect.toBeAbsentOrNullOrString(file.metadata.methodology.validation_process_exists); + expect.toBeAbsentOrNullOrString(file.metadata.methodology.validation_process_description); + expect.toBeAbsentOrNullOrString(file.metadata.methodology.validation_conducted_by); + expect.toBeAbsentOrNullOrString(file.metadata.methodology.excluded_data); + expect.toBeAbsentOrNullOrString(file.metadata.methodology.excluded_data_reason); + } + }); + }); + + it('Admin | Authenticated , When request made with no filters, should return list of dataset', async () => { + let oswAPI = new CommonAPIsApi(adminConfiguration); + + const datasetFiles = await oswAPI.listDatasetFiles(); + + expect(datasetFiles.status).toBe(200); + + expect(Array.isArray(datasetFiles.data)).toBe(true); + + datasetFiles.data.forEach(file => { + expect(file).toMatchObject({ + status: expect.toBeOneOf([DatasetItemStatusEnum.PreRelease.toString(), DatasetItemStatusEnum.Publish.toString()]), + derived_from_dataset_id: expect.toBeOneOf([null, expect.any(String)]), + uploaded_timestamp: expect.any(String), + project_group: expect.objectContaining({ + tdei_project_group_id: expect.any(String), + name: expect.any(String) + }), + service: expect.objectContaining({ + tdei_service_id: expect.any(String), + name: expect.any(String) + }), + tdei_dataset_id: expect.any(String), + download_url: expect.any(String) + }); + + // Special handling for metadata field which can be null or undefined + if (file.metadata.data_provenance && Object.keys(file.metadata.data_provenance).length > 0) { + expect.toBeAbsentOrNullOrString(file.metadata.data_provenance.full_dataset_name); + expect.toBeAbsentOrNullOrString(file.metadata.data_provenance.other_published_locations); + expect.toBeAbsentOrNullOrString(file.metadata.data_provenance.dataset_update_frequency_months); + expect.toBeAbsentOrNullOrString(file.metadata.data_provenance.schema_validation_run); + expect.toBeAbsentOrNullOrString(file.metadata.data_provenance.schema_validation_run_description); + expect.toBeAbsentOrNullOrString(file.metadata.data_provenance.allow_crowd_contributions); + expect.toBeAbsentOrNullOrString(file.metadata.data_provenance.location_inaccuracy_factors); + + } + if (file.metadata.dataset_detail) { + expect(file.metadata.dataset_detail).toEqual( + { + name: expect.toBeOneOf([null, expect.any(String)]), + description: expect.toBeOneOf([null, expect.any(String)]), + version: expect.toBeOneOf([null, expect.any(String)]), + custom_metadata: expect.toBeOneOf([null, expect.anything()]), + collected_by: expect.toBeOneOf([null, expect.any(String)]), + collection_date: expect.toBeOneOf([null, expect.any(String)]), + valid_from: expect.toBeOneOf([null, expect.any(String)]), + valid_to: expect.toBeOneOf([null, expect.toBeOneOf([null, expect.any(String)]),]), + collection_method: expect.toBeOneOf([ + null, + MetadataModelDatasetDetailCollectionMethodEnum.Generated.toString(), + MetadataModelDatasetDetailCollectionMethodEnum.Other.toString(), "others", + MetadataModelDatasetDetailCollectionMethodEnum.Transform.toString(), + MetadataModelDatasetDetailCollectionMethodEnum.Manual.toString()]), + data_source: expect.toBeOneOf([ + null, + MetadataModelDatasetDetailDataSourceEnum.InHouse.toString(), + MetadataModelDatasetDetailDataSourceEnum.TDEITools.toString(), + MetadataModelDatasetDetailDataSourceEnum._3rdParty.toString()]), + dataset_area: expect.toBeOneOf([null, expect.toBeObject()]), + schema_version: expect.toBeOneOf([null, expect.any(String)]), + } + ); + } + if (file.metadata.dataset_summary && Object.keys(file.metadata.dataset_summary).length > 0) { + expect.toBeAbsentOrNullOrString(file.metadata.dataset_summary.key_limitations); + expect.toBeAbsentOrNullOrString(file.metadata.dataset_summary.release_notes); + expect.toBeAbsentOrNullOrString(file.metadata.dataset_summary.collection_name); + expect.toBeAbsentOrNullOrString(file.metadata.dataset_summary.department_name); + expect.toBeAbsentOrNullOrString(file.metadata.dataset_summary.city); + expect.toBeAbsentOrNullOrString(file.metadata.dataset_summary.region); + expect.toBeAbsentOrNullOrString(file.metadata.dataset_summary.county); + expect.toBeAbsentOrNullOrString(file.metadata.dataset_summary.challenges); + } + if (file.metadata.maintenance && Object.keys(file.metadata.maintenance).length > 0) { + expect.toBeAbsentOrNullOrString(file.metadata.maintenance.official_maintainer); + expect.toBeAbsentOrNullOrString(file.metadata.maintenance.last_updated); + expect.toBeAbsentOrNullOrString(file.metadata.maintenance.update_frequency); + expect.toBeAbsentOrNullOrString(file.metadata.maintenance.authorization_chain); + expect.toBeAbsentOrNullOrString(file.metadata.maintenance.funding_details); + + } + if (file.metadata.methodology && Object.keys(file.metadata.methodology).length > 0) { + expect.toBeAbsentOrNullOrString(file.metadata.methodology.point_data_collection_device); + expect.toBeAbsentOrNullOrString(file.metadata.methodology.node_locations_and_attributes_editing_software); + expect.toBeAbsentOrNullOrString(file.metadata.methodology.data_collected_by_people); + expect.toBeAbsentOrNullOrString(file.metadata.methodology.data_collectors); + expect.toBeAbsentOrNullOrString(file.metadata.methodology.data_captured_automatically); + expect.toBeAbsentOrNullOrString(file.metadata.methodology.automated_collection); + expect.toBeAbsentOrNullOrString(file.metadata.methodology.data_collectors_organization); + expect.toBeAbsentOrNullOrString(file.metadata.methodology.data_collector_compensation); + expect.toBeAbsentOrNullOrString(file.metadata.methodology.preprocessing_location); + expect.toBeAbsentOrNullOrString(file.metadata.methodology.preprocessing_by); + expect.toBeAbsentOrNullOrString(file.metadata.methodology.preprocessing_steps); + expect.toBeAbsentOrNullOrString(file.metadata.methodology.data_collection_preprocessing_documentation); + expect.toBeAbsentOrNullOrString(file.metadata.methodology.documentation_uri); + expect.toBeAbsentOrNullOrString(file.metadata.methodology.validation_process_exists); + expect.toBeAbsentOrNullOrString(file.metadata.methodology.validation_process_description); + expect.toBeAbsentOrNullOrString(file.metadata.methodology.validation_conducted_by); + expect.toBeAbsentOrNullOrString(file.metadata.methodology.excluded_data); + expect.toBeAbsentOrNullOrString(file.metadata.methodology.excluded_data_reason); + } + }); + }); + + it('Admin | Authenticated , When request made with page size, should return datasets less than or equal to page size', async () => { + let oswAPI = new CommonAPIsApi(adminConfiguration); + let page_size = 5; + + const datasetFiles = await oswAPI.listDatasetFiles( + NULL_PARAM,// data_type, + NULL_PARAM,// status, + NULL_PARAM,// name, + NULL_PARAM,// version, + NULL_PARAM,// data_source, + NULL_PARAM,// collection_method, + NULL_PARAM,// collected_by, + NULL_PARAM,// derived_from_dataset_id, + NULL_PARAM,// collection_date, + NULL_PARAM,// confidence_level, + NULL_PARAM,// schema_version, + NULL_PARAM,// tdei_project_group_id, + NULL_PARAM,// service_id, + NULL_PARAM,// valid_from, + NULL_PARAM,// valid_to, + NULL_PARAM,// tdei_dataset_id, + NULL_PARAM,// bbox, + NULL_PARAM,// other_published_locations, + NULL_PARAM,// dataset_update_frequency_months, + NULL_PARAM,// schema_validation_run_description, + NULL_PARAM,// full_dataset_name, + NULL_PARAM,// collection_name, + NULL_PARAM,// department_name, + NULL_PARAM,// city, + NULL_PARAM,// region, + NULL_PARAM,// county, + NULL_PARAM,// key_limitations, + NULL_PARAM,// release notes, + NULL_PARAM,// challenges, + NULL_PARAM,// official_maintainer, + NULL_PARAM,// last_updated, + NULL_PARAM,// update_frequency, + NULL_PARAM,// authorization_chain, + NULL_PARAM,// maintenance_funded, + NULL_PARAM,// funding_details, + NULL_PARAM,// point_data_collection_device, + NULL_PARAM,// node_locations_and_attributes_editing_software, + NULL_PARAM,// data_collected_by_people, + NULL_PARAM,// data_collectors, + NULL_PARAM,// data_captured_automatically, + NULL_PARAM,// automated_collection, + NULL_PARAM,// data_collectors_organization, + NULL_PARAM,// data_collector_compensation, + NULL_PARAM,// preprocessing_location, + NULL_PARAM,// preprocessing_by, + NULL_PARAM,// preprocessing_steps, + NULL_PARAM,// data_collection_preprocessing_documentation, + NULL_PARAM,// documentation_uri, + NULL_PARAM,// validation_process_exists, + NULL_PARAM,// validation_process_description, + NULL_PARAM,// validation_conducted_by, + NULL_PARAM,// excluded_data, + NULL_PARAM,// excluded_data_reason, + NULL_PARAM,// page_no, + page_size, + "status", + "asc" + // options ?: AxiosRequestConfig + ); + + expect(datasetFiles.status).toBe(200); + expect(datasetFiles.data.length).toBeLessThanOrEqual(page_size); + + + }); + + it('Admin | Authenticated , When request made with project group Id, should return datasets of the specified project group', async () => { + let oswAPI = new CommonAPIsApi(adminConfiguration); + //TODO: read from seeder or config + //let project_group_id = '5e339544-3b12-40a5-8acd-78c66d1fa981'; + const datasetFiles = await oswAPI.listDatasetFiles( + NULL_PARAM,// data_type, + "All",// status, + NULL_PARAM,// name, + NULL_PARAM,// version, + NULL_PARAM,// data_source, + NULL_PARAM,// collection_method, + NULL_PARAM,// collected_by, + NULL_PARAM,// derived_from_dataset_id, + NULL_PARAM,// collection_date, + NULL_PARAM,// confidence_level, + NULL_PARAM,// schema_version, + tdei_project_group_id,// tdei_project_group_id, + NULL_PARAM,// service_id, + NULL_PARAM,// valid_from, + NULL_PARAM,// valid_to, + NULL_PARAM,// tdei_dataset_id, + NULL_PARAM,// bbox, + NULL_PARAM,// other_published_locations, + NULL_PARAM,// dataset_update_frequency_months, + NULL_PARAM,// schema_validation_run_description, + NULL_PARAM,// full_dataset_name, + NULL_PARAM,// collection_name, + NULL_PARAM,// department_name, + NULL_PARAM,// city, + NULL_PARAM,// region, + NULL_PARAM,// county, + NULL_PARAM,// key_limitations, + NULL_PARAM,// release notes, + NULL_PARAM,// challenges, + NULL_PARAM,// official_maintainer, + NULL_PARAM,// last_updated, + NULL_PARAM,// update_frequency, + NULL_PARAM,// authorization_chain, + NULL_PARAM,// maintenance_funded, + NULL_PARAM,// funding_details, + NULL_PARAM,// point_data_collection_device, + NULL_PARAM,// node_locations_and_attributes_editing_software, + NULL_PARAM,// data_collected_by_people, + NULL_PARAM,// data_collectors, + NULL_PARAM,// data_captured_automatically, + NULL_PARAM,// automated_collection, + NULL_PARAM,// data_collectors_organization, + NULL_PARAM,// data_collector_compensation, + NULL_PARAM,// preprocessing_location, + NULL_PARAM,// preprocessing_by, + NULL_PARAM,// preprocessing_steps, + NULL_PARAM,// data_collection_preprocessing_documentation, + NULL_PARAM,// documentation_uri, + NULL_PARAM,// validation_process_exists, + NULL_PARAM,// validation_process_description, + NULL_PARAM,// validation_conducted_by, + NULL_PARAM,// excluded_data, + NULL_PARAM,// excluded_data_reason, + 1,// page_no, + 1,// page_size, + "valid_from", + "asc" + // options ?: AxiosRequestConfig + ); + + expect(datasetFiles.status).toBe(200); + datasetFiles.data.forEach(file => { + expect(file.project_group.tdei_project_group_id).toBe(tdei_project_group_id) + }) + + }); + + it('Admin | Authenticated , When request made with service Id, should return datasets of the specified service', async () => { + let oswAPI = new CommonAPIsApi(adminConfiguration); + //TODO: read from seeder or config + //let project_group_id = '5e339544-3b12-40a5-8acd-78c66d1fa981'; + const datasetFiles = await oswAPI.listDatasetFiles( + NULL_PARAM,// data_type, + "All",// status, + NULL_PARAM,// name, + NULL_PARAM,// version, + NULL_PARAM,// data_source, + NULL_PARAM,// collection_method, + NULL_PARAM,// collected_by, + NULL_PARAM,// derived_from_dataset_id, + NULL_PARAM,// collection_date, + NULL_PARAM,// confidence_level, + NULL_PARAM,// schema_version, + NULL_PARAM,// tdei_project_group_id, + tdei_service_id_osw,// service_id, + NULL_PARAM,// valid_from, + NULL_PARAM,// valid_to, + NULL_PARAM,// tdei_dataset_id, + NULL_PARAM,// bbox, + NULL_PARAM,// other_published_locations, + NULL_PARAM,// dataset_update_frequency_months, + NULL_PARAM,// schema_validation_run_description, + NULL_PARAM,// full_dataset_name, + NULL_PARAM,// collection_name, + NULL_PARAM,// department_name, + NULL_PARAM,// city, + NULL_PARAM,// region, + NULL_PARAM,// county, + NULL_PARAM,// key_limitations, + NULL_PARAM,// release notes, + NULL_PARAM,// challenges, + NULL_PARAM,// official_maintainer, + NULL_PARAM,// last_updated, + NULL_PARAM,// update_frequency, + NULL_PARAM,// authorization_chain, + NULL_PARAM,// maintenance_funded, + NULL_PARAM,// funding_details, + NULL_PARAM,// point_data_collection_device, + NULL_PARAM,// node_locations_and_attributes_editing_software, + NULL_PARAM,// data_collected_by_people, + NULL_PARAM,// data_collectors, + NULL_PARAM,// data_captured_automatically, + NULL_PARAM,// automated_collection, + NULL_PARAM,// data_collectors_organization, + NULL_PARAM,// data_collector_compensation, + NULL_PARAM,// preprocessing_location, + NULL_PARAM,// preprocessing_by, + NULL_PARAM,// preprocessing_steps, + NULL_PARAM,// data_collection_preprocessing_documentation, + NULL_PARAM,// documentation_uri, + NULL_PARAM,// validation_process_exists, + NULL_PARAM,// validation_process_description, + NULL_PARAM,// validation_conducted_by, + NULL_PARAM,// excluded_data, + NULL_PARAM,// excluded_data_reason, + 1,// page_no, + 1,// page_size, + "valid_to", + "asc" + // options ?: AxiosRequestConfig + ); + + expect(datasetFiles.status).toBe(200); + datasetFiles.data.forEach(file => { + expect(file.service.tdei_service_id).toBe(tdei_service_id_osw) + }) + + }); + + it('Admin | Authenticated , When request made with tdei_dataset_id, should return dataset of the specified tdei_dataset_id', async () => { + let oswAPI = new CommonAPIsApi(adminConfiguration); + //let recordId = "40566429d02c4c80aee68c970977bed8"; + + const datasetFiles = await oswAPI.listDatasetFiles( + NULL_PARAM,// data_type, + "All",// status, + NULL_PARAM,// name, + NULL_PARAM,// version, + NULL_PARAM,// data_source, + NULL_PARAM,// collection_method, + NULL_PARAM,// collected_by, + NULL_PARAM,// derived_from_dataset_id, + NULL_PARAM,// collection_date, + NULL_PARAM,// confidence_level, + NULL_PARAM,// schema_version, + NULL_PARAM,// tdei_project_group_id, + NULL_PARAM,// service_id, + NULL_PARAM,// valid_from, + NULL_PARAM,// valid_to, + apiInput.osw.published_dataset,// tdei_dataset_id, + NULL_PARAM,// bbox, + NULL_PARAM,// other_published_locations, + NULL_PARAM,// dataset_update_frequency_months, + NULL_PARAM,// schema_validation_run_description, + NULL_PARAM,// full_dataset_name, + NULL_PARAM,// collection_name, + NULL_PARAM,// department_name, + NULL_PARAM,// city, + NULL_PARAM,// region, + NULL_PARAM,// county, + NULL_PARAM,// key_limitations, + NULL_PARAM,// release notes, + NULL_PARAM,// challenges, + NULL_PARAM,// official_maintainer, + NULL_PARAM,// last_updated, + NULL_PARAM,// update_frequency, + NULL_PARAM,// authorization_chain, + NULL_PARAM,// maintenance_funded, + NULL_PARAM,// funding_details, + NULL_PARAM,// point_data_collection_device, + NULL_PARAM,// node_locations_and_attributes_editing_software, + NULL_PARAM,// data_collected_by_people, + NULL_PARAM,// data_collectors, + NULL_PARAM,// data_captured_automatically, + NULL_PARAM,// automated_collection, + NULL_PARAM,// data_collectors_organization, + NULL_PARAM,// data_collector_compensation, + NULL_PARAM,// preprocessing_location, + NULL_PARAM,// preprocessing_by, + NULL_PARAM,// preprocessing_steps, + NULL_PARAM,// data_collection_preprocessing_documentation, + NULL_PARAM,// documentation_uri, + NULL_PARAM,// validation_process_exists, + NULL_PARAM,// validation_process_description, + NULL_PARAM,// validation_conducted_by, + NULL_PARAM,// excluded_data, + NULL_PARAM,// excluded_data_reason, + 1,// page_no, + 1,//page_size, + "uploaded_timestamp", + "asc" + // options ?: AxiosRequestConfig + ); + + expect(datasetFiles.status).toBe(200); + expect(datasetFiles.data.length).toBe(1); + datasetFiles.data.forEach(file => { + expect(file.tdei_dataset_id).toBe(apiInput.osw.published_dataset) + }); + }); + + it('Admin | Authenticated , When request made with schema_version, should return datasets matching schema_version', async () => { + let oswAPI = new CommonAPIsApi(adminConfiguration); + let schema_version = "v0.1"; + + const datasetFiles = await oswAPI.listDatasetFiles( + NULL_PARAM,// data_type, + "All",// status, + NULL_PARAM,// name, + NULL_PARAM,// version, + NULL_PARAM,// data_source, + NULL_PARAM,// collection_method, + NULL_PARAM,// collected_by, + NULL_PARAM,// derived_from_dataset_id, + NULL_PARAM,// collection_date, + NULL_PARAM,// confidence_level, + schema_version,// schema_version, + NULL_PARAM,// tdei_project_group_id, + NULL_PARAM,// service_id, + NULL_PARAM,// valid_from, + NULL_PARAM,// valid_to, + NULL_PARAM,// tdei_dataset_id, + NULL_PARAM,// bbox, + NULL_PARAM,// other_published_locations, + NULL_PARAM,// dataset_update_frequency_months, + NULL_PARAM,// schema_validation_run_description, + NULL_PARAM,// full_dataset_name, + NULL_PARAM,// collection_name, + NULL_PARAM,// department_name, + NULL_PARAM,// city, + NULL_PARAM,// region, + NULL_PARAM,// county, + NULL_PARAM,// key_limitations, + NULL_PARAM,// release notes, + NULL_PARAM,// challenges, + NULL_PARAM,// official_maintainer, + NULL_PARAM,// last_updated, + NULL_PARAM,// update_frequency, + NULL_PARAM,// authorization_chain, + NULL_PARAM,// maintenance_funded, + NULL_PARAM,// funding_details, + NULL_PARAM,// point_data_collection_device, + NULL_PARAM,// node_locations_and_attributes_editing_software, + NULL_PARAM,// data_collected_by_people, + NULL_PARAM,// data_collectors, + NULL_PARAM,// data_captured_automatically, + NULL_PARAM,// automated_collection, + NULL_PARAM,// data_collectors_organization, + NULL_PARAM,// data_collector_compensation, + NULL_PARAM,// preprocessing_location, + NULL_PARAM,// preprocessing_by, + NULL_PARAM,// preprocessing_steps, + NULL_PARAM,// data_collection_preprocessing_documentation, + NULL_PARAM,// documentation_uri, + NULL_PARAM,// validation_process_exists, + NULL_PARAM,// validation_process_description, + NULL_PARAM,// validation_conducted_by, + NULL_PARAM,// excluded_data, + NULL_PARAM,// excluded_data_reason, + 1,// page_no, + 1,//page_size, + "project_group_name", + "asc" + // options ?: AxiosRequestConfig + ); + + expect(datasetFiles.status).toBe(200); + datasetFiles.data.forEach(file => { + expect(file.metadata.dataset_detail!.schema_version).toContain(schema_version) + }); + }); + + it('Admin | Authenticated , When request made with name, should return dataset matching name', async () => { + let oswAPI = new CommonAPIsApi(adminConfiguration); + let name = "manual"; + + const datasetFiles = await oswAPI.listDatasetFiles( + NULL_PARAM,// data_type, + "All",// status, + name,// name, + NULL_PARAM,// version, + NULL_PARAM,// data_source, + NULL_PARAM,// collection_method, + NULL_PARAM,// collected_by, + NULL_PARAM,// derived_from_dataset_id, + NULL_PARAM,// collection_date, + NULL_PARAM,// confidence_level, + NULL_PARAM,// schema_version, + NULL_PARAM,// tdei_project_group_id, + NULL_PARAM,// service_id, + NULL_PARAM,// valid_from, + NULL_PARAM,// valid_to, + NULL_PARAM,// tdei_dataset_id, + NULL_PARAM,// bbox, + NULL_PARAM,// other_published_locations, + NULL_PARAM,// dataset_update_frequency_months, + NULL_PARAM,// schema_validation_run_description, + NULL_PARAM,// full_dataset_name, + NULL_PARAM,// collection_name, + NULL_PARAM,// department_name, + NULL_PARAM,// city, + NULL_PARAM,// region, + NULL_PARAM,// county, + NULL_PARAM,// key_limitations, + NULL_PARAM,// release notes, + NULL_PARAM,// challenges, + NULL_PARAM,// official_maintainer, + NULL_PARAM,// last_updated, + NULL_PARAM,// update_frequency, + NULL_PARAM,// authorization_chain, + NULL_PARAM,// maintenance_funded, + NULL_PARAM,// funding_details, + NULL_PARAM,// point_data_collection_device, + NULL_PARAM,// node_locations_and_attributes_editing_software, + NULL_PARAM,// data_collected_by_people, + NULL_PARAM,// data_collectors, + NULL_PARAM,// data_captured_automatically, + NULL_PARAM,// automated_collection, + NULL_PARAM,// data_collectors_organization, + NULL_PARAM,// data_collector_compensation, + NULL_PARAM,// preprocessing_location, + NULL_PARAM,// preprocessing_by, + NULL_PARAM,// preprocessing_steps, + NULL_PARAM,// data_collection_preprocessing_documentation, + NULL_PARAM,// documentation_uri, + NULL_PARAM,// validation_process_exists, + NULL_PARAM,// validation_process_description, + NULL_PARAM,// validation_conducted_by, + NULL_PARAM,// excluded_data, + NULL_PARAM,// excluded_data_reason, + 1,// page_no, + 1,//page_size + // options ?: AxiosRequestConfig + ); + + expect(datasetFiles.status).toBe(200); + datasetFiles.data.forEach(file => { + expect(file.metadata.dataset_detail!.name).toContain(name) + }); + }); + + it('Admin | Authenticated , When request made with collection_method, should return datasets matching collection_method', async () => { + let oswAPI = new CommonAPIsApi(adminConfiguration); + let collection_method = "manual"; + + const datasetFiles = await oswAPI.listDatasetFiles( + NULL_PARAM,// data_type, + "All",// status, + NULL_PARAM,// name, + NULL_PARAM,// version, + NULL_PARAM,// data_source, + collection_method,// collection_method, + NULL_PARAM,// collected_by, + NULL_PARAM,// derived_from_dataset_id, + NULL_PARAM,// collection_date, + NULL_PARAM,// confidence_level, + NULL_PARAM,// schema_version, + NULL_PARAM,// tdei_project_group_id, + NULL_PARAM,// service_id, + NULL_PARAM,// valid_from, + NULL_PARAM,// valid_to, + NULL_PARAM,// tdei_dataset_id, + NULL_PARAM,// bbox, + NULL_PARAM,// other_published_locations, + NULL_PARAM,// dataset_update_frequency_months, + NULL_PARAM,// schema_validation_run_description, + NULL_PARAM,// full_dataset_name, + NULL_PARAM,// collection_name, + NULL_PARAM,// department_name, + NULL_PARAM,// city, + NULL_PARAM,// region, + NULL_PARAM,// county, + NULL_PARAM,// key_limitations, + NULL_PARAM,// release notes, + NULL_PARAM,// challenges, + NULL_PARAM,// official_maintainer, + NULL_PARAM,// last_updated, + NULL_PARAM,// update_frequency, + NULL_PARAM,// authorization_chain, + NULL_PARAM,// maintenance_funded, + NULL_PARAM,// funding_details, + NULL_PARAM,// point_data_collection_device, + NULL_PARAM,// node_locations_and_attributes_editing_software, + NULL_PARAM,// data_collected_by_people, + NULL_PARAM,// data_collectors, + NULL_PARAM,// data_captured_automatically, + NULL_PARAM,// automated_collection, + NULL_PARAM,// data_collectors_organization, + NULL_PARAM,// data_collector_compensation, + NULL_PARAM,// preprocessing_location, + NULL_PARAM,// preprocessing_by, + NULL_PARAM,// preprocessing_steps, + NULL_PARAM,// data_collection_preprocessing_documentation, + NULL_PARAM,// documentation_uri, + NULL_PARAM,// validation_process_exists, + NULL_PARAM,// validation_process_description, + NULL_PARAM,// validation_conducted_by, + NULL_PARAM,// excluded_data, + NULL_PARAM,// excluded_data_reason, + 1,// page_no, + 1,//page_size + // options ?: AxiosRequestConfig + ); + + expect(datasetFiles.status).toBe(200); + datasetFiles.data.forEach(file => { + expect(file.metadata.dataset_detail!.collection_method).toBe(collection_method) + }); + }); + it('Admin | Authenticated , When request made with collected_by, should return datasets matching collected_by', async () => { + let oswAPI = new CommonAPIsApi(adminConfiguration); + let collected_by = "John Doe"; + + const datasetFiles = await oswAPI.listDatasetFiles( + NULL_PARAM,// data_type, + "All",// status, + NULL_PARAM,// name, + NULL_PARAM,// version, + NULL_PARAM,// data_source, + NULL_PARAM,// collection_method, + collected_by,// collected_by, + NULL_PARAM,// derived_from_dataset_id, + NULL_PARAM,// collection_date, + NULL_PARAM,// confidence_level, + NULL_PARAM,// schema_version, + NULL_PARAM,// tdei_project_group_id, + NULL_PARAM,// service_id, + NULL_PARAM,// valid_from, + NULL_PARAM,// valid_to, + NULL_PARAM,// tdei_dataset_id, + NULL_PARAM,// bbox, + NULL_PARAM,// other_published_locations, + NULL_PARAM,// dataset_update_frequency_months, + NULL_PARAM,// schema_validation_run_description, + NULL_PARAM,// full_dataset_name, + NULL_PARAM,// collection_name, + NULL_PARAM,// department_name, + NULL_PARAM,// city, + NULL_PARAM,// region, + NULL_PARAM,// county, + NULL_PARAM,// key_limitations, + NULL_PARAM,// release notes, + NULL_PARAM,// challenges, + NULL_PARAM,// official_maintainer, + NULL_PARAM,// last_updated, + NULL_PARAM,// update_frequency, + NULL_PARAM,// authorization_chain, + NULL_PARAM,// maintenance_funded, + NULL_PARAM,// funding_details, + NULL_PARAM,// point_data_collection_device, + NULL_PARAM,// node_locations_and_attributes_editing_software, + NULL_PARAM,// data_collected_by_people, + NULL_PARAM,// data_collectors, + NULL_PARAM,// data_captured_automatically, + NULL_PARAM,// automated_collection, + NULL_PARAM,// data_collectors_organization, + NULL_PARAM,// data_collector_compensation, + NULL_PARAM,// preprocessing_location, + NULL_PARAM,// preprocessing_by, + NULL_PARAM,// preprocessing_steps, + NULL_PARAM,// data_collection_preprocessing_documentation, + NULL_PARAM,// documentation_uri, + NULL_PARAM,// validation_process_exists, + NULL_PARAM,// validation_process_description, + NULL_PARAM,// validation_conducted_by, + NULL_PARAM,// excluded_data, + NULL_PARAM,// excluded_data_reason, + 1,// page_no, + 1,//page_size + // options ?: AxiosRequestConfig + ); + + expect(datasetFiles.status).toBe(200); + datasetFiles.data.forEach(file => { + expect(file.metadata.dataset_detail!.collected_by).toBe(collected_by) + }); + }); + it('Admin | Authenticated , When request made with data_source, should return datasets matching data_source', async () => { + let oswAPI = new CommonAPIsApi(adminConfiguration); + let data_source = "3rdParty"; + + const datasetFiles = await oswAPI.listDatasetFiles( + NULL_PARAM,// data_type, + "All",// status, + NULL_PARAM,// name, + NULL_PARAM,// version, + data_source,// data_source, + NULL_PARAM,// collection_method, + NULL_PARAM,// collected_by, + NULL_PARAM,// derived_from_dataset_id, + NULL_PARAM,// collection_date, + NULL_PARAM,// confidence_level, + NULL_PARAM,// schema_version, + NULL_PARAM,// tdei_project_group_id, + NULL_PARAM,// service_id, + NULL_PARAM,// valid_from, + NULL_PARAM,// valid_to, + NULL_PARAM,// tdei_dataset_id, + NULL_PARAM,// bbox, + NULL_PARAM,// other_published_locations, + NULL_PARAM,// dataset_update_frequency_months, + NULL_PARAM,// schema_validation_run_description, + NULL_PARAM,// full_dataset_name, + NULL_PARAM,// collection_name, + NULL_PARAM,// department_name, + NULL_PARAM,// city, + NULL_PARAM,// region, + NULL_PARAM,// county, + NULL_PARAM,// key_limitations, + NULL_PARAM,// release notes, + NULL_PARAM,// challenges, + NULL_PARAM,// official_maintainer, + NULL_PARAM,// last_updated, + NULL_PARAM,// update_frequency, + NULL_PARAM,// authorization_chain, + NULL_PARAM,// maintenance_funded, + NULL_PARAM,// funding_details, + NULL_PARAM,// point_data_collection_device, + NULL_PARAM,// node_locations_and_attributes_editing_software, + NULL_PARAM,// data_collected_by_people, + NULL_PARAM,// data_collectors, + NULL_PARAM,// data_captured_automatically, + NULL_PARAM,// automated_collection, + NULL_PARAM,// data_collectors_organization, + NULL_PARAM,// data_collector_compensation, + NULL_PARAM,// preprocessing_location, + NULL_PARAM,// preprocessing_by, + NULL_PARAM,// preprocessing_steps, + NULL_PARAM,// data_collection_preprocessing_documentation, + NULL_PARAM,// documentation_uri, + NULL_PARAM,// validation_process_exists, + NULL_PARAM,// validation_process_description, + NULL_PARAM,// validation_conducted_by, + NULL_PARAM,// excluded_data, + NULL_PARAM,// excluded_data_reason, + 1,// page_no, + 1,//page_size + // options ?: AxiosRequestConfig + ); + + expect(datasetFiles.status).toBe(200); + datasetFiles.data.forEach(file => { + expect(file.metadata.dataset_detail!.data_source).toBe(data_source) + }) + }); + + it('Admin | Authenticated , When request made with data_type OSW, should return datasets matching data_type', async () => { + let oswAPI = new CommonAPIsApi(adminConfiguration); + let data_type = "osw"; + + const datasetFiles = await oswAPI.listDatasetFiles( + data_type,// data_type, + "All",// status, + NULL_PARAM,// name, + NULL_PARAM,// version, + NULL_PARAM,// data_source, + NULL_PARAM,// collection_method, + NULL_PARAM,// collected_by, + NULL_PARAM,// derived_from_dataset_id, + NULL_PARAM,// collection_date, + NULL_PARAM,// confidence_level, + NULL_PARAM,// schema_version, + NULL_PARAM,// tdei_project_group_id, + NULL_PARAM,// service_id, + NULL_PARAM,// valid_from, + NULL_PARAM,// valid_to, + NULL_PARAM,// tdei_dataset_id, + NULL_PARAM,// bbox, + NULL_PARAM,// other_published_locations, + NULL_PARAM,// dataset_update_frequency_months, + NULL_PARAM,// schema_validation_run_description, + NULL_PARAM,// full_dataset_name, + NULL_PARAM,// collection_name, + NULL_PARAM,// department_name, + NULL_PARAM,// city, + NULL_PARAM,// region, + NULL_PARAM,// county, + NULL_PARAM,// key_limitations, + NULL_PARAM,// release notes, + NULL_PARAM,// challenges, + NULL_PARAM,// official_maintainer, + NULL_PARAM,// last_updated, + NULL_PARAM,// update_frequency, + NULL_PARAM,// authorization_chain, + NULL_PARAM,// maintenance_funded, + NULL_PARAM,// funding_details, + NULL_PARAM,// point_data_collection_device, + NULL_PARAM,// node_locations_and_attributes_editing_software, + NULL_PARAM,// data_collected_by_people, + NULL_PARAM,// data_collectors, + NULL_PARAM,// data_captured_automatically, + NULL_PARAM,// automated_collection, + NULL_PARAM,// data_collectors_organization, + NULL_PARAM,// data_collector_compensation, + NULL_PARAM,// preprocessing_location, + NULL_PARAM,// preprocessing_by, + NULL_PARAM,// preprocessing_steps, + NULL_PARAM,// data_collection_preprocessing_documentation, + NULL_PARAM,// documentation_uri, + NULL_PARAM,// validation_process_exists, + NULL_PARAM,// validation_process_description, + NULL_PARAM,// validation_conducted_by, + NULL_PARAM,// excluded_data, + NULL_PARAM,// excluded_data_reason, + 1,// page_no, + 1,//page_size + // options ?: AxiosRequestConfig + ); + + expect(datasetFiles.status).toBe(200); + datasetFiles.data.forEach((file: any) => { + expect(file.data_type).toBe(data_type) + }) + }); + + it('Admin | Authenticated , When request made with data_type Flex, should return datasets matching data_type', async () => { + let oswAPI = new CommonAPIsApi(adminConfiguration); + let data_type = "flex"; + + const datasetFiles = await oswAPI.listDatasetFiles( + data_type,// data_type, + "All",// status, + NULL_PARAM,// name, + NULL_PARAM,// version, + NULL_PARAM,// data_source, + NULL_PARAM,// collection_method, + NULL_PARAM,// collected_by, + NULL_PARAM,// derived_from_dataset_id, + NULL_PARAM,// collection_date, + NULL_PARAM,// confidence_level, + NULL_PARAM,// schema_version, + NULL_PARAM,// tdei_project_group_id, + NULL_PARAM,// service_id, + NULL_PARAM,// valid_from, + NULL_PARAM,// valid_to, + NULL_PARAM,// tdei_dataset_id, + NULL_PARAM,// bbox, + NULL_PARAM,// other_published_locations, + NULL_PARAM,// dataset_update_frequency_months, + NULL_PARAM,// schema_validation_run_description, + NULL_PARAM,// full_dataset_name, + NULL_PARAM,// collection_name, + NULL_PARAM,// department_name, + NULL_PARAM,// city, + NULL_PARAM,// region, + NULL_PARAM,// county, + NULL_PARAM,// key_limitations, + NULL_PARAM,// release notes, + NULL_PARAM,// challenges, + NULL_PARAM,// official_maintainer, + NULL_PARAM,// last_updated, + NULL_PARAM,// update_frequency, + NULL_PARAM,// authorization_chain, + NULL_PARAM,// maintenance_funded, + NULL_PARAM,// funding_details, + NULL_PARAM,// point_data_collection_device, + NULL_PARAM,// node_locations_and_attributes_editing_software, + NULL_PARAM,// data_collected_by_people, + NULL_PARAM,// data_collectors, + NULL_PARAM,// data_captured_automatically, + NULL_PARAM,// automated_collection, + NULL_PARAM,// data_collectors_organization, + NULL_PARAM,// data_collector_compensation, + NULL_PARAM,// preprocessing_location, + NULL_PARAM,// preprocessing_by, + NULL_PARAM,// preprocessing_steps, + NULL_PARAM,// data_collection_preprocessing_documentation, + NULL_PARAM,// documentation_uri, + NULL_PARAM,// validation_process_exists, + NULL_PARAM,// validation_process_description, + NULL_PARAM,// validation_conducted_by, + NULL_PARAM,// excluded_data, + NULL_PARAM,// excluded_data_reason, + 1,// page_no, + 1,//page_size + // options ?: AxiosRequestConfig + ); + + expect(datasetFiles.status).toBe(200); + datasetFiles.data.forEach((file: any) => { + expect(file.data_type).toBe(data_type) + }) + }); + + it('Admin | Authenticated , When request made with data_type Pathways, should return datasets matching data_type', async () => { + let oswAPI = new CommonAPIsApi(adminConfiguration); + let data_type = "pathways"; + + const datasetFiles = await oswAPI.listDatasetFiles( + data_type,// data_type, + "All",// status, + NULL_PARAM,// name, + NULL_PARAM,// version, + NULL_PARAM,// data_source, + NULL_PARAM,// collection_method, + NULL_PARAM,// collected_by, + NULL_PARAM,// derived_from_dataset_id, + NULL_PARAM,// collection_date, + NULL_PARAM,// confidence_level, + NULL_PARAM,// schema_version, + NULL_PARAM,// tdei_project_group_id, + NULL_PARAM,// service_id, + NULL_PARAM,// valid_from, + NULL_PARAM,// valid_to, + NULL_PARAM,// tdei_dataset_id, + NULL_PARAM,// bbox, + NULL_PARAM,// other_published_locations, + NULL_PARAM,// dataset_update_frequency_months, + NULL_PARAM,// schema_validation_run_description, + NULL_PARAM,// full_dataset_name, + NULL_PARAM,// collection_name, + NULL_PARAM,// department_name, + NULL_PARAM,// city, + NULL_PARAM,// region, + NULL_PARAM,// county, + NULL_PARAM,// key_limitations, + NULL_PARAM,// release notes, + NULL_PARAM,// challenges, + NULL_PARAM,// official_maintainer, + NULL_PARAM,// last_updated, + NULL_PARAM,// update_frequency, + NULL_PARAM,// authorization_chain, + NULL_PARAM,// maintenance_funded, + NULL_PARAM,// funding_details, + NULL_PARAM,// point_data_collection_device, + NULL_PARAM,// node_locations_and_attributes_editing_software, + NULL_PARAM,// data_collected_by_people, + NULL_PARAM,// data_collectors, + NULL_PARAM,// data_captured_automatically, + NULL_PARAM,// automated_collection, + NULL_PARAM,// data_collectors_organization, + NULL_PARAM,// data_collector_compensation, + NULL_PARAM,// preprocessing_location, + NULL_PARAM,// preprocessing_by, + NULL_PARAM,// preprocessing_steps, + NULL_PARAM,// data_collection_preprocessing_documentation, + NULL_PARAM,// documentation_uri, + NULL_PARAM,// validation_process_exists, + NULL_PARAM,// validation_process_description, + NULL_PARAM,// validation_conducted_by, + NULL_PARAM,// excluded_data, + NULL_PARAM,// excluded_data_reason, + 1,// page_no, + 1,//page_size + // options ?: AxiosRequestConfig + ); + + expect(datasetFiles.status).toBe(200); + datasetFiles.data.forEach((file: any) => { + expect(file.data_type).toBe(data_type) + }) + }); + + // it('Admin | Authenticated , When request made with derived_from_dataset_id, should return datasets matching derived_from_dataset_id', async () => { + // let oswAPI = new CommonAPIsApi(adminConfiguration); + // //let derived_from_dataset_id = "a042a1b3aa874701929cb33a98f28e9d"; + + // const datasetFiles = await oswAPI.listDatasetFiles( + // NULL_PARAM,// data_type, + // "All",// status, + // NULL_PARAM,// name, + // NULL_PARAM,// version, + // NULL_PARAM,// data_source, + // NULL_PARAM,// collection_method, + // NULL_PARAM,// collected_by, + // apiInput.osw.test_dataset,// derived_from_dataset_id, + // NULL_PARAM,// collection_date, + // NULL_PARAM,// confidence_level, + // NULL_PARAM,// schema_version, + // NULL_PARAM,// tdei_project_group_id, + // NULL_PARAM,// service_id, + // NULL_PARAM,// valid_from, + // NULL_PARAM,// valid_to, + // NULL_PARAM,// tdei_dataset_id, + // NULL_PARAM,// bbox, + // NULL_PARAM,// other_published_locations, + // NULL_PARAM,// dataset_update_frequency_months, + // NULL_PARAM,// schema_validation_run_description, + // NULL_PARAM,// full_dataset_name, + // NULL_PARAM,// collection_name, + // NULL_PARAM,// department_name, + // NULL_PARAM,// city, + // NULL_PARAM,// region, + // NULL_PARAM,// county, + // NULL_PARAM,// key_limitations, + // NULL_PARAM,// challenges, + // NULL_PARAM,// official_maintainer, + // NULL_PARAM,// last_updated, + // NULL_PARAM,// update_frequency, + // NULL_PARAM,// authorization_chain, + // NULL_PARAM,// maintenance_funded, + // NULL_PARAM,// funding_details, + // NULL_PARAM,// point_data_collection_device, + // NULL_PARAM,// node_locations_and_attributes_editing_software, + // NULL_PARAM,// data_collected_by_people, + // NULL_PARAM,// data_collectors, + // NULL_PARAM,// data_captured_automatically, + // NULL_PARAM,// automated_collection, + // NULL_PARAM,// data_collectors_organization, + // NULL_PARAM,// data_collector_compensation, + // NULL_PARAM,// preprocessing_location, + // NULL_PARAM,// preprocessing_by, + // NULL_PARAM,// preprocessing_steps, + // NULL_PARAM,// data_collection_preprocessing_documentation, + // NULL_PARAM,// documentation_uri, + // NULL_PARAM,// validation_process_exists, + // NULL_PARAM,// validation_process_description, + // NULL_PARAM,// validation_conducted_by, + // NULL_PARAM,// excluded_data, + // NULL_PARAM,// excluded_data_reason, + // 1,// page_no, + // 1,//page_size + // // options ?: AxiosRequestConfig + // ); + + // expect(datasetFiles.status).toBe(200); + // datasetFiles.data.forEach(file => { + // expect(file.derived_from_dataset_id).toBe(apiInput.osw.test_dataset) + // }) + // }); + + it('Admin | Authenticated , When request made with valid_to, should return datasets valid from input datetime', async () => { + let oswAPI = new CommonAPIsApi(adminConfiguration); + //set date one date before today + let valid_to = (new Date(new Date().setMonth(new Date().getMonth() - 1))).toISOString(); + + const datasetFiles = await oswAPI.listDatasetFiles( + NULL_PARAM,// data_type, + "All",// status, + NULL_PARAM,// name, + NULL_PARAM,// version, + NULL_PARAM,// data_source, + NULL_PARAM,// collection_method, + NULL_PARAM,// collected_by, + NULL_PARAM,// derived_from_dataset_id, + NULL_PARAM,// collection_date, + NULL_PARAM,// confidence_level, + NULL_PARAM,// schema_version, + NULL_PARAM,// tdei_project_group_id, + NULL_PARAM,// service_id, + NULL_PARAM,// valid_from, + valid_to,// valid_to, + NULL_PARAM,// tdei_dataset_id, + NULL_PARAM,// bbox, + NULL_PARAM,// other_published_locations, + NULL_PARAM,// dataset_update_frequency_months, + NULL_PARAM,// schema_validation_run_description, + NULL_PARAM,// full_dataset_name, + NULL_PARAM,// collection_name, + NULL_PARAM,// department_name, + NULL_PARAM,// city, + NULL_PARAM,// region, + NULL_PARAM,// county, + NULL_PARAM,// key_limitations, + NULL_PARAM,// release notes, + NULL_PARAM,// challenges, + NULL_PARAM,// official_maintainer, + NULL_PARAM,// last_updated, + NULL_PARAM,// update_frequency, + NULL_PARAM,// authorization_chain, + NULL_PARAM,// maintenance_funded, + NULL_PARAM,// funding_details, + NULL_PARAM,// point_data_collection_device, + NULL_PARAM,// node_locations_and_attributes_editing_software, + NULL_PARAM,// data_collected_by_people, + NULL_PARAM,// data_collectors, + NULL_PARAM,// data_captured_automatically, + NULL_PARAM,// automated_collection, + NULL_PARAM,// data_collectors_organization, + NULL_PARAM,// data_collector_compensation, + NULL_PARAM,// preprocessing_location, + NULL_PARAM,// preprocessing_by, + NULL_PARAM,// preprocessing_steps, + NULL_PARAM,// data_collection_preprocessing_documentation, + NULL_PARAM,// documentation_uri, + NULL_PARAM,// validation_process_exists, + NULL_PARAM,// validation_process_description, + NULL_PARAM,// validation_conducted_by, + NULL_PARAM,// excluded_data, + NULL_PARAM,// excluded_data_reason, + 1,// page_no, + 1,//page_size + // options ?: AxiosRequestConfig + ); + + expect(datasetFiles.status).toBe(200); + datasetFiles.data.forEach(file => { + expect(new Date(file.metadata.dataset_detail!.valid_to!)).toBeAfter(new Date(valid_to)) + }) + }); + + it('Admin | Authenticated , When request made with valid_from, should return datasets valid from input datetime', async () => { + let oswAPI = new CommonAPIsApi(adminConfiguration); + //set date one date before today + let valid_from = (new Date(new Date().setMonth(new Date().getMonth() - 1))).toISOString(); + + const datasetFiles = await oswAPI.listDatasetFiles( + NULL_PARAM,// data_type, + "All",// status, + NULL_PARAM,// name, + NULL_PARAM,// version, + NULL_PARAM,// data_source, + NULL_PARAM,// collection_method, + NULL_PARAM,// collected_by, + NULL_PARAM,// derived_from_dataset_id, + NULL_PARAM,// collection_date, + NULL_PARAM,// confidence_level, + NULL_PARAM,// schema_version, + NULL_PARAM,// tdei_project_group_id, + NULL_PARAM,// service_id, + valid_from,// valid_from, + NULL_PARAM,// valid_to, + NULL_PARAM,// tdei_dataset_id, + NULL_PARAM,// bbox, + NULL_PARAM,// other_published_locations, + NULL_PARAM,// dataset_update_frequency_months, + NULL_PARAM,// schema_validation_run_description, + NULL_PARAM,// full_dataset_name, + NULL_PARAM,// collection_name, + NULL_PARAM,// department_name, + NULL_PARAM,// city, + NULL_PARAM,// region, + NULL_PARAM,// county, + NULL_PARAM,// key_limitations, + NULL_PARAM,// release notes, + NULL_PARAM,// challenges, + NULL_PARAM,// official_maintainer, + NULL_PARAM,// last_updated, + NULL_PARAM,// update_frequency, + NULL_PARAM,// authorization_chain, + NULL_PARAM,// maintenance_funded, + NULL_PARAM,// funding_details, + NULL_PARAM,// point_data_collection_device, + NULL_PARAM,// node_locations_and_attributes_editing_software, + NULL_PARAM,// data_collected_by_people, + NULL_PARAM,// data_collectors, + NULL_PARAM,// data_captured_automatically, + NULL_PARAM,// automated_collection, + NULL_PARAM,// data_collectors_organization, + NULL_PARAM,// data_collector_compensation, + NULL_PARAM,// preprocessing_location, + NULL_PARAM,// preprocessing_by, + NULL_PARAM,// preprocessing_steps, + NULL_PARAM,// data_collection_preprocessing_documentation, + NULL_PARAM,// documentation_uri, + NULL_PARAM,// validation_process_exists, + NULL_PARAM,// validation_process_description, + NULL_PARAM,// validation_conducted_by, + NULL_PARAM,// excluded_data, + NULL_PARAM,// excluded_data_reason, + 1,// page_no, + 1,//page_size + // options ?: AxiosRequestConfig + ); + + expect(datasetFiles.status).toBe(200); + datasetFiles.data.forEach(file => { + expect(new Date(file.metadata.dataset_detail!.valid_from!)).toBeAfter(new Date(valid_from)) + }) + }); + + it('Admin | Authenticated , When request made with invalid tdei_dataset_id, should return empty dataset', async () => { + let oswAPI = new CommonAPIsApi(adminConfiguration); + let recordId = 'dummyRecordId'; + + const datasetFiles = await oswAPI.listDatasetFiles( + NULL_PARAM,// data_type, + "All",// status, + NULL_PARAM,// name, + NULL_PARAM,// version, + NULL_PARAM,// data_source, + NULL_PARAM,// collection_method, + NULL_PARAM,// collected_by, + NULL_PARAM,// derived_from_dataset_id, + NULL_PARAM,// collection_date, + NULL_PARAM,// confidence_level, + NULL_PARAM,// schema_version, + NULL_PARAM,// tdei_project_group_id, + NULL_PARAM,// service_id, + NULL_PARAM,// valid_from, + NULL_PARAM,// valid_to, + recordId,// tdei_dataset_id, + NULL_PARAM,// bbox, + NULL_PARAM,// other_published_locations, + NULL_PARAM,// dataset_update_frequency_months, + NULL_PARAM,// schema_validation_run_description, + NULL_PARAM,// full_dataset_name, + NULL_PARAM,// collection_name, + NULL_PARAM,// department_name, + NULL_PARAM,// city, + NULL_PARAM,// region, + NULL_PARAM,// county, + NULL_PARAM,// key_limitations, + NULL_PARAM,// release notes, + NULL_PARAM,// challenges, + NULL_PARAM,// official_maintainer, + NULL_PARAM,// last_updated, + NULL_PARAM,// update_frequency, + NULL_PARAM,// authorization_chain, + NULL_PARAM,// maintenance_funded, + NULL_PARAM,// funding_details, + NULL_PARAM,// point_data_collection_device, + NULL_PARAM,// node_locations_and_attributes_editing_software, + NULL_PARAM,// data_collected_by_people, + NULL_PARAM,// data_collectors, + NULL_PARAM,// data_captured_automatically, + NULL_PARAM,// automated_collection, + NULL_PARAM,// data_collectors_organization, + NULL_PARAM,// data_collector_compensation, + NULL_PARAM,// preprocessing_location, + NULL_PARAM,// preprocessing_by, + NULL_PARAM,// preprocessing_steps, + NULL_PARAM,// data_collection_preprocessing_documentation, + NULL_PARAM,// documentation_uri, + NULL_PARAM,// validation_process_exists, + NULL_PARAM,// validation_process_description, + NULL_PARAM,// validation_conducted_by, + NULL_PARAM,// excluded_data, + NULL_PARAM,// excluded_data_reason, + 1,// page_no, + 1,//page_size + // options ?: AxiosRequestConfig + ); + + expect(datasetFiles.status).toBe(200); + expect(datasetFiles.data.length).toBe(0); + + }); + + it('Admin | un-authenticated , When request made, should respond with unauthenticated request', async () => { + let oswAPI = new CommonAPIsApi(Utility.getAdminConfiguration()); + + const datasetFiles = oswAPI.listDatasetFiles(); + + await expect(datasetFiles).rejects.toMatchObject({ response: { status: 401 } }); + }); +}); + +describe("List API versions", () => { + + it('Admin | Authenticated , When request made, expect to return api version list', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(adminConfiguration); + // Action + const versions = await generalAPI.listApiVersions(); + + // Assert + expect(versions.status).toBe(200); + expect(versions.data.versions).not.toBeNull(); + + versions.data.versions?.forEach(version => { + expect(version).toMatchObject({ + version: expect.any(String), + documentation: expect.any(String), + specification: expect.any(String) + }); + }) + }, 30000); + + it('API-Key | Authenticated , When request made, expect to return api version list', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(apiKeyConfiguration); + // Action + const versions = await generalAPI.listApiVersions(); + + // Assert + expect(versions.status).toBe(200); + expect(versions.data.versions).not.toBeNull(); + + versions.data.versions?.forEach(version => { + expect(version).toMatchObject({ + version: expect.any(String), + documentation: expect.any(String), + specification: expect.any(String) + }); + }) + }, 30000) + + it('Admin | un-authenticated, When request made, should respond with unauthenticated request', async () => { + + let generalAPI = new CommonAPIsApi(Utility.getAdminConfiguration()); + + const version = generalAPI.listApiVersions(); + + await expect(version).rejects.toMatchObject({ response: { status: 401 } }); + + + }, 30000); +}); + +describe('List Project Groups', () => { + + it('Admin | Authenticated , When request made, expect to return list of project groups', async () => { + let generalAPI = new CommonAPIsApi(adminConfiguration); + + const projectGroupList = await generalAPI.listProjectGroups(); + + expect(projectGroupList.status).toBe(200); + expect(Array.isArray(projectGroupList.data)).toBe(true); + + projectGroupList.data.forEach(data => { + expect(data).toMatchObject({ + tdei_project_group_id: expect.any(String), + project_group_name: expect.any(String), + polygon: expect.any(Object || null) + }) + }) + }, 30000); + + + it('POC | Authenticated , When request made, expect to return list of project groups', async () => { + let generalAPI = new CommonAPIsApi(pocConfiguration); + + const projectGroupList = await generalAPI.listProjectGroups(); + + expect(projectGroupList.status).toBe(200); + expect(Array.isArray(projectGroupList.data)).toBe(true); + + projectGroupList.data.forEach(data => { + expect(data).toMatchObject({ + tdei_project_group_id: expect.any(String), + project_group_name: expect.any(String), + polygon: expect.any(Object || null) + }) + }) + }, 30000); + + it('API-Key | Authenticated , When request made, expect to return list of project groups', async () => { + let generalAPI = new CommonAPIsApi(apiKeyConfiguration); + + const projectGroupList = await generalAPI.listProjectGroups(); + + expect(projectGroupList.status).toBe(200); + expect(Array.isArray(projectGroupList.data)).toBe(true); + + projectGroupList.data.forEach(data => { + expect(data).toMatchObject({ + tdei_project_group_id: expect.any(String), + project_group_name: expect.any(String), + polygon: expect.any(Object || null) + }) + }) + }, 30000); + + it('POC | Authenticated , When requested with invalid tdei_project_group_id, expect to return tdei_project_group_id not found', async () => { + let generalAPI = new CommonAPIsApi(pocConfiguration); + const projectGroupList = generalAPI.listProjectGroups('D552d5d1-0719-4647-b86d-6ae9b25327b7'); + + await expect(projectGroupList).rejects.toMatchObject({ response: { status: 404 } }); + }, 30000); + + it('POC | Authenticated , When requested with specific tdei_project_group_id, expect to return project details identified by tdei_project_group_id', async () => { + let generalAPI = new CommonAPIsApi(pocConfiguration); + const projectGroupList = await generalAPI.listProjectGroups(tdei_project_group_id); + + expect(projectGroupList.status).toBe(200); + expect(Array.isArray(projectGroupList.data)).toBe(true); + + projectGroupList.data.forEach(data => { + expect(data).toMatchObject({ + tdei_project_group_id: expect.toInclude(tdei_project_group_id), + project_group_name: expect.any(String), + polygon: expect.any(Object || null) + }); + }); + }, 30000); + + it('POC | Authenticated , When requested with specific service name, expect to return project details name matching input', async () => { + let generalAPI = new CommonAPIsApi(pocConfiguration); + let project_name = ""; + const projectGroupList = await generalAPI.listProjectGroups(NULL_PARAM, project_name); + + expect(projectGroupList.status).toBe(200); + expect(Array.isArray(projectGroupList.data)).toBe(true); + + projectGroupList.data.forEach(data => { + expect(data).toMatchObject({ + project_group_name: expect.toInclude(project_name) + }); + }); + }, 30000); + + it('Admin | un-authenticated , When request made, should respond with unauthenticated request', async () => { + let generalAPI = new CommonAPIsApi(Utility.getAdminConfiguration()); + + const projectGroupList = generalAPI.listProjectGroups(); + + await expect(projectGroupList).rejects.toMatchObject({ response: { status: 401 } }); + + }, 30000) +}); + +describe('Clone Dataset', () => { + //Clone flex dataset + it('POC | Authenticated , When request made to clone flex dataset, expect to return cloned dataset id', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(pocConfiguration); + let metaToUpload = Utility.getMetadataBlob("flex"); + let tdei_dataset_id = apiInput.flex.published_dataset; //"ecf96dce3d36477b8ba53c6833ca4545"; //Published flex dataset + + // Action + const cloneDatasetInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => cloneDatasetRequestInterceptor(req, tdei_dataset_id, tdei_project_group_id, tdei_service_id_flex, 'metadata.json')) + const versions = await generalAPI.cloneDatasetForm(metaToUpload, tdei_dataset_id, tdei_project_group_id, tdei_service_id_flex); + // Assert + expect(versions.status).toBe(200); + expect(versions.data).toBeString(); + expect(versions.data).not.toBe(''); + axios.interceptors.request.eject(cloneDatasetInterceptor); + }, 30000); + + it('Admin | Authenticated , When request made to clone flex dataset, expect to return cloned dataset id', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(adminConfiguration); + let metaToUpload = Utility.getMetadataBlob("flex"); + let tdei_dataset_id = apiInput.flex.published_dataset;//"ecf96dce3d36477b8ba53c6833ca4545";//Published flex dataset + + // Action + const editMetaInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => cloneDatasetRequestInterceptor(req, tdei_dataset_id, tdei_project_group_id, tdei_service_id_flex, 'metadata.json')) + const versions = await generalAPI.cloneDatasetForm(metaToUpload, tdei_dataset_id, tdei_project_group_id, tdei_service_id_flex); + // Assert + expect(versions.status).toBe(200); + expect(versions.data).toBeString(); + expect(versions.data).not.toBe(''); + axios.interceptors.request.eject(editMetaInterceptor); + }, 30000); + + it('Flex Data Generator | Authenticated , When request made to clone flex dataset, expect to return cloned dataset id', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(flexDgConfiguration); + let metaToUpload = Utility.getMetadataBlob("flex"); + let tdei_dataset_id = apiInput.flex.published_dataset;//"ecf96dce3d36477b8ba53c6833ca4545";//Published flex dataset + + // Action + const editMetaInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => cloneDatasetRequestInterceptor(req, tdei_dataset_id, tdei_project_group_id, tdei_service_id_flex, 'metadata.json')) + const versions = await generalAPI.cloneDatasetForm(metaToUpload, tdei_dataset_id, tdei_project_group_id, tdei_service_id_flex); + // Assert + expect(versions.status).toBe(200); + expect(versions.data).toBeString(); + expect(versions.data).not.toBe(''); + axios.interceptors.request.eject(editMetaInterceptor); + }, 30000); + + //Clone Pathways dataset + it('POC | Authenticated , When request made to clone pathways dataset, expect to return cloned dataset id', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(pocConfiguration); + let metaToUpload = Utility.getMetadataBlob("pathways"); + let tdei_dataset_id = apiInput.pathways.published_dataset;//"1fa972ecdd034ed6807dc5027dd26da2";//Published Pathways dataset + + // Action + const editMetaInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => cloneDatasetRequestInterceptor(req, tdei_dataset_id, tdei_project_group_id, tdei_service_id_pathways, 'metadata.json')) + const versions = await generalAPI.cloneDatasetForm(metaToUpload, tdei_dataset_id, tdei_project_group_id, tdei_service_id_pathways); + // Assert + expect(versions.status).toBe(200); + expect(versions.data).toBeString(); + expect(versions.data).not.toBe(''); + axios.interceptors.request.eject(editMetaInterceptor); + }, 30000); + + it('Admin | Authenticated , When request made to clone pathways dataset, expect to return cloned dataset id', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(adminConfiguration); + let metaToUpload = Utility.getMetadataBlob("pathways"); + let tdei_dataset_id = apiInput.pathways.published_dataset;//"1fa972ecdd034ed6807dc5027dd26da2";//Published Pathways dataset + + // Action + const editMetaInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => cloneDatasetRequestInterceptor(req, tdei_dataset_id, tdei_project_group_id, tdei_service_id_pathways, 'metadata.json')) + const versions = await generalAPI.cloneDatasetForm(metaToUpload, tdei_dataset_id, tdei_project_group_id, tdei_service_id_pathways); + // Assert + expect(versions.status).toBe(200); + expect(versions.data).toBeString(); + expect(versions.data).not.toBe(''); + axios.interceptors.request.eject(editMetaInterceptor); + }, 30000); + + it('Pathways Data Generator | Authenticated , When request made to clone pathways dataset, expect to return cloned dataset id', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(pathwaysDgConfiguration); + let metaToUpload = Utility.getMetadataBlob("pathways"); + let tdei_dataset_id = apiInput.pathways.published_dataset;//"1fa972ecdd034ed6807dc5027dd26da2";//Published Pathways dataset + + // Action + const editMetaInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => cloneDatasetRequestInterceptor(req, tdei_dataset_id, tdei_project_group_id, tdei_service_id_pathways, 'metadata.json')) + const versions = await generalAPI.cloneDatasetForm(metaToUpload, tdei_dataset_id, tdei_project_group_id, tdei_service_id_pathways); + // Assert + expect(versions.status).toBe(200); + expect(versions.data).toBeString(); + expect(versions.data).not.toBe(''); + axios.interceptors.request.eject(editMetaInterceptor); + }, 30000); + + //Clone osw dataset + it('POC | Authenticated , When request made to clone OSW dataset, expect to return cloned dataset id', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(pocConfiguration); + let metaToUpload = Utility.getMetadataBlob("osw"); + let tdei_dataset_id = apiInput.osw.published_dataset;//"d4dc9901f4794f2da414dcb96412b7c1";//Published OSW dataset` + + // Action + const editMetaInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => cloneDatasetRequestInterceptor(req, tdei_dataset_id, tdei_project_group_id, tdei_service_id_osw, 'metadata.json')) + const versions = await generalAPI.cloneDatasetForm(metaToUpload, tdei_dataset_id, tdei_project_group_id, tdei_service_id_osw); + // Assert + expect(versions.status).toBe(200); + expect(versions.data).toBeString(); + expect(versions.data).not.toBe(''); + axios.interceptors.request.eject(editMetaInterceptor); + }, 30000); + + it('Admin | Authenticated , When request made to clone OSW dataset, expect to return cloned dataset id', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(adminConfiguration); + let metaToUpload = Utility.getMetadataBlob("osw"); + let tdei_dataset_id = apiInput.osw.published_dataset;//"d4dc9901f4794f2da414dcb96412b7c1";//Published OSW dataset + + // Action + const editMetaInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => cloneDatasetRequestInterceptor(req, tdei_dataset_id, tdei_project_group_id, tdei_service_id_osw, 'metadata.json')) + const versions = await generalAPI.cloneDatasetForm(metaToUpload, tdei_dataset_id, tdei_project_group_id, tdei_service_id_osw); + // Assert + expect(versions.status).toBe(200); + expect(versions.data).toBeString(); + expect(versions.data).not.toBe(''); + axios.interceptors.request.eject(editMetaInterceptor); + }, 30000); + + it('OSW Data Generator | Authenticated , When request made to clone OSW dataset, expect to return cloned dataset id', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(oswDgConfiguration); + let metaToUpload = Utility.getMetadataBlob("osw"); + let tdei_dataset_id = apiInput.osw.published_dataset;//"d4dc9901f4794f2da414dcb96412b7c1";//Published OSW dataset + + // Action + const editMetaInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => cloneDatasetRequestInterceptor(req, tdei_dataset_id, tdei_project_group_id, tdei_service_id_osw, 'metadata.json')) + const versions = await generalAPI.cloneDatasetForm(metaToUpload, tdei_dataset_id, tdei_project_group_id, tdei_service_id_osw); + // Assert + expect(versions.status).toBe(200); + expect(versions.data).toBeString(); + expect(versions.data).not.toBe(''); + axios.interceptors.request.eject(editMetaInterceptor); + }, 30000); + + it('POC | Authenticated , When request made to clone Pre-Release flex dataset which user not belong to project group, expect to return unauthorized error', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(pocConfiguration); + let metaToUpload = Utility.getMetadataBlob("flex"); + let tdei_dataset_id = apiInput.flex.pre_release_dataset;//"f2574fe66f0046389acc68ee5848e3a9";//Pre-Release dataset + + // Action + const editMetaInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => cloneDatasetRequestInterceptor(req, tdei_dataset_id, tdei_project_group_id, tdei_service_id_flex, 'metadata.json')) + // Assert + await expect(generalAPI.cloneDatasetForm(metaToUpload, tdei_dataset_id, tdei_project_group_id, tdei_service_id_flex)).rejects.toMatchObject({ response: { status: 400 } }); + axios.interceptors.request.eject(editMetaInterceptor); + }, 30000); + + it('POC | Authenticated , When request made to clone flex dataset with invalid service type, expect to return input error', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(pocConfiguration); + let metaToUpload = Utility.getMetadataBlob("flex"); + let tdei_dataset_id = apiInput.flex.pre_release_dataset;//"f2574fe66f0046389acc68ee5848e3a9";//Pre-Release dataset + + // Action + const editMetaInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => cloneDatasetRequestInterceptor(req, tdei_dataset_id, tdei_project_group_id, tdei_service_id_osw, 'metadata.json')) + // Assert + await expect(generalAPI.cloneDatasetForm(metaToUpload, tdei_dataset_id, tdei_project_group_id, tdei_service_id_osw)).rejects.toMatchObject({ response: { status: 400 } }); + axios.interceptors.request.eject(editMetaInterceptor); + }, 30000); + + it('POC | Authenticated , When request made to clone flex dataset with invalid service id, expect to return not found error', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(pocConfiguration); + let metaToUpload = Utility.getMetadataBlob("flex"); + let tdei_dataset_id = apiInput.flex.pre_release_dataset;//"f2574fe66f0046389acc68ee5848e3a9";//Pre-Release dataset + + // Action + const editMetaInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => cloneDatasetRequestInterceptor(req, tdei_dataset_id, tdei_project_group_id, "invalid_service_id", 'metadata.json')) + // Assert + await expect(generalAPI.cloneDatasetForm(metaToUpload, tdei_dataset_id, tdei_project_group_id, "invalid_service_id")).rejects.toMatchObject({ response: { status: 404 } }); + axios.interceptors.request.eject(editMetaInterceptor); + }, 30000); + + it('POC | Authenticated , When request made to clone flex dataset with invalid project group id, expect to return unauthorized error', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(pocConfiguration); + let metaToUpload = Utility.getMetadataBlob("flex"); + let tdei_dataset_id = apiInput.flex.pre_release_dataset;//"f2574fe66f0046389acc68ee5848e3a9";//Pre-Release dataset + + // Action + const editMetaInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => cloneDatasetRequestInterceptor(req, tdei_dataset_id, "invalid_project_id", tdei_service_id_flex, 'metadata.json')) + // Assert + await expect(generalAPI.cloneDatasetForm(metaToUpload, tdei_dataset_id, "invalid_project_id", tdei_service_id_flex)).rejects.toMatchObject({ response: { status: 404 } }); + axios.interceptors.request.eject(editMetaInterceptor); + }, 30000);`` + + it('POC | Authenticated , When request made to clone flex dataset with service id not associated with project group id, expect to return input error', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(pocConfiguration); + let metaToUpload = Utility.getMetadataBlob("flex"); + let tdei_dataset_id = apiInput.flex.pre_release_dataset;//"0b165272-afff-46b9-8eb4-14f81bfb92b7";//Pre-Release other project group dataset + + // Action + const editMetaInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => cloneDatasetRequestInterceptor(req, tdei_dataset_id, tdei_project_group_id, tdei_service_id_flex, 'metadata.json')) + // Assert + await expect(generalAPI.cloneDatasetForm(metaToUpload, tdei_dataset_id, tdei_project_group_id, tdei_service_id_flex)).rejects.toMatchObject({ response: { status: 400 } }); + axios.interceptors.request.eject(editMetaInterceptor); + }, 30000); + + it('POC | Authenticated , When request made to clone flex dataset with invalid metadata, expect to return input error', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(pocConfiguration); + let metaToUpload = Utility.getInvalidMetadataBlob("flex"); + let tdei_dataset_id = apiInput.flex.pre_release_dataset;//"f2574fe66f0046389acc68ee5848e3a9";//Pre-Release dataset + + // Action + const editMetaInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => cloneDatasetRequestInterceptor(req, tdei_dataset_id, tdei_project_group_id, tdei_service_id_flex, 'metadata.json')) + // Assert + await expect(generalAPI.cloneDatasetForm(metaToUpload, tdei_dataset_id, tdei_project_group_id, tdei_service_id_flex)).rejects.toMatchObject({ response: { status: 400 } }); + axios.interceptors.request.eject(editMetaInterceptor); + }, 30000); + + it('Admin | un-authenticated, When request made, should respond with unauthenticated request', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(Utility.getAdminConfiguration()); + let metaToUpload = Utility.getMetadataBlob("flex"); + let tdei_dataset_id = apiInput.flex.pre_release_dataset; + + // Action + const cloneMetaInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => cloneDatasetRequestInterceptor(req, tdei_dataset_id, tdei_project_group_id, tdei_service_id_osw, 'metadata.json')) + // Assert + await expect(generalAPI.cloneDatasetForm(metaToUpload, tdei_dataset_id, tdei_project_group_id, tdei_service_id_osw)).rejects.toMatchObject({ response: { status: 401 } }); + axios.interceptors.request.eject(cloneMetaInterceptor); + }, 30000); +}); + +describe('List Services', () => { + + it('Admin | Authenticated , When request made, expect to return list of services', async () => { + let generalAPI = new CommonAPIsApi(adminConfiguration); + + const serviceList = await generalAPI.listServices(); + + expect(serviceList.status).toBe(200); + expect(Array.isArray(serviceList.data)).toBe(true); + + serviceList.data.forEach(data => { + expect(data).toMatchObject({ + tdei_service_id: expect.toBeNullOrString(), + service_name: expect.toBeNullOrString(), + polygon: expect.any(Object || null), + service_type: expect.toBeNullOrString() + }); + }); + }, 30000); + + + it('POC | Authenticated , When request made, expect to return list of services', async () => { + let generalAPI = new CommonAPIsApi(pocConfiguration); + + const serviceList = await generalAPI.listServices(); + + expect(serviceList.status).toBe(200); + expect(Array.isArray(serviceList.data)).toBe(true); + + serviceList.data.forEach(data => { + expect(data).toMatchObject({ + tdei_service_id: expect.toBeNullOrString(), + service_name: expect.toBeNullOrString(), + polygon: expect.any(Object || null), + service_type: expect.toBeNullOrString() + }); + }); + }, 30000); + + it('API-Key | Authenticated , When request made, expect to return list of services', async () => { + let generalAPI = new CommonAPIsApi(apiKeyConfiguration); + + const serviceList = await generalAPI.listServices(); + + expect(serviceList.status).toBe(200); + expect(Array.isArray(serviceList.data)).toBe(true); + + serviceList.data.forEach(data => { + expect(data).toMatchObject({ + tdei_service_id: expect.toBeNullOrString(), + service_name: expect.toBeNullOrString(), + polygon: expect.any(Object || null), + service_type: expect.toBeNullOrString() + }); + }); + }, 30000); + + it('POC | Authenticated , When requested with invalid tdei_project_group_id, expect to return tdei_project_group_id not found', async () => { + let generalAPI = new CommonAPIsApi(pocConfiguration); + const serviceList = generalAPI.listServices(NULL_PARAM, NULL_PARAM, 'D552d5d1-0719-4647-b86d-6ae9b25327b7'); + + await expect(serviceList).rejects.toMatchObject({ response: { status: 404 } }); + }, 30000); + + it('POC | Authenticated , When requested with invalid tdei_service_id, expect to return tdei_service_id not found', async () => { + let generalAPI = new CommonAPIsApi(pocConfiguration); + const serviceList = generalAPI.listServices('D552d5d1-0719-4647-b86d-6ae9b25327b7'); + + await expect(serviceList).rejects.toMatchObject({ response: { status: 404 } }); + }, 30000); + + it('POC | Authenticated , When requested with invalid service type, expect to return invalid service type input error', async () => { + let generalAPI = new CommonAPIsApi(pocConfiguration); + const serviceList = generalAPI.listServices(NULL_PARAM, NULL_PARAM, NULL_PARAM, 'invalidServiceType'); + + await expect(serviceList).rejects.toMatchObject({ response: { status: 400 } }); + }, 30000); + + it('POC | Authenticated , When requested with specific tdei_service_id, expect to return service details identified by tdei_service_id', async () => { + let generalAPI = new CommonAPIsApi(pocConfiguration); + const serviceList = await generalAPI.listServices(tdei_service_id_osw); + + expect(serviceList.status).toBe(200); + expect(Array.isArray(serviceList.data)).toBe(true); + + serviceList.data.forEach(data => { + expect(data).toMatchObject({ + tdei_service_id: expect.toInclude(tdei_service_id_osw), + service_name: expect.toBeNullOrString(), + polygon: expect.any(Object || null), + service_type: expect.toBeNullOrString(), + tdei_project_group_id: expect.toBeNullOrString(), + }); }); + }, 30000); - beforeAll( async ()=>{ - // console.log('Hello there'); - let generalAPI = new GeneralApi(configuration); - const loginResponse = await generalAPI.authenticate({username:configuration.username,password:configuration.password}); - configuration.baseOptions = { - headers:{ - 'Authorization':'Bearer '+ loginResponse.data.access_token - } - }; + it('POC | Authenticated , When requested with specific tdei_project_group_id, expect to return service details identified by tdei_project_group_id', async () => { + let generalAPI = new CommonAPIsApi(pocConfiguration); + const serviceList = await generalAPI.listServices(NULL_PARAM, NULL_PARAM, tdei_project_group_id); + + expect(serviceList.status).toBe(200); + expect(Array.isArray(serviceList.data)).toBe(true); + serviceList.data.forEach(data => { + expect(data).toMatchObject({ + tdei_service_id: expect.toBeNullOrString(), + tdei_project_group_id: expect.toInclude(tdei_project_group_id), + service_name: expect.toBeNullOrString(), + polygon: expect.any(Object || null), + service_type: expect.toBeNullOrString() + }); }); + }, 30000); + + it('POC | Authenticated , When requested with specific service name, expect to return service details name matching input', async () => { + let generalAPI = new CommonAPIsApi(pocConfiguration); + let service_name = ""; + const serviceList = await generalAPI.listServices(NULL_PARAM, service_name); - it('Should be able to login',async ()=> { - - let generalAPI = new GeneralApi(configuration); - const loginResponse = await generalAPI.authenticate({username:configuration.username,password:configuration.password}); - expect(loginResponse.data.access_token).not.toBe(''); + expect(serviceList.status).toBe(200); + expect(Array.isArray(serviceList.data)).toBe(true); + + serviceList.data.forEach(data => { + expect(data).toMatchObject({ + tdei_service_id: expect.toBeNullOrString(), + service_name: expect.toInclude(service_name), + polygon: expect.any(Object || null), + service_type: expect.toBeNullOrString(), + tdei_project_group_id: expect.toBeNullOrString(), + }); }); + }, 30000); + + it('Admin | un-authenticated , When request made, should respond with unauthenticated request', async () => { + let generalAPI = new CommonAPIsApi(Utility.getAdminConfiguration()); + + const serviceList = generalAPI.listProjectGroups(); + + await expect(serviceList).rejects.toMatchObject({ response: { status: 401 } }); + + }, 30000); +}); + +describe('Authentication', () => { + + it('When request made with valid credentials, expect to return access_token & refresh_token in response', async () => { + let authApi = new AuthenticationApi(adminConfiguration); + + const response = await authApi.authenticate({ username: adminConfiguration.username, password: adminConfiguration.password }); + + expect(response.status).toBe(200); + + expect(response.data).toMatchObject({ + access_token: expect.any(String), + refresh_token: expect.any(String) + }); + }, 30000); + + it('When request made with invalid user, should respond with user not found error', async () => { + let authApi = new AuthenticationApi(undefined, adminConfiguration.basePath); + + const response = authApi.authenticate({ username: 'invalid', password: 'Invalid01*' }); + + await expect(response).rejects.toMatchObject({ response: { status: 404 } }); + + }, 30000); + + it('When request made with invalid creds, should respond with unauthenticated request', async () => { + let authApi = new AuthenticationApi(undefined, adminConfiguration.basePath); + + const response = authApi.authenticate({ username: 'admin@tdei.com', password: 'Invalid01*' }); + + await expect(response).rejects.toMatchObject({ response: { status: 401 } }); + + }, 30000); + + it('When request made with invalid password policy, should respond with bad request', async () => { + let authApi = new AuthenticationApi(undefined, adminConfiguration.basePath); + + const response = authApi.authenticate({ username: 'admin@tdei.com', password: 'Invalid' }); + + await expect(response).rejects.toMatchObject({ response: { status: 400 } }); + + }, 30000); + + // it('When request made with long password > 255, should respond with bad request', async () => { + // let authApi = new AuthenticationApi(undefined, adminConfiguration.basePath); + + // const response = authApi.authenticate({ + // username: 'admin@tdei.com', password: `ABCDEFG*IJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567HIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678CDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789` + // }); + + // await expect(response).rejects.toMatchObject({ response: { status: 400 } }); + + // }, 30000); +}); + +describe('Refresh token', () => { + + it('When request made with valid refresh token, expect to return fresh access_token & refresh_token in response', async () => { + let authApi = new AuthenticationApi(adminConfiguration); + + const response = await authApi.authenticate({ username: adminConfiguration.username, password: adminConfiguration.password }); + + expect(response.status).toBe(200); + + expect(response.data).toMatchObject({ + access_token: expect.any(String), + refresh_token: expect.any(String) + }); + + let requestResponse = await authApi.refreshToken(response.data.refresh_token!); + expect(requestResponse.status).toBe(200); + + expect(requestResponse.data).toMatchObject({ + access_token: expect.any(String), + refresh_token: expect.any(String) + }); + + + }, 30000); + + it('When request made with invalid refresh_token, should respond with unauthenticated request', async () => { + let authApi = new AuthenticationApi(adminConfiguration); + + const response = authApi.refreshToken("invalid"); + + await expect(response).rejects.toMatchObject({ response: { status: 401 } }); + + }, 30000); +}); + +describe('Recover password', () => { + + it('Admin | Authenticated, When request made with valid email, expect to return success response', async () => { + let authApi = new AuthenticationApi(Utility.getAdminConfiguration()); + + let requestResponse = await authApi.recoverPassword(pocConfiguration.username!); + expect(requestResponse.status).toBe(200); + + }, 30000); + + it('When request made with invalid username, should respond with user not found error', async () => { + let authApi = new AuthenticationApi(Utility.getAdminConfiguration()); + + const response = authApi.recoverPassword("invalid"); + + await expect(response).rejects.toMatchObject({ response: { status: 400 } }); + + }, 30000); +}); + +describe('Verify Email', () => { + + it('When request made with valid email, expect to return success response', async () => { + let authApi = new AuthenticationApi(Utility.getAdminConfiguration()); + + let requestResponse = await authApi.verifyEmail(pocConfiguration.username!); + expect(requestResponse.status).toBe(200); + + }, 30000); + + it('When request made with invalid username, should respond with user not found error', async () => { + let authApi = new AuthenticationApi(Utility.getAdminConfiguration()); + + const response = authApi.verifyEmail("invalid"); + + await expect(response).rejects.toMatchObject({ response: { status: 400 } }); + + }, 30000); + +}); + +describe('System metrics', () => { + + it('Admin | Authenticated, When request made, expect to return success response', async () => { + let metricsApi = new MetricsApi(adminConfiguration); + + let requestResponse = await metricsApi.systemMetrics(); + expect(requestResponse.status).toBe(200); + + }, 30000); + + it('POC | Authenticated, When request made, expect to return success response', async () => { + let metricsApi = new MetricsApi(pocConfiguration); + + let requestResponse = await metricsApi.systemMetrics(); + expect(requestResponse.status).toBe(200); + + }, 30000); + + it('API-Key | Authenticated, When request made, expect to return success response', async () => { + let metricsApi = new MetricsApi(apiKeyConfiguration); + + let requestResponse = await metricsApi.systemMetrics(); + expect(requestResponse.status).toBe(200); + + }, 30000); + + it('Admin | un-authenticated, When request made, should respond with unauthenticated request', async () => { + let metricsApi = new MetricsApi(Utility.getAdminConfiguration()); + + const response = metricsApi.systemMetrics(); + + await expect(response).rejects.toMatchObject({ response: { status: 401 } }); + + }, 30000); +}); + +describe('Data metrics', () => { + + it('Admin | Authenticated, When request made, expect to return success response', async () => { + let metricsApi = new MetricsApi(adminConfiguration); + + let requestResponse = await metricsApi.dataMetrics(); + expect(requestResponse.status).toBe(200); + + }, 30000); + + it('POC | Authenticated, When request made, expect to return success response', async () => { + let metricsApi = new MetricsApi(pocConfiguration); + + let requestResponse = await metricsApi.dataMetrics(); + expect(requestResponse.status).toBe(200); + + }, 30000); + + it('API-Key | Authenticated, When request made, expect to return success response', async () => { + let metricsApi = new MetricsApi(apiKeyConfiguration); + + let requestResponse = await metricsApi.dataMetrics(); + expect(requestResponse.status).toBe(200); + + }, 30000); + + it('Admin | un-authenticated, When request made, should respond with unauthenticated request', async () => { + let metricsApi = new MetricsApi(Utility.getAdminConfiguration()); + + const response = metricsApi.dataMetrics(); + + await expect(response).rejects.toMatchObject({ response: { status: 401 } }); + + }, 30000); +}); + +describe('Service metrics', () => { + + it('Admin | Authenticated, When request made, expect to return success response', async () => { + let metricsApi = new MetricsApi(adminConfiguration); + + let requestResponse = await metricsApi.serviceMetrics(tdei_project_group_id); + expect(requestResponse.status).toBe(200); + + }, 30000); + + it('POC | Authenticated, When request made, expect to return success response', async () => { + let metricsApi = new MetricsApi(pocConfiguration); + + let requestResponse = await metricsApi.serviceMetrics(tdei_project_group_id); + expect(requestResponse.status).toBe(200); + + }, 30000); + + it('API-Key | Authenticated, When request made, expect to return success response', async () => { + let metricsApi = new MetricsApi(apiKeyConfiguration); + + let requestResponse = await metricsApi.serviceMetrics(tdei_project_group_id); + expect(requestResponse.status).toBe(200); + + }, 30000); + + it('Admin | un-authenticated, When request made, should respond with unauthenticated request', async () => { + let metricsApi = new MetricsApi(Utility.getAdminConfiguration()); + + const response = metricsApi.serviceMetrics(tdei_project_group_id); + await expect(response).rejects.toMatchObject({ response: { status: 401 } }); + + }, 30000); + + it('Admin | Authenticated, When request made, expect to return bad request response', async () => { + let metricsApi = new MetricsApi(adminConfiguration); + + const response = metricsApi.serviceMetrics('invalid project group id'); + await expect(response).rejects.toMatchObject({ response: { status: 400 } }); + + }, 30000); + + it('POC | Authenticated, When request made, expect to return bad request response', async () => { + let metricsApi = new MetricsApi(pocConfiguration); + + const response = metricsApi.serviceMetrics('invalid project group id'); + await expect(response).rejects.toMatchObject({ response: { status: 400 } }); + + }, 30000); + + it('API-Key | Authenticated, When request made, expect to return bad request response', async () => { + let metricsApi = new MetricsApi(apiKeyConfiguration); + + const response = metricsApi.serviceMetrics('invalid project group id'); + await expect(response).rejects.toMatchObject({ response: { status: 400 } }); + + }, 30000); + + it('Admin | Authenticated, When request made, expect to return not found response', async () => { + let metricsApi = new MetricsApi(adminConfiguration); + + const response = metricsApi.serviceMetrics('9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d'); + await expect(response).rejects.toMatchObject({ response: { status: 404 } }); + + }, 30000); + + it('POC | Authenticated, When request made, expect to return not found response', async () => { + let metricsApi = new MetricsApi(pocConfiguration); + + const response = metricsApi.serviceMetrics('9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d'); + await expect(response).rejects.toMatchObject({ response: { status: 404 } }); + + }, 30000); + + it('API-Key | Authenticated, When request made, expect to return not found response', async () => { + let metricsApi = new MetricsApi(apiKeyConfiguration); + + const response = metricsApi.serviceMetrics('9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d'); + await expect(response).rejects.toMatchObject({ response: { status: 404 } }); + + }, 30000); + +}); + +describe('regenerateApiKey', () => { + + it('POC | Authenticated, When request made, expect to return success response', async () => { + let authApi = new AuthenticationApi(apiTesterConfiguration); + + let respone = await authApi.regenerateApiKey(); + expect(respone.status).toBe(200); + + }, 30000); - it('Should list down all the organizations',async () => { + it('API-Key | Authenticated, When request made with same api key, expect to return unauthorizes response', async () => { + let authApi = new AuthenticationApi(apiTesterKeyConfiguration); - let generalAPI = new GeneralApi(configuration); - const orgList = await generalAPI.listOrganizations(); - expect(Array.isArray(orgList.data)).toBe(true); + const response = authApi.regenerateApiKey(); + await expect(response).rejects.toMatchObject({ response: { status: 401 } }); - },10000); + }, 30000); }); \ No newline at end of file diff --git a/src/__tests__/gtfsflex.test.ts b/src/__tests__/gtfsflex.test.ts new file mode 100644 index 0000000..15441dc --- /dev/null +++ b/src/__tests__/gtfsflex.test.ts @@ -0,0 +1,702 @@ +import { Configuration, CommonAPIsApi, GTFSFlexApi, VersionSpec } from "tdei-client"; +import { Utility } from "../utils"; +import axios, { InternalAxiosRequestConfig } from "axios"; +import AdmZip from "adm-zip"; +import exp from "constants"; + +const NULL_PARAM = void 0; + +let apiKeyConfiguration: Configuration = {}; +let pocConfiguration: Configuration = {}; +let dgConfiguration: Configuration = {}; +let oswdgConfiguration: Configuration = {}; +let adminConfiguration: Configuration = {}; +let validationJobId: string = '1'; +let uploadedJobId: string = '1'; +let uploadedDatasetId: string = '1'; +let publishJobId: string = '1'; +let tdei_project_group_id = ""; +let service_id = ""; +let apiInput: any = {}; + +const editMetadataRequestInterceptor = (request: InternalAxiosRequestConfig, tdei_dataset_id: string, datasetName: string) => { + if ( + request.url?.includes(`/api/v1/metadata/${tdei_dataset_id}`) + ) { + let data = request.data as FormData; + let metaFile = data.get("file") as File; + delete data['file']; + data.set('file', metaFile, datasetName); + } + return request; +}; + +const uploadRequestInterceptor = (request: InternalAxiosRequestConfig, tdei_project_group_id: string, service_id: string, datasetName: string, changestName: string, metafileName: string) => { + if ( + request.url?.includes(`/api/v1/gtfs-flex/upload/${tdei_project_group_id}/${service_id}`) + ) { + let data = request.data as FormData; + let datasetFile = data.get("dataset") as File; + let metaFile = data.get('metadata') as File; + let changesetFile = data.get('changeset') as File; + delete data['dataset']; + delete data['metadata']; + delete data['changeset']; + data.set('dataset', datasetFile, datasetName); + data.set('metadata', metaFile, metafileName); + data.set('changeset', changesetFile, changestName); + + } + return request; +}; + +const validateRequestInterceptor = (request: InternalAxiosRequestConfig, datasetName: string) => { + if ( + request.url?.includes(`/api/v1/gtfs-flex/validate`) + ) { + let data = request.data as FormData; + let datasetFile = data.get("dataset") as File; + delete data['dataset']; + data.set('dataset', datasetFile, datasetName); + } + return request; +}; + +beforeAll(async () => { + let seedData = Utility.seedData; + tdei_project_group_id = seedData.project_group.tdei_project_group_id; + service_id = seedData.services.find(x => x.service_type == "flex")!.tdei_service_id; + apiKeyConfiguration = Utility.getApiKeyConfiguration(); + pocConfiguration = Utility.getPocConfiguration(); + dgConfiguration = Utility.getFlexDataGeneratorConfiguration(); + adminConfiguration = Utility.getAdminConfiguration(); + oswdgConfiguration = Utility.getOSWDataGeneratorConfiguration(); + await Utility.setAuthToken(adminConfiguration); + await Utility.setAuthToken(pocConfiguration); + await Utility.setAuthToken(dgConfiguration); + await Utility.setAuthToken(oswdgConfiguration); + apiInput = Utility.getApiInput(); + +}); + + +describe('Upload flex dataset', () => { + + it('Flex Data Generator | Authenticated , When request made with dataset, metadata and changeset file, should return request job id as response', async () => { + let flexAPI = new GTFSFlexApi(dgConfiguration); + let metaToUpload = Utility.getMetadataBlob("flex"); + let changesetToUpload = Utility.getChangesetBlob(); + let dataset = Utility.getFlexBlob(); + let derived_from_dataset_id = ''; + const uploadInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => uploadRequestInterceptor(req, tdei_project_group_id, service_id, 'flex-valid.zip', 'changeset.zip', 'metadata.json')) + const uploadFileResponse = await flexAPI.uploadGtfsFlexFileForm(dataset, metaToUpload, changesetToUpload, tdei_project_group_id, service_id, derived_from_dataset_id); + + expect(uploadFileResponse.status).toBe(202); + expect(uploadFileResponse.data).not.toBeNull(); + uploadedJobId = uploadFileResponse.data; + console.log("uploaded job_id", uploadedJobId); + axios.interceptors.request.eject(uploadInterceptor); + //verify location header + expect(uploadFileResponse.headers.location).toBeDefined(); + expect(uploadFileResponse.headers.location).toContain(`/api/v1/jobs?job_id=${uploadedJobId}`); + + }, 20000); + + it('POC | Authenticated , When request made with dataset, metadata and changeset file, should return request job id as response', async () => { + let flexAPI = new GTFSFlexApi(pocConfiguration); + let metaToUpload = Utility.getMetadataBlob("flex"); + let changesetToUpload = Utility.getChangesetBlob(); + let dataset = Utility.getFlexBlob(); + let derived_from_dataset_id = ''; + const uploadInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => uploadRequestInterceptor(req, tdei_project_group_id, service_id, 'flex-valid.zip', 'changeset.zip', 'metadata.json')) + const uploadFileResponse = await flexAPI.uploadGtfsFlexFileForm(dataset, metaToUpload, changesetToUpload, tdei_project_group_id, service_id, derived_from_dataset_id); + + expect(uploadFileResponse.status).toBe(202); + expect(uploadFileResponse.data).not.toBeNull(); + axios.interceptors.request.eject(uploadInterceptor); + }, 20000); + + it('Admin | Authenticated , When request made with dataset, metadata and changeset file, should return request job id as response', async () => { + let flexAPI = new GTFSFlexApi(adminConfiguration); + let metaToUpload = Utility.getMetadataBlob("flex"); + let changesetToUpload = Utility.getChangesetBlob(); + let dataset = Utility.getFlexBlob(); + let derived_from_dataset_id = ''; + const uploadInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => uploadRequestInterceptor(req, tdei_project_group_id, service_id, 'flex-valid.zip', 'changeset.zip', 'metadata.json')) + const uploadFileResponse = await flexAPI.uploadGtfsFlexFileForm(dataset, metaToUpload, changesetToUpload, tdei_project_group_id, service_id, derived_from_dataset_id); + + expect(uploadFileResponse.status).toBe(202); + expect(uploadFileResponse.data).not.toBeNull(); + + axios.interceptors.request.eject(uploadInterceptor); + }, 20000); + + it('Admin | Authenticated , When request made with dataset and invalid metafile, should return bad request with metadata validation errors', async () => { + let flexAPI = new GTFSFlexApi(adminConfiguration); + let metaToUpload = Utility.getInvalidMetadataBlob("flex"); + let changesetToUpload = Utility.getChangesetBlob(); + let dataset = Utility.getFlexBlob(); + const uploadInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => uploadRequestInterceptor(req, tdei_project_group_id, service_id, 'flex-valid.zip', 'changeset.zip', 'metadata.json')) + const uploadFileResponse = flexAPI.uploadGtfsFlexFileForm(dataset, metaToUpload, changesetToUpload, tdei_project_group_id, service_id) + + await expect(uploadFileResponse).rejects.toMatchObject({ response: { status: 400 } }); + + axios.interceptors.request.eject(uploadInterceptor); + }, 20000) + + it('Admin | Authenticated , When request made with invalid service id, should return service id not found', async () => { + let flexAPI = new GTFSFlexApi(adminConfiguration); + let metaToUpload = Utility.getMetadataBlob("flex"); + let changesetToUpload = Utility.getChangesetBlob(); + let dataset = Utility.getFlexBlob(); + const uploadInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => uploadRequestInterceptor(req, tdei_project_group_id, "invalid_service_id", 'flex-valid.zip', 'changeset.zip', 'metadata.json')) + const uploadFileResponse = flexAPI.uploadGtfsFlexFileForm(dataset, metaToUpload, changesetToUpload, tdei_project_group_id, "invalid_service_id") + + await expect(uploadFileResponse).rejects.toMatchObject({ response: { status: 404 } }); + + axios.interceptors.request.eject(uploadInterceptor); + }, 20000) + + it('Admin | Authenticated , When request made with invalid project id, should return project id not found', async () => { + let flexAPI = new GTFSFlexApi(adminConfiguration); + let metaToUpload = Utility.getMetadataBlob("flex"); + let changesetToUpload = Utility.getChangesetBlob(); + let dataset = Utility.getFlexBlob(); + const uploadInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => uploadRequestInterceptor(req, "invalid_tdei_project_group_id", service_id, 'flex-valid.zip', 'changeset.zip', 'metadata.json')) + const uploadFileResponse = flexAPI.uploadGtfsFlexFileForm(dataset, metaToUpload, changesetToUpload, "invalid_tdei_project_group_id", service_id) + + await expect(uploadFileResponse).rejects.toMatchObject({ response: { status: 404 } }); + + axios.interceptors.request.eject(uploadInterceptor); + }, 20000); + + it('Admin | Authenticated , When request made with invalid derived dataset id, should return derived dataset id not found', async () => { + let flexAPI = new GTFSFlexApi(adminConfiguration); + let metaToUpload = Utility.getMetadataBlob("flex"); + let changesetToUpload = Utility.getChangesetBlob(); + let dataset = Utility.getFlexBlob(); + const uploadInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => uploadRequestInterceptor(req, tdei_project_group_id, service_id, 'flex-valid.zip', 'changeset.zip', 'metadata.json')) + const uploadFileResponse = flexAPI.uploadGtfsFlexFileForm(dataset, metaToUpload, changesetToUpload, tdei_project_group_id, service_id, "Invalid-derived-dataset-id"); + + await expect(uploadFileResponse).rejects.toMatchObject({ response: { status: 404 } }); + + axios.interceptors.request.eject(uploadInterceptor); + }, 20000); + + it('OSW Data Generator | Authenticated , When request made with valid inputs, should return unauthorized error', async () => { + let flexAPI = new GTFSFlexApi(oswdgConfiguration); + let metaToUpload = Utility.getMetadataBlob("flex"); + let changesetToUpload = Utility.getChangesetBlob(); + let dataset = Utility.getFlexBlob(); + const uploadInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => uploadRequestInterceptor(req, tdei_project_group_id, service_id, 'flex-valid.zip', 'changeset.zip', 'metadata.json')) + const uploadFileResponse = flexAPI.uploadGtfsFlexFileForm(dataset, metaToUpload, changesetToUpload, tdei_project_group_id, service_id) + + await expect(uploadFileResponse).rejects.toMatchObject({ response: { status: 403 } }); + + axios.interceptors.request.eject(uploadInterceptor); + }, 20000); + + it('Admin | un-authenticated , When request made with dataset, metadata and changeset file, should respond with unauthenticated request', async () => { + let flexAPI = new GTFSFlexApi(Utility.getAdminConfiguration()); + let metaToUpload = Utility.getMetadataBlob("flex"); + let changesetToUpload = Utility.getChangesetBlob(); + let dataset = Utility.getFlexBlob(); + + const uploadInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => uploadRequestInterceptor(req, tdei_project_group_id, service_id, 'flex-valid.zip', 'changeset.zip', 'metadata.json')) + const uploadFileResponse = flexAPI.uploadGtfsFlexFileForm(dataset, metaToUpload, changesetToUpload, tdei_project_group_id, service_id) + + await expect(uploadFileResponse).rejects.toMatchObject({ response: { status: 401 } }); + axios.interceptors.request.eject(uploadInterceptor); + + }, 20000) + + it('API-Key | Authenticated , When request made with dataset, metadata and changeset file, should respond with unauthorized request', async () => { + let flexAPI = new GTFSFlexApi(apiKeyConfiguration); + let metaToUpload = Utility.getMetadataBlob("flex"); + let changesetToUpload = Utility.getChangesetBlob(); + let dataset = Utility.getFlexBlob(); + + const uploadInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => uploadRequestInterceptor(req, tdei_project_group_id, service_id, 'flex-valid.zip', 'changeset.zip', 'metadata.json')) + const uploadFileResponse = flexAPI.uploadGtfsFlexFileForm(dataset, metaToUpload, changesetToUpload, tdei_project_group_id, service_id, NULL_PARAM, { headers: { 'x-api-key': apiKeyConfiguration.apiKey?.toString() } }) + + await expect(uploadFileResponse).rejects.toMatchObject({ response: { status: 403 } }); + axios.interceptors.request.eject(uploadInterceptor); + + }, 20000) +}); + +describe('Check upload request job completion status', () => { + jest.retryTimes(1, { logErrorsBeforeRetry: true }); + it('Flex Data Generator | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(dgConfiguration); + await new Promise((r) => setTimeout(r, 80000)); + let uploadStatus = await generalAPI.listJobs(tdei_project_group_id, uploadedJobId, true); + expect(uploadStatus.status).toBe(200); + expect(uploadStatus.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + job_id: expect.toBeOneOf([`${uploadedJobId}`]), + status: expect.toBeOneOf(["COMPLETED"]), + progress: expect.objectContaining({ + total_stages: expect.any(Number), + completed_stages: expect.any(Number), + current_state: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "RUNNING"]), + current_stage: expect.any(String) + }) + }) + ]) + ); + uploadedDatasetId = uploadStatus.data[0].response_props.tdei_dataset_id; + console.log("uploaded dataset_id", uploadedDatasetId); + }, 90000); + + it('POC | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(pocConfiguration); + let uploadStatus = await generalAPI.listJobs(tdei_project_group_id, uploadedJobId, true); + expect(uploadStatus.status).toBe(200); + }, 25000); + + + it('Admin | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(adminConfiguration); + let uploadStatus = await generalAPI.listJobs("", uploadedJobId, true); + expect(uploadStatus.status).toBe(200); + }, 25000); + + it('Admin | un-authenticated , When request made, should respond with unauthenticated request', async () => { + let generalAPI = new CommonAPIsApi(Utility.getAdminConfiguration()); + + let listResponse = generalAPI.listJobs("", uploadedJobId, true); + + await expect(listResponse).rejects.toMatchObject({ response: { status: 401 } }); + }); + + it('API-Key | Authenticated , When request made, should respond with success request', async () => { + let generalAPI = new CommonAPIsApi(apiKeyConfiguration); + + let listResponse = await generalAPI.listJobs(tdei_project_group_id, uploadedJobId, true); + + expect(listResponse.status).toBe(200); + }); +}); + +describe("Edit Metadata API", () => { + + it('Flex Data Generator | Authenticated , When request made, expect to return sucess', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(dgConfiguration); + let metaToUpload = Utility.getMetadataBlob("flex"); + let tdei_dataset_id = uploadedDatasetId; + // Action + const editMetaInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => editMetadataRequestInterceptor(req, tdei_dataset_id, 'metadata.json')) + const versions = await generalAPI.editMetadataForm(metaToUpload, tdei_dataset_id); + // Assert + expect(versions.status).toBe(200); + axios.interceptors.request.eject(editMetaInterceptor); + }, 30000); + + it('POC | Authenticated , When request made, expect to return sucess', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(pocConfiguration); + let metaToUpload = Utility.getMetadataBlob("flex"); + let tdei_dataset_id = uploadedDatasetId; + // Action + const editMetaInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => editMetadataRequestInterceptor(req, tdei_dataset_id, 'metadata.json')) + const versions = await generalAPI.editMetadataForm(metaToUpload, tdei_dataset_id); + // Assert + expect(versions.status).toBe(200); + axios.interceptors.request.eject(editMetaInterceptor); + }, 30000); + + it('Admin | Authenticated , When request made, expect to return sucess', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(adminConfiguration); + let metaToUpload = Utility.getMetadataBlob("flex"); + let tdei_dataset_id = uploadedDatasetId; + // Action + const editMetaInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => editMetadataRequestInterceptor(req, tdei_dataset_id, 'metadata.json')) + const versions = await generalAPI.editMetadataForm(metaToUpload, tdei_dataset_id); + // Assert + expect(versions.status).toBe(200); + axios.interceptors.request.eject(editMetaInterceptor); + }, 30000); + + it('Admin | un-authenticated, When request made, should respond with unauthenticated request', async () => { + + // Arrange + let generalAPI = new CommonAPIsApi(Utility.getAdminConfiguration()); + let metaToUpload = Utility.getMetadataBlob("flex"); + let tdei_dataset_id = uploadedDatasetId; + // Action + const editMetaInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => editMetadataRequestInterceptor(req, tdei_dataset_id, 'metadata.json')) + // Assert + await expect(generalAPI.editMetadataForm(metaToUpload, tdei_dataset_id)).rejects.toMatchObject({ response: { status: 401 } }); + axios.interceptors.request.eject(editMetaInterceptor); + }, 30000); +}); + +describe('Publish the flex dataset', () => { + jest.retryTimes(1, { logErrorsBeforeRetry: true }); + + it('Admin | When passed with valid input having null valid_from & valid_to metadata, should respond with required field error', async () => { + let gtfsFlexApi = new GTFSFlexApi(adminConfiguration); + + let publishResponse = gtfsFlexApi.publishGtfsFlexFile(uploadedDatasetId); + + await expect(publishResponse).rejects.toMatchObject({ response: { status: 400 } }); + }); + + it('Flex Data Generator | Authenticated , Edit metadata before publishing, should return success', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(dgConfiguration); + let metaToUpload = Utility.getEditMetadataBlob("flex", { + valid_from: "2024-10-31T18:30:00.000Z", + valid_to: "2024-11-01T18:30:00.000Z" + }); + let tdei_dataset_id = uploadedDatasetId; + // Action + const editMetaInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => editMetadataRequestInterceptor(req, tdei_dataset_id, 'metadata.json')) + const versions = await generalAPI.editMetadataForm(metaToUpload, tdei_dataset_id); + // Assert + expect(versions.status).toBe(200); + axios.interceptors.request.eject(editMetaInterceptor); + }, 30000); + + it('Flex Data Generator | Authenticated , When request made with tdei_dataset_id, should return request job id as response', async () => { + + await new Promise((r) => setTimeout(r, 60000)); + let flexAPI = new GTFSFlexApi(dgConfiguration); + let publish = await flexAPI.publishGtfsFlexFile(uploadedDatasetId); + expect(publish.status).toBe(202); + expect(publish.data).toBeNumber(); + publishJobId = publish.data; + console.log("publish job_id", publishJobId); + //verify location header + expect(publish.headers.location).toBeDefined(); + expect(publish.headers.location).toContain(`/api/v1/jobs?job_id=${publishJobId}`); + }, 70000); + + it('Admin | When passed with already published tdei_dataset_id, should respond with bad request', async () => { + + let flexAPI = new GTFSFlexApi(adminConfiguration); + let tdei_dataset_id = apiInput.flex.published_dataset; + + let publishResponse = flexAPI.publishGtfsFlexFile(tdei_dataset_id); + + await expect(publishResponse).rejects.toMatchObject({ response: { status: 400 } }); + }); + + it('Admin | When passed with invalid tdei_dataset_id, should respond with dataset id not found', async () => { + + let flexAPI = new GTFSFlexApi(adminConfiguration); + + let publishResponse = flexAPI.publishGtfsFlexFile("invalid_tdei_dataset_id"); + + await expect(publishResponse).rejects.toMatchObject({ response: { status: 404 } }); + }); + + it('Admin | When passed with osw tdei_dataset_id, should respond with daset type mismatch error', async () => { + + let flexAPI = new GTFSFlexApi(adminConfiguration); + let tdei_dataset_id = apiInput.osw.pre_release_dataset; + + let publishResponse = flexAPI.publishGtfsFlexFile(tdei_dataset_id); + + await expect(publishResponse).rejects.toMatchObject({ response: { status: 400 } }); + }); + + it('Admin | un-authenticated , When request made, should respond with unauthenticated request', async () => { + let flexAPI = new GTFSFlexApi(Utility.getAdminConfiguration()); + + let publishResponse = flexAPI.publishGtfsFlexFile(uploadedDatasetId); + + await expect(publishResponse).rejects.toMatchObject({ response: { status: 401 } }); + }); + + it('API-Key | Authenticated , When request made, should respond with unauthorized request', async () => { + let flexAPI = new GTFSFlexApi(apiKeyConfiguration); + + let publishResponse = flexAPI.publishGtfsFlexFile(uploadedDatasetId); + + await expect(publishResponse).rejects.toMatchObject({ response: { status: 403 } }); + }); +}); + +describe('Check publish request job completion status', () => { + jest.retryTimes(1, { logErrorsBeforeRetry: true }); + + it('Admin | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(adminConfiguration); + await new Promise((r) => setTimeout(r, 60000)); + + let uploadStatus = await generalAPI.listJobs(tdei_project_group_id, publishJobId, true); + + expect(uploadStatus.status).toBe(200); + expect(uploadStatus.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + job_id: expect.toBeOneOf([`${publishJobId}`]), + status: expect.toBeOneOf(["COMPLETED"]), + progress: expect.objectContaining({ + total_stages: expect.any(Number), + completed_stages: expect.any(Number), + current_state: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "RUNNING"]), + current_stage: expect.any(String) + }) + }) + ]) + ); + }, 70000); + + it('POC | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(pocConfiguration); + let uploadStatus = await generalAPI.listJobs(tdei_project_group_id, publishJobId, true); + expect(uploadStatus.status).toBe(200); + }, 25000); + + + it('Admin | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(adminConfiguration); + let uploadStatus = await generalAPI.listJobs("", publishJobId, true); + expect(uploadStatus.status).toBe(200); + }, 25000); + + it('Admin | un-authenticated , When request made, should respond with unauthenticated request', async () => { + let generalAPI = new CommonAPIsApi(Utility.getAdminConfiguration()); + + let downloadResponse = generalAPI.listJobs("", publishJobId, true); + + await expect(downloadResponse).rejects.toMatchObject({ response: { status: 401 } }); + }); + +}); + +describe('Validate-only flex dataset request', () => { + it('Flex Data Generator | Authenticated , When request made with valid dataset, should return request job id as response', async () => { + let flexAPI = new GTFSFlexApi(dgConfiguration); + let dataset = Utility.getFlexBlob(); + try { + const validateInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => validateRequestInterceptor(req, 'flex-valid.zip')) + const validateFileResponse = await flexAPI.validateGtfsFlexFileForm(dataset); + + expect(validateFileResponse.status).toBe(202); + expect(validateFileResponse.data).not.toBeNull(); + validationJobId = validateFileResponse.data; + console.log("validation job_id", validationJobId); + axios.interceptors.request.eject(validateInterceptor); + //verify location header + expect(validateFileResponse.headers.location).toBeDefined(); + expect(validateFileResponse.headers.location).toContain(`/api/v1/jobs?job_id=${validationJobId}`); + } catch (e) { + console.log(e); + } + }, 20000) + + it('Admin | Authenticated , When request made with valid dataset, should return request job id as response', async () => { + let flexAPI = new GTFSFlexApi(adminConfiguration); + let dataset = Utility.getFlexBlob(); + + const validateInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => validateRequestInterceptor(req, 'flex-valid.zip')) + const uploadFileResponse = await flexAPI.validateGtfsFlexFileForm(dataset); + + expect(uploadFileResponse.status).toBe(202); + expect(uploadFileResponse.data).not.toBeNull(); + axios.interceptors.request.eject(validateInterceptor); + + }, 20000) + + it('Admin | un-authenticated , When request made with dataset, should return with unauthenticated request', async () => { + let flexAPI = new GTFSFlexApi(Utility.getAdminConfiguration()); + let dataset = Utility.getFlexBlob(); + + const validateInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => validateRequestInterceptor(req, 'flex-valid.zip')) + const uploadFileResponse = flexAPI.validateGtfsFlexFileForm(dataset); + + await expect(uploadFileResponse).rejects.toMatchObject({ response: { status: 401 } }); + axios.interceptors.request.eject(validateInterceptor); + + }, 20000); + + it('API-Key | Authenticated , When request made with dataset, should return request job id as response', async () => { + let flexAPI = new GTFSFlexApi(apiKeyConfiguration); + let dataset = Utility.getFlexBlob(); + + const validateInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => validateRequestInterceptor(req, 'flex-valid.zip')) + const uploadFileResponse = await flexAPI.validateGtfsFlexFileForm(dataset, { headers: { 'x-api-key': apiKeyConfiguration.apiKey?.toString() } }); + + expect(uploadFileResponse.status).toBe(202); + expect(uploadFileResponse.data).not.toBeNull(); + axios.interceptors.request.eject(validateInterceptor); + + }, 20000); + +}); + +describe('Check validation-only request job completion status', () => { + jest.retryTimes(1, { logErrorsBeforeRetry: true }); + it('Admin | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(adminConfiguration); + + await new Promise((r) => setTimeout(r, 20000)); + let validateStatus = await generalAPI.listJobs("", validationJobId, true); + + expect(validateStatus.status).toBe(200); + expect(validateStatus.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + job_id: expect.toBeOneOf([`${validationJobId}`]), + status: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS"]), + progress: expect.objectContaining({ + total_stages: expect.any(Number), + completed_stages: expect.any(Number), + current_state: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "RUNNING"]), + current_stage: expect.any(String) + }) + }) + ]) + ); + }, 25000); + + it('POC | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(pocConfiguration); + let uploadStatus = await generalAPI.listJobs(tdei_project_group_id, validationJobId, true); + expect(uploadStatus.status).toBe(200); + }, 25000); + + + it('Admin | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(adminConfiguration); + let uploadStatus = await generalAPI.listJobs("", validationJobId, true); + expect(uploadStatus.status).toBe(200); + }, 25000); + + it('Admin | un-authenticated , When request made, should respond with unauthenticated request', async () => { + let generalAPI = new CommonAPIsApi(Utility.getAdminConfiguration()); + let validateStatusResponse = generalAPI.listJobs("", validationJobId, true); + await expect(validateStatusResponse).rejects.toMatchObject({ response: { status: 401 } }); + }) + +}); + +describe('List flex versions', () => { + it('Admin | Authenticated , When request made, should respond with flex version list', async () => { + let flexAPI = new GTFSFlexApi(adminConfiguration); + console.log("adminConfiguration", adminConfiguration); + let versions = await flexAPI.listGtfsFlexVersions(); + expect(versions.status).toBe(200); + expect(Array.isArray(versions.data.versions)).toBe(true); + versions.data.versions?.forEach(version => { + expect(version).toMatchObject({ + version: expect.any(String), + documentation: expect.any(String), + specification: expect.any(String) + }) + }) + }) + + it('API-Key | Authenticated , When request made, should respond with flex version list', async () => { + let flexAPI = new GTFSFlexApi(apiKeyConfiguration); + + let versions = await flexAPI.listGtfsFlexVersions({ headers: { 'x-api-key': apiKeyConfiguration.apiKey?.toString() } }); + + expect(versions.status).toBe(200); + expect(Array.isArray(versions.data.versions)).toBe(true); + versions.data.versions?.forEach(version => { + expect(version).toMatchObject({ + version: expect.any(String), + documentation: expect.any(String), + specification: expect.any(String) + }) + }) + }) + + it('Admin | un-authenticated , When request made, should respond with unauthenticated request', async () => { + let flexAPI = new GTFSFlexApi(Utility.getAdminConfiguration()); + + let versionsResponse = flexAPI.listGtfsFlexVersions(); + + await expect(versionsResponse).rejects.toMatchObject({ response: { status: 401 } }); + }) +}); + +describe('Download flex dataset', () => { + it('Admin | Authenticated , When request made with tdei_dataset_id, should stream the zip file', async () => { + + let flexAPI = new GTFSFlexApi(adminConfiguration); + + let response = await flexAPI.getGtfsFlexFile(uploadedDatasetId, { responseType: 'arraybuffer' }); + const data: any = response.data; + const contentType = response.headers['content-type']; + const zip = new AdmZip(data); + const entries = zip.getEntries(); + + expect(entries.length).toBeGreaterThanOrEqual(0); + expect(contentType).toBe("application/octet-stream"); + expect(response.data).not.toBeNull(); + expect(response.status).toBe(200); + }, 10000); + + it('Flex Data Generator | Authenticated , When request made with tdei_dataset_id, should stream the zip file', async () => { + + let flexAPI = new GTFSFlexApi(dgConfiguration); + + let response = await flexAPI.getGtfsFlexFile(uploadedDatasetId, { responseType: 'arraybuffer' }); + const data: any = response.data; + const contentType = response.headers['content-type']; + const zip = new AdmZip(data); + const entries = zip.getEntries(); + + expect(entries.length).toBeGreaterThanOrEqual(0); + expect(contentType).toBe("application/octet-stream"); + expect(response.data).not.toBeNull(); + expect(response.status).toBe(200); + }, 10000); + + it('API-Key | Authenticated , When request made with tdei_dataset_id, should stream the zip file', async () => { + + let flexAPI = new GTFSFlexApi(apiKeyConfiguration); + + let response = await flexAPI.getGtfsFlexFile(uploadedDatasetId, { responseType: 'arraybuffer' }); + const data: any = response.data; + const contentType = response.headers['content-type']; + const zip = new AdmZip(data); + const entries = zip.getEntries(); + + expect(entries.length).toBeGreaterThanOrEqual(0); + expect(contentType).toBe("application/octet-stream"); + expect(response.data).not.toBeNull(); + expect(response.status).toBe(200); + }, 10000); + + it('Admin | Authenticated , When request made with invalid tdei_dataset_id, should respond dataset id not found error', async () => { + + let recordId = 'dummyRecordId'; + let flexAPI = new GTFSFlexApi(adminConfiguration); + + let response = flexAPI.getGtfsFlexFile(recordId); + + await expect(response).rejects.toMatchObject({ response: { status: 404 } }); + + }); + + it('Admin | Authenticated , When request made with pathways tdei_dataset_id, should respond dataset type mismatch error', async () => { + + let flexAPI = new GTFSFlexApi(adminConfiguration); + + let response = flexAPI.getGtfsFlexFile(apiInput.pathways.pre_release_dataset); + + await expect(response).rejects.toMatchObject({ response: { status: 400 } }); + + }); + + it('Admin | un-authenticated , When request made with tdei_dataset_id, should respond with unauthenticated request', async () => { + + let flexAPI = new GTFSFlexApi(Utility.getAdminConfiguration()); + + let response = flexAPI.getGtfsFlexFile(uploadedDatasetId); + + await expect(response).rejects.toMatchObject({ response: { status: 401 } }); + + }); + +}); \ No newline at end of file diff --git a/src/__tests__/gtfspathways.test.ts b/src/__tests__/gtfspathways.test.ts new file mode 100644 index 0000000..653aaac --- /dev/null +++ b/src/__tests__/gtfspathways.test.ts @@ -0,0 +1,724 @@ +import { Configuration, GTFSPathwaysApi, CommonAPIsApi, VersionSpec } from "tdei-client"; +import { Utility } from "../utils"; +import axios, { InternalAxiosRequestConfig } from "axios"; +import AdmZip from "adm-zip"; + +let apiKeyConfiguration: Configuration = {}; +let pocConfiguration: Configuration = {}; +let dgConfiguration: Configuration = {}; +let oswDgConfiguration: Configuration = {}; +let adminConfiguration: Configuration = {}; +const NULL_PARAM = void 0; + +let validationJobId: string = '1'; +let uploadedJobId: string = '1'; +let publishJobId: string = '1'; +let uploadedDatasetId: string = '1'; +let tdei_project_group_id = ""; +let service_id = ""; +let apiInput: any = {}; + +const editMetadataRequestInterceptor = (request: InternalAxiosRequestConfig, tdei_dataset_id: string, datasetName: string) => { + if ( + request.url?.includes(`/api/v1/metadata/${tdei_dataset_id}`) + ) { + let data = request.data as FormData; + let metaFile = data.get("file") as File; + delete data['file']; + data.set('file', metaFile, datasetName); + } + return request; +}; + +const uploadRequestInterceptor = (request: InternalAxiosRequestConfig, tdei_project_group_id: string, service_id: string, datasetName: string, changestName: string, metafileName: string) => { + if ( + request.url?.includes(`/api/v1/gtfs-pathways/upload/${tdei_project_group_id}/${service_id}`) + ) { + let data = request.data as FormData; + let datasetFile = data.get("dataset") as File; + let metaFile = data.get('metadata') as File; + let changesetFile = data.get('changeset') as File; + delete data['dataset']; + delete data['metadata']; + delete data['changeset']; + data.set('dataset', datasetFile, datasetName); + data.set('metadata', metaFile, metafileName); + data.set('changeset', changesetFile, changestName); + } + return request; +}; + +const validateRequestInterceptor = (request: InternalAxiosRequestConfig, datasetName: string) => { + if ( + request.url?.includes(`/api/v1/gtfs-pathways/validate`) + ) { + let data = request.data as FormData; + let datasetFile = data.get("dataset") as File; + delete data['dataset']; + data.set('dataset', datasetFile, datasetName); + } + return request; +}; + +beforeAll(async () => { + let seedData = Utility.seedData; + tdei_project_group_id = seedData.project_group.tdei_project_group_id; + service_id = seedData.services.find(x => x.service_type == "pathways")!.tdei_service_id; + adminConfiguration = Utility.getAdminConfiguration(); + apiKeyConfiguration = Utility.getApiKeyConfiguration(); + pocConfiguration = Utility.getPocConfiguration(); + dgConfiguration = Utility.getPathwaysDataGeneratorConfiguration(); + oswDgConfiguration = Utility.getOSWDataGeneratorConfiguration(); + await Utility.setAuthToken(adminConfiguration); + await Utility.setAuthToken(pocConfiguration); + await Utility.setAuthToken(dgConfiguration); + await Utility.setAuthToken(oswDgConfiguration); + apiInput = Utility.getApiInput(); +}); + + +describe('Upload pathways dataset', () => { + + it('Pathways Data Generator | Authenticated , When request made with dataset, metadata and changeset file, should return request job id as response', async () => { + let pathwaysAPI = new GTFSPathwaysApi(dgConfiguration); + let metaToUpload = Utility.getMetadataBlob("pathways") + let changesetToUpload = Utility.getChangesetBlob(); + let dataset = Utility.getPathwaysBlob(); + let derived_from_dataset_id = ''; + try { + const uploadInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => uploadRequestInterceptor(req, tdei_project_group_id, service_id, 'pathways-valid.zip', 'changeset.zip', 'metadata.json')) + const uploadFileResponse = await pathwaysAPI.uploadGtfsPathwaysFileForm(dataset, metaToUpload, changesetToUpload, tdei_project_group_id, service_id, derived_from_dataset_id); + + expect(uploadFileResponse.status).toBe(202); + expect(uploadFileResponse.data).not.toBeNull(); + uploadedJobId = uploadFileResponse.data; + console.log("uploaded tdei_dataset_id", uploadedJobId); + axios.interceptors.request.eject(uploadInterceptor); + //verify location header + expect(uploadFileResponse.headers.location).toBeDefined(); + expect(uploadFileResponse.headers.location).toContain(`/api/v1/jobs?job_id=${uploadedJobId}`); + } catch (e) { + console.log(e); + } + }, 20000); + + it('POC | Authenticated , When request made with dataset, metadata and changeset file, should return request job id as response', async () => { + let pathwaysAPI = new GTFSPathwaysApi(pocConfiguration); + let metaToUpload = Utility.getMetadataBlob("pathways") + let changesetToUpload = Utility.getChangesetBlob(); + let dataset = Utility.getPathwaysBlob(); + let derived_from_dataset_id = ''; + try { + const uploadInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => uploadRequestInterceptor(req, tdei_project_group_id, service_id, 'pathways-valid.zip', 'changeset.zip', 'metadata.json')) + const uploadFileResponse = await pathwaysAPI.uploadGtfsPathwaysFileForm(dataset, metaToUpload, changesetToUpload, tdei_project_group_id, service_id, derived_from_dataset_id); + + expect(uploadFileResponse.status).toBe(202); + expect(uploadFileResponse.data).not.toBeNull(); + axios.interceptors.request.eject(uploadInterceptor); + } catch (e) { + console.log(e); + } + }, 20000); + + it('Admin | Authenticated , When request made with dataset, metadata and changeset file, should return request job id as response', async () => { + let pathwaysAPI = new GTFSPathwaysApi(adminConfiguration); + let metaToUpload = Utility.getMetadataBlob("pathways") + let changesetToUpload = Utility.getChangesetBlob(); + let dataset = Utility.getPathwaysBlob(); + let derived_from_dataset_id = ''; + try { + const uploadInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => uploadRequestInterceptor(req, tdei_project_group_id, service_id, 'pathways-valid.zip', 'changeset.zip', 'metadata.json')) + const uploadFileResponse = await pathwaysAPI.uploadGtfsPathwaysFileForm(dataset, metaToUpload, changesetToUpload, tdei_project_group_id, service_id, derived_from_dataset_id); + + expect(uploadFileResponse.status).toBe(202); + expect(uploadFileResponse.data).not.toBeNull(); + axios.interceptors.request.eject(uploadInterceptor); + } catch (e) { + console.log(e); + } + }, 20000); + + it('Admin | Authenticated , When request made with dataset and invalid metafile, should return bad request with metadata validation errors', async () => { + let pathwaysAPI = new GTFSPathwaysApi(adminConfiguration); + let metaToUpload = Utility.getInvalidMetadataBlob("Pathways"); + let changesetToUpload = Utility.getChangesetBlob(); + let dataset = Utility.getPathwaysBlob(); + try { + const uploadInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => uploadRequestInterceptor(req, tdei_project_group_id, service_id, 'pathways-valid.zip', 'changeset.zip', 'metadata.json')) + const uploadFileResponse = pathwaysAPI.uploadGtfsPathwaysFileForm(dataset, metaToUpload, changesetToUpload, tdei_project_group_id, service_id) + + expect(await uploadFileResponse).rejects.toMatchObject({ response: { status: 400 } }); + + axios.interceptors.request.eject(uploadInterceptor); + } catch (e) { + console.log(e); + } + }, 20000) + + it('Admin | Authenticated , When request made with invalid service id, should return service id not found', async () => { + let pathwaysAPI = new GTFSPathwaysApi(adminConfiguration); + let metaToUpload = Utility.getMetadataBlob("pathways"); + let changesetToUpload = Utility.getChangesetBlob(); + let dataset = Utility.getPathwaysBlob(); + try { + const uploadInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => uploadRequestInterceptor(req, tdei_project_group_id, "invalid_service_id", 'pathways-valid.zip', 'changeset.zip', 'metadata.json')) + const uploadFileResponse = pathwaysAPI.uploadGtfsPathwaysFileForm(dataset, metaToUpload, changesetToUpload, tdei_project_group_id, "invalid_service_id") + + expect(await uploadFileResponse).rejects.toMatchObject({ response: { status: 404 } }); + + axios.interceptors.request.eject(uploadInterceptor); + } catch (e) { + console.log(e); + } + }, 20000); + + it('Admin | Authenticated , When request made with invalid project group id, should return project group id not found', async () => { + let pathwaysAPI = new GTFSPathwaysApi(adminConfiguration); + let metaToUpload = Utility.getMetadataBlob("pathways"); + let changesetToUpload = Utility.getChangesetBlob(); + let dataset = Utility.getPathwaysBlob(); + try { + const uploadInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => uploadRequestInterceptor(req, "invalid_tdei_project_group_id", service_id, 'pathways-valid.zip', 'changeset.zip', 'metadata.json')) + const uploadFileResponse = pathwaysAPI.uploadGtfsPathwaysFileForm(dataset, metaToUpload, changesetToUpload, "invalid_tdei_project_group_id", service_id) + + expect(await uploadFileResponse).rejects.toMatchObject({ response: { status: 404 } }); + + axios.interceptors.request.eject(uploadInterceptor); + } catch (e) { + console.log(e); + } + }, 20000); + + it('Admin | Authenticated , When request made with invalid derived dataset id, should return derived dataset id not found', async () => { + let pathwaysAPI = new GTFSPathwaysApi(adminConfiguration); + let metaToUpload = Utility.getMetadataBlob("pathways"); + let changesetToUpload = Utility.getChangesetBlob(); + let dataset = Utility.getPathwaysBlob(); + try { + const uploadInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => uploadRequestInterceptor(req, tdei_project_group_id, service_id, 'pathways-valid.zip', 'changeset.zip', 'metadata.json')) + const uploadFileResponse = pathwaysAPI.uploadGtfsPathwaysFileForm(dataset, metaToUpload, changesetToUpload, tdei_project_group_id, service_id, "invalid_derived_dataset_id") + + expect(await uploadFileResponse).rejects.toMatchObject({ response: { status: 404 } }); + + axios.interceptors.request.eject(uploadInterceptor); + } catch (e) { + console.log(e); + } + }, 20000); + + it('OSW Data Generator | Authenticated , When request made with valid input, should return unauthorized request', async () => { + let pathwaysAPI = new GTFSPathwaysApi(oswDgConfiguration); + let metaToUpload = Utility.getMetadataBlob("pathways"); + let changesetToUpload = Utility.getChangesetBlob(); + let dataset = Utility.getPathwaysBlob(); + try { + const uploadInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => uploadRequestInterceptor(req, tdei_project_group_id, service_id, 'pathways-valid.zip', 'changeset.zip', 'metadata.json')) + const uploadFileResponse = pathwaysAPI.uploadGtfsPathwaysFileForm(dataset, metaToUpload, changesetToUpload, tdei_project_group_id, service_id) + + expect(await uploadFileResponse).rejects.toMatchObject({ response: { status: 403 } }); + + axios.interceptors.request.eject(uploadInterceptor); + } catch (e) { + console.log(e); + } + }, 20000); + + it('Admin | un-authenticated , When request made with dataset, metadata and changeset file, should respond with unauthenticated request', async () => { + let pathwaysAPI = new GTFSPathwaysApi(Utility.getAdminConfiguration()); + let metaToUpload = Utility.getMetadataBlob("pathways"); + let changesetToUpload = Utility.getChangesetBlob(); + let dataset = Utility.getPathwaysBlob(); + + const uploadInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => uploadRequestInterceptor(req, tdei_project_group_id, service_id, 'pathways-valid.zip', 'changeset.zip', 'metadata.json')) + const uploadFileResponse = pathwaysAPI.uploadGtfsPathwaysFileForm(dataset, metaToUpload, changesetToUpload, tdei_project_group_id, service_id) + + await expect(uploadFileResponse).rejects.toMatchObject({ response: { status: 401 } }); + axios.interceptors.request.eject(uploadInterceptor); + + }, 20000) + + it('API-Key | authenticated , When request made with dataset, metadata and changeset file, should respond with unauthorized request', async () => { + let pathwaysAPI = new GTFSPathwaysApi(apiKeyConfiguration); + let metaToUpload = Utility.getMetadataBlob("pathways"); + let changesetToUpload = Utility.getChangesetBlob(); + let dataset = Utility.getPathwaysBlob(); + + const uploadInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => uploadRequestInterceptor(req, tdei_project_group_id, service_id, 'pathways-valid.zip', 'changeset.zip', 'metadata.json')) + const uploadFileResponse = pathwaysAPI.uploadGtfsPathwaysFileForm(dataset, metaToUpload, changesetToUpload, tdei_project_group_id, service_id, NULL_PARAM, { headers: { 'x-api-key': apiKeyConfiguration.apiKey?.toString() } }); + + await expect(uploadFileResponse).rejects.toMatchObject({ response: { status: 403 } }); + axios.interceptors.request.eject(uploadInterceptor); + + }, 20000) + +}); + +describe('Check upload request job completion status', () => { + jest.retryTimes(1, { logErrorsBeforeRetry: true }); + + it('Pathways Data Generator | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(dgConfiguration); + await new Promise((r) => setTimeout(r, 30000)); + + let uploadStatus = await generalAPI.listJobs(tdei_project_group_id, uploadedJobId, true); + expect(uploadStatus.status).toBe(200); + expect(uploadStatus.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + job_id: expect.toBeOneOf([`${uploadedJobId}`]), + status: expect.toBeOneOf(["COMPLETED"]), + progress: expect.objectContaining({ + total_stages: expect.any(Number), + completed_stages: expect.any(Number), + current_state: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "RUNNING"]), + current_stage: expect.any(String) + }) + }) + ]) + ); + uploadedDatasetId = uploadStatus.data[0].response_props.tdei_dataset_id; + console.log("uploaded tdei_dataset_id", uploadedDatasetId); + }, 35000); + + it('POC | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(pocConfiguration); + let uploadStatus = await generalAPI.listJobs(tdei_project_group_id, uploadedJobId, true); + expect(uploadStatus.status).toBe(200); + }, 25000); + + + it('Admin | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(adminConfiguration); + let uploadStatus = await generalAPI.listJobs("", uploadedJobId, true); + expect(uploadStatus.status).toBe(200); + }, 25000); + + it('Admin | un-authenticated , When request made, should respond with unauthenticated request', async () => { + let generalAPI = new CommonAPIsApi(Utility.getAdminConfiguration()); + + let listResponse = generalAPI.listJobs("", uploadedJobId, true); + + await expect(listResponse).rejects.toMatchObject({ response: { status: 401 } }); + }); + + it('API-Key | Authenticated , When request made, should respond with success request', async () => { + let generalAPI = new CommonAPIsApi(apiKeyConfiguration); + + let listResponse = await generalAPI.listJobs(tdei_project_group_id, uploadedJobId, true); + + expect(listResponse.status).toBe(200); + }); +}); + +describe("Edit Metadata API", () => { + + it('Pathways Data Generator | Authenticated , When request made, expect to return sucess', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(dgConfiguration); + let metaToUpload = Utility.getMetadataBlob("pathways"); + let tdei_dataset_id = uploadedDatasetId; + // Action + const editMetaInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => editMetadataRequestInterceptor(req, tdei_dataset_id, 'metadata.json')) + const versions = await generalAPI.editMetadataForm(metaToUpload, tdei_dataset_id); + // Assert + expect(versions.status).toBe(200); + axios.interceptors.request.eject(editMetaInterceptor); + }, 30000); + + it('POC | Authenticated , When request made, expect to return sucess', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(pocConfiguration); + let metaToUpload = Utility.getMetadataBlob("pathways"); + let tdei_dataset_id = uploadedDatasetId; + // Action + const editMetaInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => editMetadataRequestInterceptor(req, tdei_dataset_id, 'metadata.json')) + const versions = await generalAPI.editMetadataForm(metaToUpload, tdei_dataset_id); + // Assert + expect(versions.status).toBe(200); + axios.interceptors.request.eject(editMetaInterceptor); + }, 30000); + + it('Admin | Authenticated , When request made, expect to return sucess', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(adminConfiguration); + let metaToUpload = Utility.getMetadataBlob("pathways"); + let tdei_dataset_id = uploadedDatasetId; + // Action + const editMetaInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => editMetadataRequestInterceptor(req, tdei_dataset_id, 'metadata.json')) + const versions = await generalAPI.editMetadataForm(metaToUpload, tdei_dataset_id); + // Assert + expect(versions.status).toBe(200); + axios.interceptors.request.eject(editMetaInterceptor); + }, 30000); + + it('Admin | un-authenticated, When request made, should respond with unauthenticated request', async () => { + + // Arrange + let generalAPI = new CommonAPIsApi(Utility.getAdminConfiguration()); + let metaToUpload = Utility.getMetadataBlob("pathways"); + let tdei_dataset_id = uploadedDatasetId; + // Action + const editMetaInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => editMetadataRequestInterceptor(req, tdei_dataset_id, 'metadata.json')) + // Assert + await expect(generalAPI.editMetadataForm(metaToUpload, tdei_dataset_id)).rejects.toMatchObject({ response: { status: 401 } }); + axios.interceptors.request.eject(editMetaInterceptor); + }, 30000); +}); + +describe('Publish the pathways dataset', () => { + jest.retryTimes(1, { logErrorsBeforeRetry: true }); + + it('Admin | When passed with valid input having null valid_from & valid_to metadata, should respond with required field error', async () => { + let pathwaysAPI = new GTFSPathwaysApi(adminConfiguration); + + let publishResponse = pathwaysAPI.publishGtfsPathwaysFile(uploadedDatasetId); + + await expect(publishResponse).rejects.toMatchObject({ response: { status: 400 } }); + }); + + it('Pathways Data Generator | Authenticated , Edit metadata before publishing, should return success', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(dgConfiguration); + let metaToUpload = Utility.getEditMetadataBlob("pathways", { + valid_from: "2021-01-01", + valid_to: "2021-12-31" + }); + let tdei_dataset_id = uploadedDatasetId; + // Action + const editMetaInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => editMetadataRequestInterceptor(req, tdei_dataset_id, 'metadata.json')) + const versions = await generalAPI.editMetadataForm(metaToUpload, tdei_dataset_id); + // Assert + expect(versions.status).toBe(200); + axios.interceptors.request.eject(editMetaInterceptor); + }, 30000); + + it('Pathways Data Generator | Authenticated , When request made with tdei_dataset_id, should return request job id as response', async () => { + + let pathwaysAPI = new GTFSPathwaysApi(dgConfiguration); + let publish = await pathwaysAPI.publishGtfsPathwaysFile(uploadedDatasetId); + expect(publish.status).toBe(202); + expect(publish.data).toBeNumber(); + publishJobId = publish.data; + console.log("publish job_id", publishJobId); + //verify location header + expect(publish.headers.location).toBeDefined(); + expect(publish.headers.location).toContain(`/api/v1/jobs?job_id=${publishJobId}`); + }); + + it('Admin | When passed with already published tdei_dataset_id, should respond with bad request', async () => { + + let pathwaysAPI = new GTFSPathwaysApi(adminConfiguration); + let tdei_dataset_id = apiInput.pathways.published_dataset; + + let publishResponse = pathwaysAPI.publishGtfsPathwaysFile(tdei_dataset_id); + + await expect(publishResponse).rejects.toMatchObject({ response: { status: 400 } }); + }); + + it('Admin | When passed with osw dataset id, should respond with invalid dataset type error', async () => { + let pathwaysAPI = new GTFSPathwaysApi(adminConfiguration); + let tdei_dataset_id = apiInput.osw.pre_release_dataset; + + let publishResponse = pathwaysAPI.publishGtfsPathwaysFile(tdei_dataset_id); + + await expect(publishResponse).rejects.toMatchObject({ response: { status: 400 } }); + }); + + it('Admin | When passed with invalid dataset id, should respond with dataset id not found error', async () => { + let pathwaysAPI = new GTFSPathwaysApi(adminConfiguration); + + let publishResponse = pathwaysAPI.publishGtfsPathwaysFile("invalid_tdei_dataset_id"); + + await expect(publishResponse).rejects.toMatchObject({ response: { status: 404 } }); + }); + + it('Admin | un-authenticated , When request made, should respond with unauthenticated request', async () => { + let pathwaysAPI = new GTFSPathwaysApi(Utility.getAdminConfiguration()); + + let publishResponse = pathwaysAPI.publishGtfsPathwaysFile(uploadedDatasetId); + + await expect(publishResponse).rejects.toMatchObject({ response: { status: 401 } }); + }); + + it('API-Key | Authenticated , When request made, should respond with unauthorized request', async () => { + let pathwaysAPI = new GTFSPathwaysApi(apiKeyConfiguration); + + let publishResponse = pathwaysAPI.publishGtfsPathwaysFile(uploadedDatasetId, { headers: { 'x-api-key': apiKeyConfiguration.apiKey?.toString() } }); + + await expect(publishResponse).rejects.toMatchObject({ response: { status: 403 } }); + }); +}); + +describe('Check publish request job completion status', () => { + jest.retryTimes(1, { logErrorsBeforeRetry: true }); + + it('Pathways Data Generator | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(dgConfiguration); + await new Promise((r) => setTimeout(r, 20000)); + + let uploadStatus = await generalAPI.listJobs(tdei_project_group_id, publishJobId, true); + + expect(uploadStatus.status).toBe(200); + expect(uploadStatus.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + job_id: expect.toBeOneOf([`${publishJobId}`]), + status: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS"]), + progress: expect.objectContaining({ + total_stages: expect.any(Number), + completed_stages: expect.any(Number), + current_state: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "RUNNING"]), + current_stage: expect.any(String) + }) + }) + ]) + ); + }, 25000); + + it('POC | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(pocConfiguration); + let uploadStatus = await generalAPI.listJobs(tdei_project_group_id, publishJobId, true); + expect(uploadStatus.status).toBe(200); + }, 25000); + + + it('Admin | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(adminConfiguration); + let uploadStatus = await generalAPI.listJobs("", publishJobId, true); + expect(uploadStatus.status).toBe(200); + }, 25000); + + it('Admin | un-authenticated , When request made, should respond with unauthenticated request', async () => { + let generalAPI = new CommonAPIsApi(Utility.getAdminConfiguration()); + + let downloadResponse = generalAPI.listJobs("", publishJobId, true); + + await expect(downloadResponse).rejects.toMatchObject({ response: { status: 401 } }); + }); +}); + +describe('Validate-only pathways dataset request', () => { + it('Pathways Data Generator | Authenticated , When request made with valid dataset, should return request job id as response', async () => { + let pathwaysAPI = new GTFSPathwaysApi(dgConfiguration); + let dataset = Utility.getPathwaysBlob(); + try { + const validateInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => validateRequestInterceptor(req, 'pathways-valid.zip')) + const uploadFileResponse = await pathwaysAPI.validateGtfsPathwaysFileForm(dataset); + + expect(uploadFileResponse.status).toBe(202); + expect(uploadFileResponse.data).not.toBeNull(); + validationJobId = uploadFileResponse.data; + console.log("validation job_id", validationJobId); + axios.interceptors.request.eject(validateInterceptor); + //verify location header + expect(uploadFileResponse.headers.location).toBeDefined(); + expect(uploadFileResponse.headers.location).toContain(`/api/v1/jobs?job_id=${validationJobId}`); + } catch (e) { + console.log(e); + } + }, 20000) + + it('Admin | Authenticated , When request made with valid dataset, should return request job id as response', async () => { + let pathwaysAPI = new GTFSPathwaysApi(adminConfiguration); + let dataset = Utility.getPathwaysBlob(); + const validateInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => validateRequestInterceptor(req, 'pathways-valid.zip')) + const uploadFileResponse = await pathwaysAPI.validateGtfsPathwaysFileForm(dataset); + + expect(uploadFileResponse.status).toBe(202); + expect(uploadFileResponse.data).not.toBeNull(); + axios.interceptors.request.eject(validateInterceptor); + }, 20000) + + it('Admin | un-authenticated , When request made with dataset, should return with unauthenticated request', async () => { + let pathwaysAPI = new GTFSPathwaysApi(Utility.getAdminConfiguration()); + let dataset = Utility.getPathwaysBlob(); + + const validateInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => validateRequestInterceptor(req, 'pathways-valid.zip')) + const uploadFileResponse = pathwaysAPI.validateGtfsPathwaysFileForm(dataset); + + await expect(uploadFileResponse).rejects.toMatchObject({ response: { status: 401 } }); + axios.interceptors.request.eject(validateInterceptor); + + }, 20000); + + it('API-Key | Authenticated , When request made with dataset, should return request job id as responset', async () => { + let pathwaysAPI = new GTFSPathwaysApi(apiKeyConfiguration); + let dataset = Utility.getPathwaysBlob(); + const validateInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => validateRequestInterceptor(req, 'pathways-valid.zip')) + const uploadFileResponse = await pathwaysAPI.validateGtfsPathwaysFileForm(dataset, { headers: { 'x-api-key': apiKeyConfiguration.apiKey?.toString() } }); + + expect(uploadFileResponse.status).toBe(202); + expect(uploadFileResponse.data).not.toBeNull(); + axios.interceptors.request.eject(validateInterceptor); + + }, 20000); +}); + +describe('Check validation-only request job completion status', () => { + jest.retryTimes(1, { logErrorsBeforeRetry: true }); + + it('Pathways Data Generator | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(dgConfiguration); + + await new Promise((r) => setTimeout(r, 20000)); + let validateStatus = await generalAPI.listJobs(tdei_project_group_id, validationJobId, true); + + expect(validateStatus.status).toBe(200); + expect(validateStatus.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + job_id: expect.toBeOneOf([`${validationJobId}`]), + status: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS"]), + progress: expect.objectContaining({ + total_stages: expect.any(Number), + completed_stages: expect.any(Number), + current_state: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "RUNNING"]), + current_stage: expect.any(String) + }) + }) + ]) + ); + }, 25000); + + it('POC | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(pocConfiguration); + let uploadStatus = await generalAPI.listJobs(tdei_project_group_id, validationJobId, true); + expect(uploadStatus.status).toBe(200); + }, 25000); + + + it('Admin | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(adminConfiguration); + let uploadStatus = await generalAPI.listJobs("", validationJobId, true); + expect(uploadStatus.status).toBe(200); + }, 25000); + + it('Admin | un-authenticated , When request made, should respond with unauthenticated request', async () => { + let generalAPI = new CommonAPIsApi(Utility.getAdminConfiguration()); + let validateStatusResponse = generalAPI.listJobs("", validationJobId, true); + await expect(validateStatusResponse).rejects.toMatchObject({ response: { status: 401 } }); + }) + +}); + +describe('List pathways versions', () => { + it('Admin | Authenticated , When request made, should respond with pathways version list', async () => { + let pathwaysAPI = new GTFSPathwaysApi(adminConfiguration); + + let versions = await pathwaysAPI.listGtfsPathwaysVersions(); + + expect(versions.status).toBe(200); + expect(Array.isArray(versions.data.versions)).toBe(true); + versions.data.versions?.forEach(version => { + expect(version).toMatchObject({ + version: expect.any(String), + documentation: expect.any(String), + specification: expect.any(String) + }) + }) + }) + it('API-Key | Authenticated , When request made, should respond with pathways version list', async () => { + let pathwaysAPI = new GTFSPathwaysApi(apiKeyConfiguration); + + let versions = await pathwaysAPI.listGtfsPathwaysVersions({ headers: { 'x-api-key': apiKeyConfiguration.apiKey?.toString() } }); + + expect(versions.status).toBe(200); + expect(Array.isArray(versions.data.versions)).toBe(true); + versions.data.versions?.forEach(version => { + expect(version).toMatchObject({ + version: expect.any(String), + documentation: expect.any(String), + specification: expect.any(String) + }) + }) + }) + + it('Admin | un-authenticated , When request made, should respond with unauthenticated request', async () => { + let pathwaysAPI = new GTFSPathwaysApi(Utility.getAdminConfiguration()); + + let versionsResponse = pathwaysAPI.listGtfsPathwaysVersions(); + + await expect(versionsResponse).rejects.toMatchObject({ response: { status: 401 } }); + }) +}); + +describe('Download pathways dataset', () => { + it('Admin | Authenticated , When request made with tdei_dataset_id, should stream the zip file', async () => { + + let pathwaysAPI = new GTFSPathwaysApi(adminConfiguration); + + let response = await pathwaysAPI.getGtfsPathwaysFile(uploadedDatasetId, { responseType: 'arraybuffer' }); + const data: any = response.data; + const contentType = response.headers['content-type']; + const zip = new AdmZip(data); + const entries = zip.getEntries(); + + expect(entries.length).toBeGreaterThanOrEqual(0); + expect(contentType).toBe("application/octet-stream"); + expect(response.data).not.toBeNull(); + expect(response.status).toBe(200); + }, 10000); + + it('Pathways Data Generator | Authenticated , When request made with tdei_dataset_id, should stream the zip file', async () => { + + let pathwaysAPI = new GTFSPathwaysApi(dgConfiguration); + + let response = await pathwaysAPI.getGtfsPathwaysFile(uploadedDatasetId, { responseType: 'arraybuffer' }); + const data: any = response.data; + const contentType = response.headers['content-type']; + const zip = new AdmZip(data); + const entries = zip.getEntries(); + + expect(entries.length).toBeGreaterThanOrEqual(0); + expect(contentType).toBe("application/octet-stream"); + expect(response.data).not.toBeNull(); + expect(response.status).toBe(200); + }, 10000); + + it('API-Key | Authenticated , When request made with tdei_dataset_id, should stream the zip file', async () => { + + let pathwaysAPI = new GTFSPathwaysApi(apiKeyConfiguration); + + let response = await pathwaysAPI.getGtfsPathwaysFile(uploadedDatasetId, { responseType: 'arraybuffer', headers: { 'x-api-key': apiKeyConfiguration.apiKey?.toString() } }); + const data: any = response.data; + const contentType = response.headers['content-type']; + const zip = new AdmZip(data); + const entries = zip.getEntries(); + + expect(entries.length).toBeGreaterThanOrEqual(0); + expect(contentType).toBe("application/octet-stream"); + expect(response.data).not.toBeNull(); + expect(response.status).toBe(200); + }, 10000); + + it('Admin | Authenticated , When request made with invalid tdei_dataset_id, should respond with dataset id not found error', async () => { + + let recordId = 'dummyRecordId'; + let pathwaysAPI = new GTFSPathwaysApi(adminConfiguration); + + let response = pathwaysAPI.getGtfsPathwaysFile(recordId); + + await expect(response).rejects.toMatchObject({ response: { status: 404 } }); + + }) + + it('Admin | un-authenticated , When request made with tdei_dataset_id, should respond with unauthenticated request', async () => { + + let pathwaysAPI = new GTFSPathwaysApi(Utility.getAdminConfiguration()); + + let response = pathwaysAPI.getGtfsPathwaysFile(uploadedDatasetId); + + await expect(response).rejects.toMatchObject({ response: { status: 401 } }); + + }); + + it('Admin | Authenticated , When request made with flex tdei_dataset_id, should respond with dataset type mismatch error', async () => { + + let pathwaysAPI = new GTFSPathwaysApi(adminConfiguration); + + let response = pathwaysAPI.getGtfsPathwaysFile(apiInput.flex.pre_release_dataset); + + await expect(response).rejects.toMatchObject({ response: { status: 400 } }); + + }); +}); \ No newline at end of file diff --git a/src/__tests__/osw.test.ts b/src/__tests__/osw.test.ts index c55a441..62717f6 100644 --- a/src/__tests__/osw.test.ts +++ b/src/__tests__/osw.test.ts @@ -1,85 +1,3019 @@ -import { Configuration, GeneralApi, OSWApi, OswUpload } from "tdei-client"; -import testHarness from "../test-harness.json"; -import axios from "axios"; +import { OSWApi, VersionSpec, CommonAPIsApi, Configuration, JobDetails, JobDetailsJobTypeEnum, JobDetailsStatusEnum } from "tdei-client"; +import axios, { InternalAxiosRequestConfig } from "axios"; import { Utility } from "../utils"; -import path from "path"; -import * as fs from "fs"; +import AdmZip from "adm-zip"; +const { addMsg } = require("jest-html-reporters/helper"); -describe('Tests for OSW', ()=>{ +let apiKeyConfiguration: Configuration = {}; +let pocConfiguration: Configuration = {}; +let dgConfiguration: Configuration = {}; +let adminConfiguration: Configuration = {}; +let flexDgConfiguration: Configuration = {}; +let pathwaysDgConfiguration: Configuration = {}; +let uploadedJobId: string = ''; +let uploadedJobId_PreRelease_poc: string = ''; +let uploadedJobId_PreRelease_admin = ''; +let publishJobId: string = ''; +let confidenceJobId: string = '1'; +let confidenceJobWithSubRegionId: string = '1'; +let convertJobId: string = '1'; +let datasetBboxJobIdOSM: string = '1'; +let datasetBboxJobIdOSW: string = '1'; +let validationJobId: string = '1'; +let uploadedDatasetId: string = '1'; +let uploadedDatasetId_PreRelease_poc: string = '1'; +let uploadedDatasetId_PreRelease_admin: string = '1'; +let tdei_project_group_id = ""; +let service_id = ""; +let qualityMetricJobId = '1'; +const NULL_PARAM = void 0; +let apiInput: any = {}; +let bboxRecordId = ""; - let configuration = new Configuration({ - username: testHarness.system.username, - password: testHarness.system.password, - basePath: testHarness.system.baseUrl - + +const tagQualityRequestInterceptor = (request: InternalAxiosRequestConfig, tdei_dataset_id: string, datasetName: string) => { + if ( + request.url?.includes(`/api/v1/osw/quality-metric/tag/${tdei_dataset_id}`) + ) { + let data = request.data as FormData; + let metaFile = data.get("file") as File; + delete data['file']; + data.set('file', metaFile, datasetName); + } + return request; +}; + +const editMetadataRequestInterceptor = (request: InternalAxiosRequestConfig, tdei_dataset_id: string, datasetName: string) => { + if ( + request.url?.includes(`/api/v1/metadata/${tdei_dataset_id}`) + ) { + let data = request.data as FormData; + let metaFile = data.get("file") as File; + delete data['file']; + data.set('file', metaFile, datasetName); + } + return request; +}; + +const oswUploadRequestInterceptor = (request: InternalAxiosRequestConfig, tdei_project_group_id: string, service_id: string, datasetName: string, changestName: string, metafileName: string) => { + if ( + request.url?.includes(`/api/v1/osw/upload/${tdei_project_group_id}/${service_id}`) + ) { + let data = request.data as FormData; + let datasetFile = data.get("dataset") as File; + let metaFile = data.get('metadata') as File; + let changesetFile = data.get('changeset') as File; + delete data['dataset']; + delete data['metadata']; + delete data['changeset']; + data.set('dataset', datasetFile, datasetName); + data.set('metadata', metaFile, metafileName); + data.set('changeset', changesetFile, changestName); + } + return request; +}; + +const oswValidateRequestInterceptor = (request: InternalAxiosRequestConfig, datasetName: string) => { + if ( + request.url?.includes(`/api/v1/osw/validate`) + ) { + let data = request.data as FormData; + let datasetFile = data.get("dataset") as File; + delete data['dataset']; + data.set('dataset', datasetFile, datasetName); + } + return request; +}; + +const oswConvertRequestInterceptor = (request: InternalAxiosRequestConfig, fileName: string) => { + if ( + request.url?.includes(`/api/v1/osw/convert`) + ) { + let data = request.data as FormData; + let file = data.get("file") as File; + delete data['file']; + data.set('file', file, fileName); + } + return request; +}; + +const oswConfidenceRequestInterceptor = (request: InternalAxiosRequestConfig, tdei_dataset_id: string, fileName: string) => { + if ( + request.url?.includes(`/api/v1/osw/confidence/${tdei_dataset_id}`) + ) { + if (fileName) { + let data = request.data as FormData; + let file = data.get("file") as File; + if (file) { + delete data['file']; + data.set('file', file, fileName); + } + } + } + return request; +}; + +beforeAll(async () => { + let seedData = Utility.seedData; + tdei_project_group_id = seedData.project_group.tdei_project_group_id; + service_id = seedData.services.find(x => x.service_type == "osw")!.tdei_service_id; + adminConfiguration = Utility.getAdminConfiguration(); + apiKeyConfiguration = Utility.getApiKeyConfiguration(); + pocConfiguration = Utility.getPocConfiguration(); + dgConfiguration = Utility.getOSWDataGeneratorConfiguration(); + flexDgConfiguration = Utility.getFlexDataGeneratorConfiguration(); + pathwaysDgConfiguration = Utility.getPathwaysDataGeneratorConfiguration(); + apiInput = Utility.getApiInput(); + bboxRecordId = apiInput.osw.test_dataset; + await authenticate(); +}); + + +afterAll(async () => { +}); + +describe('Upload OSW dataset', () => { + it('OSW Data Generator | Authenticated , When request made with dataset, metadata and changeset file, should return request job id as response', async () => { + let oswAPI = new OSWApi(dgConfiguration); + let metaToUpload = Utility.getMetadataBlob("osw"); + let changesetToUpload = Utility.getChangesetBlob(); + let dataset = Utility.getOSWBlob(); + try { + const uploadInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => oswUploadRequestInterceptor(req, tdei_project_group_id, service_id, 'osw-valid.zip', 'changeset.zip', 'metadata.json')) + const uploadFileResponse = await oswAPI.uploadOswFileForm(dataset, metaToUpload, changesetToUpload, tdei_project_group_id, service_id); + + expect(uploadFileResponse.status).toBe(202); + expect(uploadFileResponse.data).not.toBeNull(); + uploadedJobId = uploadFileResponse.data; + console.log("uploaded tdei_dataset_id", uploadedJobId); + await addMsg({ message: { "OSW Data Generator - uploaded Job Id ": uploadedJobId } }); + axios.interceptors.request.eject(uploadInterceptor); + + //verify location header + expect(uploadFileResponse.headers.location).toBeDefined(); + expect(uploadFileResponse.headers.location).toContain(`/api/v1/jobs?job_id=${uploadedJobId}`); + } catch (e) { + console.log(e); + } + }, 20000); + + it('POC | Authenticated , When request made with dataset, metadata and changeset file, should return request job id as response', async () => { + let oswAPI = new OSWApi(pocConfiguration); + let metaToUpload = Utility.getMetadataBlob("osw"); + let changesetToUpload = Utility.getChangesetBlob(); + let dataset = Utility.getOSWBlob(); + try { + const uploadInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => oswUploadRequestInterceptor(req, tdei_project_group_id, service_id, 'osw-valid.zip', 'changeset.zip', 'metadata.json')) + const uploadFileResponse = await oswAPI.uploadOswFileForm(dataset, metaToUpload, changesetToUpload, tdei_project_group_id, service_id); + + expect(uploadFileResponse.status).toBe(202); + expect(uploadFileResponse.data).not.toBeNull(); + uploadedJobId_PreRelease_poc = uploadFileResponse.data; + console.log("uploaded tdei_dataset_id - pre-release", uploadedJobId_PreRelease_poc); + await addMsg({ message: { "OSW POC - uploaded Job Id ": uploadedJobId_PreRelease_poc } }); + axios.interceptors.request.eject(uploadInterceptor); + } catch (e) { + console.log(e); + } + }, 20000); + + it('Admin | Authenticated , When request made with dataset, metadata and changeset file, should return request job id as response', async () => { + let oswAPI = new OSWApi(adminConfiguration); + let metaToUpload = Utility.getMetadataBlob("osw"); + let changesetToUpload = Utility.getChangesetBlob(); + let dataset = Utility.getOSWBlob(); + try { + const uploadInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => oswUploadRequestInterceptor(req, tdei_project_group_id, service_id, 'osw-valid.zip', 'changeset.zip', 'metadata.json')) + const uploadFileResponse = await oswAPI.uploadOswFileForm(dataset, metaToUpload, changesetToUpload, tdei_project_group_id, service_id); + + expect(uploadFileResponse.status).toBe(202); + uploadedJobId_PreRelease_admin = uploadFileResponse.data; + await addMsg({ message: { "OSW Admin - uploaded Job Id ": uploadFileResponse.data } }); + expect(uploadFileResponse.data).not.toBeNull(); + axios.interceptors.request.eject(uploadInterceptor); + } catch (e) { + console.log(e); + } + }, 20000); + + it('Admin | Authenticated , When request made with dataset and invalid metafile, should return bad request with metadata validation errors', async () => { + let oswAPI = new OSWApi(adminConfiguration); + let metaToUpload = Utility.getInvalidMetadataBlob("osw"); + let changesetToUpload = Utility.getChangesetBlob(); + let dataset = Utility.getOSWBlob(); + try { + const uploadInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => oswUploadRequestInterceptor(req, tdei_project_group_id, service_id, 'osw-valid.zip', 'changeset.zip', 'metadata.json')) + const uploadFileResponse = oswAPI.uploadOswFileForm(dataset, metaToUpload, changesetToUpload, tdei_project_group_id, service_id) + + expect(await uploadFileResponse).rejects.toMatchObject({ response: { status: 400 } }); + + axios.interceptors.request.eject(uploadInterceptor); + } catch (e) { + console.log(e); + } + }, 20000) + + it('Admin | Authenticated , When request made with invalid service id, should return service id not found', async () => { + let oswAPI = new OSWApi(adminConfiguration); + let metaToUpload = Utility.getMetadataBlob("osw"); + let changesetToUpload = Utility.getChangesetBlob(); + let dataset = Utility.getOSWBlob(); + try { + const uploadInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => oswUploadRequestInterceptor(req, tdei_project_group_id, 'invalid_service_id', 'osw-valid.zip', 'changeset.zip', 'metadata.json')) + const uploadFileResponse = oswAPI.uploadOswFileForm(dataset, metaToUpload, changesetToUpload, tdei_project_group_id, 'invalid_service_id') + + expect(await uploadFileResponse).rejects.toMatchObject({ response: { status: 404 } }); + + axios.interceptors.request.eject(uploadInterceptor); + } catch (e) { + console.log(e); + } + }, 20000) + + it('Admin | Authenticated , When request made with invalid project id, should return project id not found', async () => { + let oswAPI = new OSWApi(adminConfiguration); + let metaToUpload = Utility.getMetadataBlob("osw"); + let changesetToUpload = Utility.getChangesetBlob(); + let dataset = Utility.getOSWBlob(); + try { + const uploadInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => oswUploadRequestInterceptor(req, 'invalid_tdei_project_group_id', service_id, 'osw-valid.zip', 'changeset.txt', 'metadata.json')) + const uploadFileResponse = oswAPI.uploadOswFileForm(dataset, metaToUpload, changesetToUpload, 'invalid_tdei_project_group_id', service_id) + + expect(await uploadFileResponse).rejects.toMatchObject({ response: { status: 404 } }); + + axios.interceptors.request.eject(uploadInterceptor); + } catch (e) { + console.log(e); + } + }, 20000) + + it('Admin | Authenticated , When request made with invalid derived dataset id, should return derived dataset id not found', async () => { + let oswAPI = new OSWApi(adminConfiguration); + let metaToUpload = Utility.getMetadataBlob("osw"); + let changesetToUpload = Utility.getChangesetBlob(); + let dataset = Utility.getOSWBlob(); + try { + const uploadInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => oswUploadRequestInterceptor(req, tdei_project_group_id, service_id, 'osw-valid.zip', 'changeset.txt', 'metadata.json')) + const uploadFileResponse = oswAPI.uploadOswFileForm(dataset, metaToUpload, changesetToUpload, tdei_project_group_id, service_id, "InvalidDerivedDatasetId") + + expect(await uploadFileResponse).rejects.toMatchObject({ response: { status: 404 } }); + + axios.interceptors.request.eject(uploadInterceptor); + } catch (e) { + console.log(e); + } + }, 20000) + + it('Flex Data generator | Authenticated , When request made with valid input, should return unauthorized request', async () => { + let oswAPI = new OSWApi(flexDgConfiguration); + let metaToUpload = Utility.getMetadataBlob("osw"); + let changesetToUpload = Utility.getChangesetBlob(); + let dataset = Utility.getOSWBlob(); + try { + const uploadInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => oswUploadRequestInterceptor(req, tdei_project_group_id, service_id, 'osw-valid.zip', 'changeset.txt', 'metadata.json')) + const uploadFileResponse = oswAPI.uploadOswFileForm(dataset, metaToUpload, changesetToUpload, tdei_project_group_id, service_id) + + expect(await uploadFileResponse).rejects.toMatchObject({ response: { status: 403 } }); + + axios.interceptors.request.eject(uploadInterceptor); + } catch (e) { + console.log(e); + } + }, 20000) + + it('Admin | un-authenticated , When request made with dataset, metadata and changeset file, should respond with unauthenticated request', async () => { + let oswAPI = new OSWApi(Utility.getAdminConfiguration()); + let metaToUpload = Utility.getMetadataBlob("osw"); + let changesetToUpload = Utility.getChangesetBlob(); + let dataset = Utility.getOSWBlob(); + + const uploadInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => oswUploadRequestInterceptor(req, tdei_project_group_id, service_id, 'osw-valid.zip', 'changeset.zip', 'metadata.json')) + const uploadFileResponse = oswAPI.uploadOswFileForm(dataset, metaToUpload, changesetToUpload, tdei_project_group_id, service_id) + + await expect(uploadFileResponse).toReject(); + axios.interceptors.request.eject(uploadInterceptor); + + }, 20000) + + it('API-Key | Authenticated , When request made with dataset, metadata and changeset file, should respond with unauthorized request', async () => { + let oswAPI = new OSWApi(apiKeyConfiguration); + let metaToUpload = Utility.getMetadataBlob("osw"); + let changesetToUpload = Utility.getChangesetBlob(); + let dataset = Utility.getOSWBlob(); + + const uploadInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => oswUploadRequestInterceptor(req, tdei_project_group_id, service_id, 'osw-valid.zip', 'changeset.zip', 'metadata.json')) + const uploadFileResponse = oswAPI.uploadOswFileForm(dataset, metaToUpload, changesetToUpload, tdei_project_group_id, service_id, NULL_PARAM, { headers: { 'x-api-key': apiKeyConfiguration.apiKey?.toString() } }) + + await expect(uploadFileResponse).rejects.toMatchObject({ response: { status: 403 } }); + axios.interceptors.request.eject(uploadInterceptor); + + }, 20000) + +}); + +describe('Check upload request job completion status', () => { + jest.retryTimes(1, { logErrorsBeforeRetry: true }); + it('OSW Data Generator | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(dgConfiguration); + await new Promise((r) => setTimeout(r, 190000)); + let uploadStatus = await generalAPI.listJobs(tdei_project_group_id, uploadedJobId, true); + expect(uploadStatus.status).toBe(200); + expect(uploadStatus.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + job_id: expect.toBeOneOf([`${uploadedJobId}`]), + status: expect.toBeOneOf(["COMPLETED"]) + }) + ]) + ); + uploadedDatasetId = uploadStatus.data[0].response_props.tdei_dataset_id; + console.log("uploaded tdei_dataset_id", uploadedDatasetId); + }, 195000); + + it('POC | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(pocConfiguration); + await new Promise((r) => setTimeout(r, 25000)); + let uploadStatus = await generalAPI.listJobs(tdei_project_group_id, uploadedJobId_PreRelease_poc, true); + expect(uploadStatus.status).toBe(200); + uploadedDatasetId_PreRelease_poc = uploadStatus.data[0].response_props.tdei_dataset_id; + expect(uploadStatus.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + job_id: expect.toBeOneOf([`${uploadedJobId_PreRelease_poc}`]), + status: expect.toBeOneOf(["COMPLETED"]) + }) + ]) + ); + }, 30000); + + + it('Admin | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(adminConfiguration); + await new Promise((r) => setTimeout(r, 25000)); + let uploadStatus = await generalAPI.listJobs("", uploadedJobId_PreRelease_admin, true); + expect(uploadStatus.status).toBe(200); + uploadedDatasetId_PreRelease_admin = uploadStatus.data[0].response_props.tdei_dataset_id; + expect(uploadStatus.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + job_id: expect.toBeOneOf([`${uploadedJobId_PreRelease_admin}`]), + status: expect.toBeOneOf(["COMPLETED"]) + }) + ]) + ); + }, 30000); + + it('Admin | un-authenticated , When request made, should respond with unauthenticated request', async () => { + let generalAPI = new CommonAPIsApi(Utility.getAdminConfiguration()); + + let downloadResponse = generalAPI.listJobs("", uploadedJobId, true); + + await expect(downloadResponse).rejects.toMatchObject({ response: { status: 401 } }); + }); + +}); + +describe("Edit Metadata API", () => { + + it('OSW Data Generator | Authenticated , When request made, expect to return sucess', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(dgConfiguration); + let metaToUpload = Utility.getMetadataBlob("osw"); + let tdei_dataset_id = uploadedDatasetId; + // Action + const editMetaInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => editMetadataRequestInterceptor(req, tdei_dataset_id, 'metadata.json')) + const versions = await generalAPI.editMetadataForm(metaToUpload, tdei_dataset_id); + // Assert + expect(versions.status).toBe(200); + axios.interceptors.request.eject(editMetaInterceptor); + }, 30000); + + it('POC | Authenticated , When request made, expect to return sucess', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(pocConfiguration); + let metaToUpload = Utility.getMetadataBlob("osw"); + let tdei_dataset_id = uploadedDatasetId; + // Action + const editMetaInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => editMetadataRequestInterceptor(req, tdei_dataset_id, 'metadata.json')) + const versions = await generalAPI.editMetadataForm(metaToUpload, tdei_dataset_id); + // Assert + expect(versions.status).toBe(200); + axios.interceptors.request.eject(editMetaInterceptor); + }, 30000); + + it('Admin | Authenticated , When request made, expect to return sucess', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(adminConfiguration); + let metaToUpload = Utility.getMetadataBlob("osw"); + let tdei_dataset_id = uploadedDatasetId; + // Action + const editMetaInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => editMetadataRequestInterceptor(req, tdei_dataset_id, 'metadata.json')) + const versions = await generalAPI.editMetadataForm(metaToUpload, tdei_dataset_id); + // Assert + expect(versions.status).toBe(200); + axios.interceptors.request.eject(editMetaInterceptor); + }, 30000); + + it('Admin | Authenticated, When request made with invalid dataset id, should respond with dataset not found error', async () => { + + // Arrange + let generalAPI = new CommonAPIsApi(adminConfiguration); + let metaToUpload = Utility.getMetadataBlob("osw"); + // Action + const editMetaInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => editMetadataRequestInterceptor(req, "invalid_tdei_dataset_id", 'metadata.json')) + // Assert + await expect(generalAPI.editMetadataForm(metaToUpload, "invalid_tdei_dataset_id")).rejects.toMatchObject({ response: { status: 404 } }); + axios.interceptors.request.eject(editMetaInterceptor); + }, 30000); + + it('Admin | Authenticated, When request made with invalid osw schema version, should respond with metadata error', async () => { + + // Arrange + let generalAPI = new CommonAPIsApi(adminConfiguration); + let metaToUpload = Utility.getEditMetadataBlob("osw", { schema_version: "invalid" }); + // Action + const editMetaInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => editMetadataRequestInterceptor(req, uploadedDatasetId, 'metadata.json')) + // Assert + await expect(generalAPI.editMetadataForm(metaToUpload, uploadedDatasetId)).rejects.toMatchObject({ response: { status: 400 } }); + axios.interceptors.request.eject(editMetaInterceptor); + }, 30000); + + it('Admin | un-authenticated, When request made, should respond with unauthenticated request', async () => { + + // Arrange + let generalAPI = new CommonAPIsApi(Utility.getAdminConfiguration()); + let metaToUpload = Utility.getMetadataBlob("osw"); + let tdei_dataset_id = uploadedDatasetId; + // Action + const editMetaInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => editMetadataRequestInterceptor(req, tdei_dataset_id, 'metadata.json')) + // Assert + await expect(generalAPI.editMetadataForm(metaToUpload, tdei_dataset_id)).rejects.toMatchObject({ response: { status: 401 } }); + axios.interceptors.request.eject(editMetaInterceptor); + }, 30000); + + it('API-Key | Authenticated, When request made, should respond with unauthorized request', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(apiKeyConfiguration); + let metaToUpload = Utility.getMetadataBlob("osw"); + let tdei_dataset_id = uploadedDatasetId; + // Action + const editMetaInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => editMetadataRequestInterceptor(req, tdei_dataset_id, 'metadata.json')) + // Assert + await expect(generalAPI.editMetadataForm(metaToUpload, tdei_dataset_id, { headers: { 'x-api-key': apiKeyConfiguration.apiKey?.toString() } })).rejects.toMatchObject({ response: { status: 403 } }); + axios.interceptors.request.eject(editMetaInterceptor); + }, 30000); +}); + +let datasetInclineTagJobId = '1'; +describe('Dataset Incline Tag Request', () => { + + it('Admin | Authenticated , When request made with valid dataset, should return request job id as response', async () => { + let oswAPI = new OSWApi(adminConfiguration); + let inclineRequest = await oswAPI.datasetTagIncline(uploadedDatasetId_PreRelease_admin); + + expect(inclineRequest.status).toBe(202); + expect(inclineRequest.data).toBeNumber(); + datasetInclineTagJobId = inclineRequest.data!; + + //verify location header + expect(inclineRequest.headers.location).toBeDefined(); + expect(inclineRequest.headers.location).toContain(`/api/v1/jobs?job_id=${datasetInclineTagJobId}`); + }); + + it('Admin | authenticated , When request made with invalid dataset, should return with dataset not found error', async () => { + let oswAPI = new OSWApi(adminConfiguration); + + let inclineRequest = oswAPI.datasetTagIncline('invalid_dataset_id'); + + await expect(inclineRequest).rejects.toMatchObject({ response: { status: 404 } }); + }); + + it('Admin | authenticated , When request made with empty source dataset, should return with dataset not found error', async () => { + + let oswAPI = new OSWApi(adminConfiguration); + + let inclineRequest = oswAPI.datasetTagIncline(" "); + + await expect(inclineRequest).rejects.toMatchObject({ response: { status: 404 } }); + }); + + it('Admin | un-authenticated , When request made with dataset, should return with unauthenticated request', async () => { + let oswAPI = new OSWApi(Utility.getAdminConfiguration()); + + let inclineRequest = oswAPI.datasetTagIncline(uploadedDatasetId_PreRelease_admin); + + await expect(inclineRequest).rejects.toMatchObject({ response: { status: 401 } }); + }); + + it('API-Key | Authenticated , When request made with dataset, should return with unauthorized request', async () => { + let oswAPI = new OSWApi(apiKeyConfiguration); + + let inclineRequest = oswAPI.datasetTagIncline(uploadedDatasetId_PreRelease_admin, { headers: { 'x-api-key': apiKeyConfiguration.apiKey?.toString() } }); + + await expect(inclineRequest).rejects.toMatchObject({ response: { status: 403 } }); + }); +}); + +describe('Check dataset-incline request job running status', () => { + jest.retryTimes(1, { logErrorsBeforeRetry: true }); + it('Admin | Authenticated, When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(adminConfiguration); + await new Promise((r) => setTimeout(r, 40000)); + let formatStatus = await generalAPI.listJobs('', datasetInclineTagJobId, true); + + expect(formatStatus.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + job_id: expect.toBeOneOf([`${datasetInclineTagJobId}`]), + status: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "RUNNING", "FAILED"]), + progress: expect.objectContaining({ + total_stages: expect.any(Number), + completed_stages: expect.any(Number), + current_stage: expect.any(String) + }) + }) + ]) + ); + }, 45000); + + it('Admin | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(adminConfiguration); + let uploadStatus = await generalAPI.listJobs('', datasetInclineTagJobId, true); + expect(uploadStatus.status).toBe(200); + }, 25000); + + it('Admin | un-authenticated , When request made, should respond with unauthenticated request', async () => { + let generalAPI = new CommonAPIsApi(Utility.getAdminConfiguration()); + + let bboxStatusResponse = generalAPI.listJobs('', datasetInclineTagJobId, true); + + await expect(bboxStatusResponse).rejects.toMatchObject({ response: { status: 401 } }); + }); + +}); + +describe('Download Incline request file', () => { + + // it('Admin | Authenticated , When request made with tdei_dataset_id, should stream the zip file', async () => { + // let generalAPI = new CommonAPIsApi(adminConfiguration); + // await new Promise((r) => setTimeout(r, 10000)); + // + // let response = await generalAPI.jobDownload(datasetInclineTagJobId, { responseType: 'arraybuffer' }); + // const data: any = response.data; + // const contentType = response.headers['content-type']; + // + // expect(contentType).toBeOneOf(["application/xml", "application/zip"]); + // expect(response.data).not.toBeNull(); + // expect(response.status).toBe(200); + // if (contentType === "application/zip") { + // const zip = new AdmZip(data); + // const entries = zip.getEntries(); + // expect(entries.length).toBeGreaterThanOrEqual(1); + // } + // }, 20000); + + it('Admin | un-authenticated , When request made with tdei_dataset_id, should respond with unauthenticated request', async () => { + let generalAPI = new CommonAPIsApi(Utility.getAdminConfiguration()); + + let downloadResponse = generalAPI.jobDownload(datasetInclineTagJobId); + + await expect(downloadResponse).rejects.toMatchObject({ response: { status: 401 } }); + }); +}); + +describe('Publish the OSW dataset', () => { + it('Admin | When passed with valid input having null valid_from & valid_to metadata, should respond with required field error', async () => { + let oswAPI = new OSWApi(adminConfiguration); + + let publishResponse = oswAPI.publishOswFile(uploadedDatasetId); + + await expect(publishResponse).rejects.toMatchObject({ response: { status: 400 } }); + }); + + it('OSW Data Generator | Authenticated , Edit metadata before publishing, should return success', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(dgConfiguration); + let metaToUpload = Utility.getEditMetadataBlob("osw", { + valid_from: "2021-01-01", + valid_to: "2021-12-31" + }); + let tdei_dataset_id = uploadedDatasetId; + // Action + const editMetaInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => editMetadataRequestInterceptor(req, tdei_dataset_id, 'metadata.json')) + const versions = await generalAPI.editMetadataForm(metaToUpload, tdei_dataset_id); + // Assert + expect(versions.status).toBe(200); + axios.interceptors.request.eject(editMetaInterceptor); + }, 30000); + + it('OSW Data Generator | Authenticated , When request made with tdei_dataset_id, should return request job id as response', async () => { + + let oswAPI = new OSWApi(dgConfiguration); + let publishOsw = await oswAPI.publishOswFile(uploadedDatasetId); + expect(publishOsw.status).toBe(202); + expect(publishOsw.data).toBeNumber(); + publishJobId = publishOsw.data; + await addMsg({ message: { "OSW Data Generator - publish Job Id ": publishJobId } }); + console.log("publish job_id", publishJobId); + //verify location header + expect(publishOsw.headers.location).toBeDefined(); + expect(publishOsw.headers.location).toContain(`/api/v1/jobs?job_id=${publishJobId}`); + }); + + it('OSW Data Generator | Authenticated , Pre-release dataset , edit metadata before publishing, should return success', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(dgConfiguration); + let metaToUpload = Utility.getEditMetadataBlob("osw", { + valid_from: "2021-01-01", + valid_to: "2021-12-31" + }); + let tdei_dataset_id = uploadedDatasetId_PreRelease_admin; + // Action + const editMetaInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => editMetadataRequestInterceptor(req, tdei_dataset_id, 'metadata.json')) + const versions = await generalAPI.editMetadataForm(metaToUpload, tdei_dataset_id); + // Assert + expect(versions.status).toBe(200); + axios.interceptors.request.eject(editMetaInterceptor); + }, 30000); + + it('Admin | Authenticated , When request made with tdei_dataset_id, should return request job id as response', async () => { + + let oswAPI = new OSWApi(adminConfiguration); + let publishOsw = await oswAPI.publishOswFile(uploadedDatasetId_PreRelease_admin); + await addMsg({ message: { "OSW Admin - publish Job Id ": publishOsw.data } }); + expect(publishOsw.status).toBe(202); + expect(publishOsw.data).toBeNumber(); + }); + + it('When passed with already published tdei_dataset_id, should respond with bad request', async () => { + + let oswAPI = new OSWApi(adminConfiguration); + let tdei_dataset_id = apiInput.osw.published_dataset; + + let publishOswResponse = oswAPI.publishOswFile(tdei_dataset_id); + + await expect(publishOswResponse).rejects.toMatchObject({ response: { status: 400 } }); + }); + + it('When passed with flex tdei_dataset_id, should respond dataset data type mismatch error', async () => { + + let oswAPI = new OSWApi(adminConfiguration); + + let publishOswResponse = oswAPI.publishOswFile(apiInput.flex.pre_release_dataset); + + await expect(publishOswResponse).rejects.toMatchObject({ response: { status: 400 } }); + }); + + it('When passed with invalid tdei_dataset_id, should respond with dataset id not found error', async () => { + + let oswAPI = new OSWApi(adminConfiguration); + + let publishOswResponse = oswAPI.publishOswFile("invalid_tdei_dataset_id"); + + await expect(publishOswResponse).rejects.toMatchObject({ response: { status: 404 } }); + }); + + it('Admin | un-authenticated , When request made, should respond with unauthenticated request', async () => { + let oswAPI = new OSWApi(Utility.getAdminConfiguration()); + + let publishOswResponse = oswAPI.publishOswFile(uploadedDatasetId); + + await expect(publishOswResponse).rejects.toMatchObject({ response: { status: 401 } }); + }); + + it('API-Key | Authenticated , When request made, should respond with unauthorized request', async () => { + let oswAPI = new OSWApi(Utility.getAdminConfiguration()); + + let publishOswResponse = oswAPI.publishOswFile(uploadedDatasetId, { headers: { 'x-api-key': apiKeyConfiguration.apiKey?.toString() } }); + + await expect(publishOswResponse).rejects.toMatchObject({ response: { status: 403 } }); + }); +}); + +describe('Check publish request job running status', () => { + jest.retryTimes(1, { logErrorsBeforeRetry: true }); + it('OSW Data Generaror | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(dgConfiguration); + await new Promise((r) => setTimeout(r, 40000)); + + let uploadStatus = await generalAPI.listJobs(tdei_project_group_id, publishJobId, true, NULL_PARAM, NULL_PARAM); + + expect(uploadStatus.status).toBe(200); + expect(uploadStatus.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + job_id: expect.toBeOneOf([`${publishJobId}`]), + status: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "RUNNING"]) + }) + ]) + ); + }, 45000); + + it('POC | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(pocConfiguration); + let uploadStatus = await generalAPI.listJobs(tdei_project_group_id, publishJobId, true); + expect(uploadStatus.status).toBe(200); + }, 25000); + + + it('Admin | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(adminConfiguration); + let uploadStatus = await generalAPI.listJobs("", publishJobId, true); + expect(uploadStatus.status).toBe(200); + }, 25000); + + it('Admin | un-authenticated , When request made, should respond with unauthenticated request', async () => { + let generalAPI = new CommonAPIsApi(Utility.getAdminConfiguration()); + + let downloadResponse = generalAPI.listJobs("", publishJobId, true); + + await expect(downloadResponse).rejects.toMatchObject({ response: { status: 401 } }); + }); +}); + +describe('Validate-only OSW dataset request', () => { + it('OSW Data Generator | Authenticated , When request made with valid dataset, should return request job id as response', async () => { + let oswAPI = new OSWApi(dgConfiguration); + let dataset = Utility.getOSWBlob(); + try { + const validateInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => oswValidateRequestInterceptor(req, 'osw-valid.zip')) + const validateFileResponse = await oswAPI.validateOswFileForm(dataset); + + expect(validateFileResponse.status).toBe(202); + expect(validateFileResponse.data).not.toBeNull(); + validationJobId = validateFileResponse.data; + console.log("validation job_id", validationJobId); + axios.interceptors.request.eject(validateInterceptor); + + //verify location header + expect(validateFileResponse.headers.location).toBeDefined(); + expect(validateFileResponse.headers.location).toContain(`/api/v1/jobs?job_id=${validationJobId}`); + } catch (e) { + console.log(e); + } + }, 20000); + + it('POC | Authenticated , When request made with valid dataset, should return request job id as response', async () => { + let oswAPI = new OSWApi(pocConfiguration); + let dataset = Utility.getOSWBlob(); + try { + const validateInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => oswValidateRequestInterceptor(req, 'osw-valid.zip')) + const uploadFileResponse = await oswAPI.validateOswFileForm(dataset); + + expect(uploadFileResponse.status).toBe(202); + expect(uploadFileResponse.data).not.toBeNull(); + axios.interceptors.request.eject(validateInterceptor); + } catch (e) { + console.log(e); + } + }, 20000) + + it('Admin | Authenticated , When request made with valid dataset, should return request job id as response', async () => { + let oswAPI = new OSWApi(adminConfiguration); + let dataset = Utility.getOSWBlob(); + const validateInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => oswValidateRequestInterceptor(req, 'osw-valid.zip')) + const uploadFileResponse = await oswAPI.validateOswFileForm(dataset); + + expect(uploadFileResponse.status).toBe(202); + expect(uploadFileResponse.data).not.toBeNull(); + axios.interceptors.request.eject(validateInterceptor); + + }, 20000) + + it('Admin | un-authenticated , When request made with dataset, should return with unauthenticated request', async () => { + let oswAPI = new OSWApi(Utility.getAdminConfiguration()); + let dataset = Utility.getOSWBlob(); + + const validateInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => oswValidateRequestInterceptor(req, 'osw-valid.zip')) + const uploadFileResponse = oswAPI.validateOswFileForm(dataset); + + await expect(uploadFileResponse).rejects.toMatchObject({ response: { status: 401 } }); + axios.interceptors.request.eject(validateInterceptor); + + }, 20000); + + it('API-Key | Authenticated , When request made with dataset, should return request job id as response', async () => { + let oswAPI = new OSWApi(apiKeyConfiguration); + let dataset = Utility.getOSWBlob(); + const validateInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => oswValidateRequestInterceptor(req, 'osw-valid.zip')) + const uploadFileResponse = await oswAPI.validateOswFileForm(dataset, { headers: { 'x-api-key': apiKeyConfiguration.apiKey?.toString() } }); + + expect(uploadFileResponse.status).toBe(202); + expect(uploadFileResponse.data).not.toBeNull(); + axios.interceptors.request.eject(validateInterceptor); + }, 20000); + +}); + +describe('Check validation-only request job running status', () => { + jest.retryTimes(1, { logErrorsBeforeRetry: true }); + it('OSW Data Generator | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(dgConfiguration); + + await new Promise((r) => setTimeout(r, 90000)); + let validateStatus = await generalAPI.listJobs(tdei_project_group_id, validationJobId, true); + + expect(validateStatus.status).toBe(200); + expect(validateStatus.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + job_id: expect.toBeOneOf([`${validationJobId}`]), + status: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "RUNNING"]) + }) + ]) + ); + }, 95000); + + it('POC | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(pocConfiguration); + let uploadStatus = await generalAPI.listJobs(tdei_project_group_id, validationJobId, true); + expect(uploadStatus.status).toBe(200); + }, 25000); + + + it('Admin | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(adminConfiguration); + let uploadStatus = await generalAPI.listJobs("", validationJobId, true); + expect(uploadStatus.status).toBe(200); + }, 25000); + + it('Admin | un-authenticated , When request made, should respond with unauthenticated request', async () => { + let generalAPI = new CommonAPIsApi(Utility.getAdminConfiguration()); + let validateStatusResponse = generalAPI.listJobs("", validationJobId, true); + await expect(validateStatusResponse).rejects.toMatchObject({ response: { status: 401 } }); + }); +}); + +describe('Calculate dataset confidence request', () => { + it('OSW Data Generator | Authenticated , When request made with invalid tdei_dataset_id, should respond with bad request', async () => { + let oswAPI = new OSWApi(dgConfiguration); + + let calculateConfidence = oswAPI.oswConfidenceCalculateForm("dummytdeirecordid"); + + await expect(calculateConfidence).rejects.toMatchObject({ response: { status: 404 } }); + }); + + it('OSW Data Generator | Authenticated , When request made, should respond request job id as response', async () => { + let oswAPI = new OSWApi(dgConfiguration); + + let calculateConfidence = await oswAPI.oswConfidenceCalculateForm(uploadedDatasetId); + + expect(calculateConfidence.status).toBe(202); + + expect(calculateConfidence.data).toBeNumber(); + + confidenceJobId = calculateConfidence.data; + console.log("confidence job_id", confidenceJobId); + //verify location header + expect(calculateConfidence.headers.location).toBeDefined(); + expect(calculateConfidence.headers.location).toContain(`/api/v1/jobs?job_id=${confidenceJobId}`); + }); + + it('OSW Data Generator | Authenticated , When request made with sub-region, should respond request job id as response', async () => { + let oswAPI = new OSWApi(dgConfiguration); + + const confidenceInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => oswConfidenceRequestInterceptor(req, uploadedDatasetId, 'subregion.geojson')) + let calculateConfidence = await oswAPI.oswConfidenceCalculateForm(uploadedDatasetId, Utility.getOSWSubRegionBlob()); + + expect(calculateConfidence.status).toBe(202); + + expect(calculateConfidence.data).toBeNumber(); + + confidenceJobWithSubRegionId = calculateConfidence.data; + console.log("confidence with sub-region job_id", confidenceJobWithSubRegionId); + axios.interceptors.request.eject(confidenceInterceptor); + }); + + it('POC | Authenticated , When request made, should respond request job id as response', async () => { + let oswAPI = new OSWApi(pocConfiguration); + + let calculateConfidence = await oswAPI.oswConfidenceCalculateForm(uploadedDatasetId); + + expect(calculateConfidence.status).toBe(202); + + expect(calculateConfidence.data).toBeNumber(); + }); + + it('Admin | Authenticated , When request made, should respond request job id as response', async () => { + let oswAPI = new OSWApi(adminConfiguration); + + let calculateConfidence = await oswAPI.oswConfidenceCalculateForm(uploadedDatasetId); + + expect(calculateConfidence.status).toBe(202); + + expect(calculateConfidence.data).toBeNumber(); + }); + + it('Admin | Authenticated , When request made with invalid sub-region file, should respond with bad request', async () => { + let oswAPI = new OSWApi(adminConfiguration); + + let calculateConfidenceResponse = oswAPI.oswConfidenceCalculateForm(uploadedDatasetId, Utility.getOSWInvalidSubRegionBlob()); + + await expect(calculateConfidenceResponse).rejects.toMatchObject({ response: { status: 400 } }); + }) + + it('Admin | Authenticated , When request made with invalid sub-region file type zip , should respond with bad request', async () => { + let oswAPI = new OSWApi(adminConfiguration); + + let calculateConfidenceResponse = oswAPI.oswConfidenceCalculateForm(uploadedDatasetId, Utility.getOSWBlob()); + + await expect(calculateConfidenceResponse).rejects.toMatchObject({ response: { status: 400 } }); + }) + + it('Admin | Authenticated , When request made with invalid dataset id, should respond with Dataset not found error', async () => { + let oswAPI = new OSWApi(adminConfiguration); + + let calculateConfidenceResponse = oswAPI.oswConfidenceCalculateForm("Invalid_uploadedDatasetId"); + + await expect(calculateConfidenceResponse).rejects.toMatchObject({ response: { status: 404 } }); + }) + + it('Admin | Authenticated , When request made with flex dataset id, should respond with Dataset type mismatch error', async () => { + let oswAPI = new OSWApi(adminConfiguration); + + let calculateConfidenceResponse = oswAPI.oswConfidenceCalculateForm(apiInput.flex.pre_release_dataset); + + await expect(calculateConfidenceResponse).rejects.toMatchObject({ response: { status: 400 } }); + }) + + it('Admin | un-authenticated , When request made, should respond with unauthenticated request', async () => { + let oswAPI = new OSWApi(Utility.getAdminConfiguration()); + + let calculateConfidenceResponse = oswAPI.oswConfidenceCalculateForm(uploadedDatasetId); + + await expect(calculateConfidenceResponse).rejects.toMatchObject({ response: { status: 401 } }); + }) + + it('API-Key | Authenticated , When request made, should respond request job id as response', async () => { + let oswAPI = new OSWApi(apiKeyConfiguration); + + let calculateConfidence = await oswAPI.oswConfidenceCalculateForm(uploadedDatasetId); + + expect(calculateConfidence.status).toBe(202); + + expect(calculateConfidence.data).toBeNumber(); + }) +}); + +describe('Check confidence request job running status', () => { + jest.retryTimes(1, { logErrorsBeforeRetry: true }); + + it('OSW Data Generator | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(dgConfiguration); + await new Promise((r) => setTimeout(r, 10000)); + let confidenceStatus = await generalAPI.listJobs(tdei_project_group_id, confidenceJobId.toString(), true); + + expect(confidenceStatus.status).toBe(200); + + expect(confidenceStatus.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + job_id: expect.toBeOneOf([`${confidenceJobId}`]), + status: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "RUNNING"]), + progress: expect.objectContaining({ + total_stages: expect.any(Number), + completed_stages: expect.any(Number), + current_state: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "RUNNING"]), + current_stage: expect.any(String) + }) + }) + ]) + ); + }, 15000); + + it('OSW Data Generator | Authenticated , When request made to check confidence with sub-region request, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(dgConfiguration); + await new Promise((r) => setTimeout(r, 10000)); + let confidenceStatus = await generalAPI.listJobs(tdei_project_group_id, confidenceJobWithSubRegionId.toString(), true); + + expect(confidenceStatus.status).toBe(200); + + expect(confidenceStatus.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + job_id: expect.toBeOneOf([`${confidenceJobWithSubRegionId}`]), + status: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "RUNNING"]), + progress: expect.objectContaining({ + total_stages: expect.any(Number), + completed_stages: expect.any(Number), + current_state: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "RUNNING"]), + current_stage: expect.any(String) + }) + }) + ]) + ); + }, 15000); + + it('POC | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(pocConfiguration); + let uploadStatus = await generalAPI.listJobs(tdei_project_group_id, confidenceJobId, true); + expect(uploadStatus.status).toBe(200); + }, 25000); + + + it('Admin | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(adminConfiguration); + let uploadStatus = await generalAPI.listJobs("", confidenceJobId, true); + expect(uploadStatus.status).toBe(200); + }, 25000); + + it('Admin | un-authenticated , When request made, should respond with unauthenticated request', async () => { + let generalAPI = new CommonAPIsApi(Utility.getAdminConfiguration()); + let confidenceStatusResponse = generalAPI.listJobs("", confidenceJobId, true); + + await expect(confidenceStatusResponse).rejects.toMatchObject({ response: { status: 401 } }); + }); +}); + +describe('List OSW Versions', () => { + it('API-Key | Authenticated , When request made, should respond with OSW version list', async () => { + let oswAPI = new OSWApi(apiKeyConfiguration); + + let oswVersions = await oswAPI.listOswVersions({ headers: { 'x-api-key': apiKeyConfiguration.apiKey?.toString() } }); + + expect(oswVersions.status).toBe(200); + expect(Array.isArray(oswVersions.data.versions)).toBe(true); + oswVersions.data.versions?.forEach(version => { + expect(version).toMatchObject({ + version: expect.any(String), + documentation: expect.any(String), + specification: expect.any(String) + }) + }) + }) + + it('Admin | un-authenticated , When request made, should respond with unauthenticated request', async () => { + let oswAPI = new OSWApi(Utility.getAdminConfiguration()); + + let oswVersionsResponse = oswAPI.listOswVersions(); + + await expect(oswVersionsResponse).rejects.toMatchObject({ response: { status: 401 } }); + }) +}); + +describe('Convert dataset request', () => { + it('OSW Data Generator | Authenticated , When request made with valid dataset, should return request job id as response', async () => { + let oswAPI = new OSWApi(dgConfiguration); + let oswBlob = Utility.getOSWBlob(); + + const convertInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => oswConvertRequestInterceptor(req, 'osw-valid.zip')) + let formatResponse = await oswAPI.oswOnDemandFormatForm(oswBlob, "osw", "osm"); + + expect(formatResponse.status).toBe(202); + expect(formatResponse.data).toBeNumber(); + convertJobId = formatResponse.data!; + console.log("convert job_id", convertJobId); + axios.interceptors.request.eject(convertInterceptor); + //verify location header + expect(formatResponse.headers.location).toBeDefined(); + expect(formatResponse.headers.location).toContain(`/api/v1/jobs?job_id=${convertJobId}`); + }); + + it('POC | Authenticated , When request made with valid dataset, should return request job id as response', async () => { + let oswAPI = new OSWApi(pocConfiguration); + let oswBlob = Utility.getOSWBlob(); + + const convertInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => oswConvertRequestInterceptor(req, 'osw-valid.zip')) + let formatResponse = await oswAPI.oswOnDemandFormatForm(oswBlob, "osw", "osm"); + + expect(formatResponse.status).toBe(202); + expect(formatResponse.data).toBeNumber(); + axios.interceptors.request.eject(convertInterceptor); + }); + + it('Admin | Authenticated , When request made with valid dataset, should return request job id as response', async () => { + let oswAPI = new OSWApi(adminConfiguration); + let oswBlob = Utility.getOSWBlob(); + + const convertInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => oswConvertRequestInterceptor(req, 'osw-valid.zip')) + let formatResponse = await oswAPI.oswOnDemandFormatForm(oswBlob, "osw", "osm"); + + expect(formatResponse.status).toBe(202); + expect(formatResponse.data).toBeNumber(); + axios.interceptors.request.eject(convertInterceptor); + }); + + it('Admin | Authenticated , When request made with dataset with same source=target output, should return with bad request', async () => { + let oswAPI = new OSWApi(adminConfiguration); + let oswBlob = Utility.getOSWBlob(); + + const convertInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => oswConvertRequestInterceptor(req, 'osw-valid.zip')) + let formatResponse = oswAPI.oswOnDemandFormatForm(oswBlob, "osw", "osw"); + + await expect(formatResponse).rejects.toMatchObject({ response: { status: 400 } }); + axios.interceptors.request.eject(convertInterceptor); + }); + + it('Admin | Authenticated , When request made with dataset with invalid source, should return with bad request', async () => { + let oswAPI = new OSWApi(adminConfiguration); + let oswBlob = Utility.getOSWBlob(); + + const convertInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => oswConvertRequestInterceptor(req, 'osw-valid.zip')) + let formatResponse = oswAPI.oswOnDemandFormatForm(oswBlob, "osw_invalid", "osm"); + + await expect(formatResponse).rejects.toMatchObject({ response: { status: 400 } }); + axios.interceptors.request.eject(convertInterceptor); + }); + + it('Admin | Authenticated , When request made with dataset with invalid target, should return with bad request', async () => { + let oswAPI = new OSWApi(adminConfiguration); + let oswBlob = Utility.getOSWBlob(); + + const convertInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => oswConvertRequestInterceptor(req, 'osw-valid.zip')) + let formatResponse = oswAPI.oswOnDemandFormatForm(oswBlob, "osw", "osm_invalid"); + + await expect(formatResponse).rejects.toMatchObject({ response: { status: 400 } }); + axios.interceptors.request.eject(convertInterceptor); + }); + + it('Admin | Authenticated , When request made with unsupported geojson extension dataset, should return with dataset file type error', async () => { + let oswAPI = new OSWApi(adminConfiguration); + let oswBlob = Utility.getMetadataBlob("osw"); + + const convertInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => oswConvertRequestInterceptor(req, 'osw-valid.geojson')) + let formatResponse = oswAPI.oswOnDemandFormatForm(oswBlob, "osw", "osm"); + + await expect(formatResponse).rejects.toMatchObject({ response: { status: 400 } }); + axios.interceptors.request.eject(convertInterceptor); + }); + + it('Admin | un-authenticated , When request made with dataset, should return with unauthenticated request', async () => { + let oswAPI = new OSWApi(Utility.getAdminConfiguration()); + let oswBlob = Utility.getOSWBlob(); + + const convertInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => oswConvertRequestInterceptor(req, 'osw-valid.zip')) + let formatResponse = oswAPI.oswOnDemandFormatForm(oswBlob, "osw", "osm"); + + await expect(formatResponse).rejects.toMatchObject({ response: { status: 401 } }); + axios.interceptors.request.eject(convertInterceptor); + }); + + it('API-Key | Authenticated , When request made with dataset, should return request job id as response', async () => { + let oswAPI = new OSWApi(apiKeyConfiguration); + let oswBlob = Utility.getOSWBlob(); + + const convertInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => oswConvertRequestInterceptor(req, 'osw-valid.zip')) + let formatResponse = await oswAPI.oswOnDemandFormatForm(oswBlob, "osw", "osm", { headers: { 'x-api-key': apiKeyConfiguration.apiKey?.toString() } }); + + expect(formatResponse.status).toBe(202); + expect(formatResponse.data).toBeNumber(); + axios.interceptors.request.eject(convertInterceptor); + }); + +}); + +describe('Check convert request job running status', () => { + jest.retryTimes(1, { logErrorsBeforeRetry: true }); + + it('OSW Data Generator | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(dgConfiguration); + await new Promise((r) => setTimeout(r, 20000)); + + let formatStatus = await generalAPI.listJobs(tdei_project_group_id, convertJobId, true); + + expect(formatStatus.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + job_id: expect.toBeOneOf([`${convertJobId}`]), + status: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "RUNNING"]), + progress: expect.objectContaining({ + total_stages: expect.any(Number), + completed_stages: expect.any(Number), + current_state: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "RUNNING"]), + current_stage: expect.any(String) + }) + }) + ]) + ); + }, 35000); + + it('POC | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(pocConfiguration); + let uploadStatus = await generalAPI.listJobs(tdei_project_group_id, convertJobId, true); + expect(uploadStatus.status).toBe(200); + }, 25000); + + + it('Admin | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(adminConfiguration); + let uploadStatus = await generalAPI.listJobs("", convertJobId, true); + expect(uploadStatus.status).toBe(200); + }, 25000); + + it('Admin | un-authenticated , When request made, should respond with unauthenticated request', async () => { + let generalAPI = new CommonAPIsApi(Utility.getAdminConfiguration()); + + let formatStatusResponse = generalAPI.listJobs("", convertJobId, true); + + await expect(formatStatusResponse).rejects.toMatchObject({ response: { status: 401 } }); + }); + +}) + +describe('Download converted file', () => { + jest.retryTimes(1, { logErrorsBeforeRetry: true }); + it('OSW Data Generator | Authenticated , When request made with tdei_dataset_id, should stream the zip file', async () => { + let generalAPI = new CommonAPIsApi(dgConfiguration); + await new Promise((r) => setTimeout(r, 20000)); + + let response = await generalAPI.jobDownload(convertJobId, { responseType: 'arraybuffer' }); + const data: any = response.data; + const contentType = response.headers['content-type']; + + expect(contentType).toBeOneOf(["application/xml", "application/zip"]); + expect(response.data).not.toBeNull(); + expect(response.status).toBe(200); + if (contentType === "application/zip") { + const zip = new AdmZip(data); + const entries = zip.getEntries(); + expect(entries.length).toBe(1); + } + }, 30000); + + it('Admin | un-authenticated , When request made, should respond with unauthenticated request', async () => { + let generalAPI = new CommonAPIsApi(Utility.getAdminConfiguration()); + + let downloadResponse = generalAPI.jobDownload(convertJobId); + + await expect(downloadResponse).rejects.toMatchObject({ response: { status: 401 } }); + }); + +}); + +describe('Download OSW File as zip', () => { + it('API-Key | Authenticated , When request made with tdei_dataset_id, should stream the zip file', async () => { + + let oswAPI = new OSWApi(apiKeyConfiguration); + + let response = await oswAPI.getOswFile(uploadedDatasetId, "osw", "latest", { responseType: 'arraybuffer' }); + const data: any = response.data; + const contentType = response.headers['content-type']; + const zip = new AdmZip(data); + const entries = zip.getEntries(); + + expect(entries.length).toBeGreaterThanOrEqual(2); + expect(contentType).toBe("application/octet-stream"); + expect(response.data).not.toBeNull(); + expect(response.status).toBe(200); + }, 10000); + + it('Admin | Authenticated , When request made with invalid file format, should respond with bad request error', async () => { + + let oswAPI = new OSWApi(adminConfiguration); + + let response = oswAPI.getOswFile("42292e88-21b1-448a-b4c1-493fb3346571", "oos"); + + await expect(response).rejects.toMatchObject({ response: { status: 400 } }); + + }); + + it('Admin | Authenticated , When request made with invalid file version, should respond with bad request error', async () => { + + let oswRecordId = 'dummyRecordId'; + let oswAPI = new OSWApi(adminConfiguration); + + let response = oswAPI.getOswFile(oswRecordId, "osm", "dummyVersion"); + + await expect(response).rejects.toMatchObject({ response: { status: 400 } }); + + }); + + it('Admin | Authenticated , When request made with invalid tdei_dataset_id, should respond with dataset id not found error', async () => { + + let oswRecordId = 'dummyRecordId'; + let oswAPI = new OSWApi(adminConfiguration); + + let response = oswAPI.getOswFile(oswRecordId); + + await expect(response).rejects.toMatchObject({ response: { status: 404 } }); + + }); + + it('Admin | Authenticated , When request made with flex tdei_dataset_id, should respond with dataset type mismatch error', async () => { + + let oswAPI = new OSWApi(adminConfiguration); + + let response = oswAPI.getOswFile(apiInput.flex.pre_release_dataset); + + await expect(response).rejects.toMatchObject({ response: { status: 400 } }); + + }); + + it('Admin | un-authenticated , When request made with tdei_dataset_id, should respond with unauthenticated request', async () => { + + let oswAPI = new OSWApi(Utility.getAdminConfiguration()); + + let response = oswAPI.getOswFile(uploadedDatasetId); + + await expect(response).rejects.toMatchObject({ response: { status: 401 } }); + + }); +}); + +describe('Dataset Bbox Request', () => { + it('OSW Data Generator | Authenticated ,[OSM] When request made with valid dataset, should return request job id as response', async () => { + let oswAPI = new OSWApi(dgConfiguration); + + let bboxRequest = await oswAPI.datasetBbox(bboxRecordId, 'osm', [-122.264913, 47.558543, -122.10549, 47.691327]); + + expect(bboxRequest.status).toBe(202); + expect(bboxRequest.data).toBeNumber(); + datasetBboxJobIdOSM = bboxRequest.data!; + //verify location header + expect(bboxRequest.headers.location).toBeDefined(); + expect(bboxRequest.headers.location).toContain(`/api/v1/jobs?job_id=${datasetBboxJobIdOSM}`); + }); + + it('POC | Authenticated ,[OSM] When request made with valid dataset, should return request job id as response', async () => { + let oswAPI = new OSWApi(pocConfiguration); + + let bboxRequest = await oswAPI.datasetBbox(bboxRecordId, 'osm', [-122.264913, 47.558543, -122.10549, 47.691327]); + + expect(bboxRequest.status).toBe(202); + expect(bboxRequest.data).toBeNumber(); + }); + + it('Admin | Authenticated ,[OSM] When request made with valid dataset, should return request job id as response', async () => { + let oswAPI = new OSWApi(adminConfiguration); + + let bboxRequest = await oswAPI.datasetBbox(bboxRecordId, 'osm', [-122.264913, 47.558543, -122.10549, 47.691327]); + + expect(bboxRequest.status).toBe(202); + expect(bboxRequest.data).toBeNumber(); + }); + + + it('API-Key | Authenticated ,[OSM] When request made with dataset, should return request job id as response', async () => { + let oswAPI = new OSWApi(apiKeyConfiguration); + + let bboxRequest = await oswAPI.datasetBbox(bboxRecordId, 'osm', [-122.264913, 47.558543, -122.10549, 47.691327], { headers: { 'x-api-key': apiKeyConfiguration.apiKey?.toString() } }); + + expect(bboxRequest.status).toBe(202); + expect(bboxRequest.data).toBeNumber(); + }); + + it('OSW Data Generator | Authenticated ,[OSW] When request made with valid dataset, should return request job id as response', async () => { + let oswAPI = new OSWApi(dgConfiguration); + + let bboxRequest = await oswAPI.datasetBbox(bboxRecordId, 'osw', [-122.264913, 47.558543, -122.10549, 47.691327]); + + expect(bboxRequest.status).toBe(202); + expect(bboxRequest.data).toBeNumber(); + datasetBboxJobIdOSW = bboxRequest.data!; + console.log("dataset bbox job_id", datasetBboxJobIdOSW); + }); + + it('POC | Authenticated ,[OSW] When request made with valid dataset, should return request job id as response', async () => { + let oswAPI = new OSWApi(pocConfiguration); + + let bboxRequest = await oswAPI.datasetBbox(bboxRecordId, 'osw', [-122.264913, 47.558543, -122.10549, 47.691327]); + + expect(bboxRequest.status).toBe(202); + expect(bboxRequest.data).toBeNumber(); + }); + + it('Admin | Authenticated ,[OSW] When request made with valid dataset, should return request job id as response', async () => { + let oswAPI = new OSWApi(adminConfiguration); + + let bboxRequest = await oswAPI.datasetBbox(bboxRecordId, 'osw', [-122.264913, 47.558543, -122.10549, 47.691327]); + + expect(bboxRequest.status).toBe(202); + expect(bboxRequest.data).toBeNumber(); + }); + + + it('API-Key | Authenticated ,[OSW] When request made with dataset, should return request job id as response', async () => { + let oswAPI = new OSWApi(apiKeyConfiguration); + + let bboxRequest = await oswAPI.datasetBbox(bboxRecordId, 'osw', [-122.264913, 47.558543, -122.10549, 47.691327], { headers: { 'x-api-key': apiKeyConfiguration.apiKey?.toString() } }); + + expect(bboxRequest.status).toBe(202); + expect(bboxRequest.data).toBeNumber(); + }); + + it('Admin | un-authenticated , When request made with dataset, should return with unauthenticated request', async () => { + let oswAPI = new OSWApi(Utility.getAdminConfiguration()); + + let bboxRequest = oswAPI.datasetBbox(bboxRecordId, 'osm', [-122.264913, 47.558543, -122.10549, 47.691327]); + + await expect(bboxRequest).rejects.toMatchObject({ response: { status: 401 } }); + }); + + it('Admin | Authenticated , When request made with invalid dataset, should return with dataset not found error', async () => { + let oswAPI = new OSWApi(adminConfiguration); + + let bboxRequest = oswAPI.datasetBbox("invalid_bboxRecordId", 'osm', [-122.264913, 47.558543, -122.10549, 47.691327]); + + await expect(bboxRequest).rejects.toMatchObject({ response: { status: 404 } }); + }); + + it('Admin | Authenticated , When request made with invalid bbox, should return with invalid bbox error', async () => { + let oswAPI = new OSWApi(adminConfiguration); + + let bboxRequest = oswAPI.datasetBbox(bboxRecordId, 'osm', [47.691327]); + + await expect(bboxRequest).rejects.toMatchObject({ response: { status: 400 } }); + }); + + it('Admin | Authenticated , When request made with flex dataset, should return with dataset type mismatch error error', async () => { + let oswAPI = new OSWApi(adminConfiguration); + + let bboxRequest = oswAPI.datasetBbox(apiInput.flex.pre_release_dataset, 'osm', [-122.264913, 47.558543, -122.10549, 47.691327]); + + await expect(bboxRequest).rejects.toMatchObject({ response: { status: 400 } }); + }); + +}); + +describe('Check dataset-bbox request job running status', () => { + jest.retryTimes(1, { logErrorsBeforeRetry: true }); + it('OSW Data Generator | Authenticated ,[OSM] When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(dgConfiguration); + await new Promise((r) => setTimeout(r, 40000)); + + let formatStatus = await generalAPI.listJobs(tdei_project_group_id, datasetBboxJobIdOSM, true); + + expect(formatStatus.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + job_id: expect.toBeOneOf([`${datasetBboxJobIdOSM}`]), + status: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "RUNNING"]), + progress: expect.objectContaining({ + total_stages: expect.any(Number), + completed_stages: expect.any(Number), + current_state: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "RUNNING"]), + current_stage: expect.any(String) + }) + }) + ]) + ); + }, 45000); + + it('OSW Data Generator | Authenticated , [OSW] When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(dgConfiguration); + await new Promise((r) => setTimeout(r, 40000)); + + let formatStatus = await generalAPI.listJobs(tdei_project_group_id, datasetBboxJobIdOSW, true); + + expect(formatStatus.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + job_id: expect.toBeOneOf([`${datasetBboxJobIdOSW}`]), + status: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "RUNNING"]), + progress: expect.objectContaining({ + total_stages: expect.any(Number), + completed_stages: expect.any(Number), + current_state: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "RUNNING"]), + current_stage: expect.any(String) + }) + }) + ]) + ); + }, 45000); + + it('POC | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(pocConfiguration); + let uploadStatus = await generalAPI.listJobs(tdei_project_group_id, datasetBboxJobIdOSM, true); + expect(uploadStatus.status).toBe(200); + }, 25000); + + + it('Admin | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(adminConfiguration); + let uploadStatus = await generalAPI.listJobs("", datasetBboxJobIdOSM, true); + expect(uploadStatus.status).toBe(200); + }, 25000); + + it('Admin | un-authenticated , When request made, should respond with unauthenticated request', async () => { + let generalAPI = new CommonAPIsApi(Utility.getAdminConfiguration()); + + let bboxStatusResponse = generalAPI.listJobs("", datasetBboxJobIdOSM, true); + + await expect(bboxStatusResponse).rejects.toMatchObject({ response: { status: 401 } }); + }); + +}); + +describe('Download Dataset Bbox request file', () => { + + it('OSW Data Generator | Authenticated , When request made with tdei_dataset_id, should stream the zip file', async () => { + await new Promise((r) => setTimeout(r, 30000)); + let generalAPI = new CommonAPIsApi(dgConfiguration); + + let response = await generalAPI.jobDownload(datasetBboxJobIdOSM, { responseType: 'arraybuffer' }); + const data: any = response.data; + const contentType = response.headers['content-type']; + + expect(contentType).toBeOneOf(["application/xml", "application/zip"]); + expect(response.data).not.toBeNull(); + expect(response.status).toBe(200); + if (contentType === "application/zip") { + const zip = new AdmZip(data); + const entries = zip.getEntries(); + expect(entries.length).toBeGreaterThanOrEqual(1); + } + }, 40000); + + it('Admin | un-authenticated , When request made with tdei_dataset_id, should respond with unauthenticated request', async () => { + let generalAPI = new CommonAPIsApi(Utility.getAdminConfiguration()); + + let downloadResponse = generalAPI.jobDownload(datasetBboxJobIdOSM); + + await expect(downloadResponse).rejects.toMatchObject({ response: { status: 401 } }); + }); + +}); + +let datasetRoadTagJobId = '1'; +describe('Dataset Road Tag Request', () => { + // let datasetTagSourceRecordId = apiInput.osw.test_dataset; + // let datasetTagTargetPublishedRecordId = apiInput.osw.published_dataset;//'762f3533-b18f-470f-8051-1a7988bf80c7'; + + it('OSW Data Generator | Authenticated , When request made with valid dataset, should return request job id as response', async () => { + let oswAPI = new OSWApi(dgConfiguration); + + let roadTagRequest = await oswAPI.datasetTagRoad(apiInput.osw.test_dataset, uploadedDatasetId_PreRelease_poc); + + expect(roadTagRequest.status).toBe(202); + expect(roadTagRequest.data).toBeNumber(); + datasetRoadTagJobId = roadTagRequest.data!; + console.log("dataset road tag job_id", datasetRoadTagJobId); + //verify location header + expect(roadTagRequest.headers.location).toBeDefined(); + expect(roadTagRequest.headers.location).toContain(`/api/v1/jobs?job_id=${datasetRoadTagJobId}`); + }); + + it('Admin | Authenticated , When request made with valid dataset, should return request job id as response', async () => { + let oswAPI = new OSWApi(adminConfiguration); + + let bboxRequest = await oswAPI.datasetTagRoad(apiInput.osw.test_dataset, uploadedDatasetId_PreRelease_poc); + + expect(bboxRequest.status).toBe(202); + expect(bboxRequest.data).toBeNumber(); + }); + + it('POC | Authenticated , When request made with valid dataset, should return request job id as response', async () => { + let oswAPI = new OSWApi(pocConfiguration); + + let bboxRequest = await oswAPI.datasetTagRoad(apiInput.osw.test_dataset, uploadedDatasetId_PreRelease_poc); + + expect(bboxRequest.status).toBe(202); + expect(bboxRequest.data).toBeNumber(); + }); + + it('Admin | authenticated , When request made with publish target dataset, should return with bad request', async () => { + let oswAPI = new OSWApi(adminConfiguration); + + let bboxRequest = oswAPI.datasetTagRoad(apiInput.osw.test_dataset, apiInput.osw.published_dataset); + + await expect(bboxRequest).rejects.toMatchObject({ response: { status: 400 } }); + }); + + it('Admin | authenticated , When request made with invalid source dataset, should return with dataset not found error', async () => { + + let oswAPI = new OSWApi(adminConfiguration); + + let bboxRequest = oswAPI.datasetTagRoad("invalid_source", apiInput.osw.published_dataset); + + await expect(bboxRequest).rejects.toMatchObject({ response: { status: 404 } }); + }); + + it('Admin | authenticated , When request made with invalid target dataset, should return with dataset not found error', async () => { + let oswAPI = new OSWApi(adminConfiguration); + + let bboxRequest = oswAPI.datasetTagRoad(apiInput.osw.test_dataset, "invalid_target"); + + await expect(bboxRequest).rejects.toMatchObject({ response: { status: 404 } }); + }); + + it('Admin | un-authenticated , When request made with dataset, should return with unauthenticated request', async () => { + let oswAPI = new OSWApi(Utility.getAdminConfiguration()); + + let bboxRequest = oswAPI.datasetTagRoad(apiInput.osw.test_dataset, uploadedDatasetId_PreRelease_poc); + + await expect(bboxRequest).rejects.toMatchObject({ response: { status: 401 } }); + }); + + it('API-Key | Authenticated , When request made with dataset, should return with unauthorized request', async () => { + let oswAPI = new OSWApi(apiKeyConfiguration); + + let bboxRequest = oswAPI.datasetTagRoad(apiInput.osw.test_dataset, uploadedDatasetId_PreRelease_poc, { headers: { 'x-api-key': apiKeyConfiguration.apiKey?.toString() } }); + + await expect(bboxRequest).rejects.toMatchObject({ response: { status: 403 } }); + }); + +}); + +describe('Check dataset-road-tag request job completion status', () => { + jest.retryTimes(1, { logErrorsBeforeRetry: true }); + + it('OSW Data Generator | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(dgConfiguration); + await new Promise((r) => setTimeout(r, 50000)); + + let formatStatus = await generalAPI.listJobs(tdei_project_group_id, datasetRoadTagJobId, true); + + expect(formatStatus.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + job_id: expect.toBeOneOf([`${datasetRoadTagJobId}`]), + status: expect.toBeOneOf(["COMPLETED"]) + }) + ]) + ); + }, 55000); + + it('POC | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(pocConfiguration); + let uploadStatus = await generalAPI.listJobs(tdei_project_group_id, datasetRoadTagJobId, true); + expect(uploadStatus.status).toBe(200); + }, 25000); + + + it('Admin | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(adminConfiguration); + let uploadStatus = await generalAPI.listJobs("", datasetRoadTagJobId, true); + expect(uploadStatus.status).toBe(200); + }, 25000); + + it('Admin | un-authenticated , When request made, should respond with unauthenticated request', async () => { + let generalAPI = new CommonAPIsApi(Utility.getAdminConfiguration()); + + let bboxStatusResponse = generalAPI.listJobs("", datasetRoadTagJobId, true); + + await expect(bboxStatusResponse).rejects.toMatchObject({ response: { status: 401 } }); + }); + +}); + +describe('Download Dataset Road Tag request file', () => { + + it('Admin | Authenticated , When request made with tdei_dataset_id, should stream the zip file', async () => { + let generalAPI = new CommonAPIsApi(adminConfiguration); + await new Promise((r) => setTimeout(r, 10000)); + + let response = await generalAPI.jobDownload(datasetBboxJobIdOSW, { responseType: 'arraybuffer' }); + const data: any = response.data; + const contentType = response.headers['content-type']; + + expect(contentType).toBeOneOf(["application/xml", "application/zip"]); + expect(response.data).not.toBeNull(); + expect(response.status).toBe(200); + if (contentType === "application/zip") { + const zip = new AdmZip(data); + const entries = zip.getEntries(); + expect(entries.length).toBeGreaterThanOrEqual(1); + } + }, 20000); + + it('API-Key | Authenticated , When request made with tdei_dataset_id, should stream the zip file', async () => { + let generalAPI = new CommonAPIsApi(apiKeyConfiguration); + + let response = await generalAPI.jobDownload(datasetBboxJobIdOSW, { responseType: 'arraybuffer' }); + const data: any = response.data; + const contentType = response.headers['content-type']; + + expect(contentType).toBeOneOf(["application/xml", "application/zip"]); + expect(response.data).not.toBeNull(); + expect(response.status).toBe(200); + if (contentType === "application/zip") { + const zip = new AdmZip(data); + const entries = zip.getEntries(); + expect(entries.length).toBeGreaterThanOrEqual(1); + } + }, 20000); + + it('Admin | un-authenticated , When request made with tdei_dataset_id, should respond with unauthenticated request', async () => { + let generalAPI = new CommonAPIsApi(Utility.getAdminConfiguration()); + + let downloadResponse = generalAPI.jobDownload(datasetBboxJobIdOSM); + + await expect(downloadResponse).rejects.toMatchObject({ response: { status: 401 } }); + }); + +}); + +let datasetUnionJobId = '1'; +describe('Dataset Union Request', () => { + + it('OSW Data Generator | Authenticated , When request made with valid dataset, should return request job id as response', async () => { + let oswAPI = new OSWApi(dgConfiguration); + + let unionRequest = await oswAPI.oswUnion({ + tdei_dataset_id_one: uploadedDatasetId, + tdei_dataset_id_two: uploadedDatasetId_PreRelease_poc + } + ); + + expect(unionRequest.status).toBe(202); + expect(unionRequest.data).toBeNumber(); + datasetUnionJobId = unionRequest.data!; + console.log("dataset Union job_id", datasetUnionJobId); + //verify location header + expect(unionRequest.headers.location).toBeDefined(); + expect(unionRequest.headers.location).toContain(`/api/v1/jobs?job_id=${datasetUnionJobId}`); + }); + + it('Admin | Authenticated , When request made with valid dataset, should return request job id as response', async () => { + let oswAPI = new OSWApi(adminConfiguration); + + let bboxRequest = await oswAPI.oswUnion({ + tdei_dataset_id_one: uploadedDatasetId, + tdei_dataset_id_two: uploadedDatasetId_PreRelease_poc }); - - beforeAll( async ()=>{ - // console.log('Hello there'); - let generalAPI = new GeneralApi(configuration); - const loginResponse = await generalAPI.authenticate({username:configuration.username,password:configuration.password}); - configuration.baseOptions = { - headers:{ - 'Authorization':'Bearer '+ loginResponse.data.access_token - } - }; - - + + expect(bboxRequest.status).toBe(202); + expect(bboxRequest.data).toBeNumber(); + }); + + it('POC | Authenticated , When request made with valid dataset, should return request job id as response', async () => { + let oswAPI = new OSWApi(pocConfiguration); + + let bboxRequest = await oswAPI.oswUnion({ + tdei_dataset_id_one: uploadedDatasetId, + tdei_dataset_id_two: uploadedDatasetId_PreRelease_poc }); - - it('Should get list of osw versions', async ()=>{ - let oswAPI = new OSWApi(configuration); - const oswVersions = await oswAPI.listOswVersions(); - expect(oswVersions.status).toBe(200); - expect(Array.isArray(oswVersions.data.versions)).toBe(true); + expect(bboxRequest.status).toBe(202); + expect(bboxRequest.data).toBeNumber(); + }); + + it('Admin | authenticated , When request made with invalid left dataset, should return with dataset not found error', async () => { + let oswAPI = new OSWApi(adminConfiguration); + + let bboxRequest = oswAPI.oswUnion({ + tdei_dataset_id_one: "invalid", + tdei_dataset_id_two: uploadedDatasetId }); - - it('Should return list of osw files', async ()=>{ - let oswAPI = new OSWApi(configuration); - const oswFiles = await oswAPI.listOswFiles(); - expect(oswFiles.status).toBe(200); - expect(Array.isArray(oswFiles.data)).toBe(true); + await expect(bboxRequest).rejects.toMatchObject({ response: { status: 404 } }); + }); + + it('Admin | authenticated , When request made with invalid right dataset, should return with dataset not found error', async () => { + let oswAPI = new OSWApi(adminConfiguration); + + let bboxRequest = oswAPI.oswUnion({ + tdei_dataset_id_one: uploadedDatasetId, + tdei_dataset_id_two: "invalid" }); - it('Should be able to upload osw files', async ()=>{ - - let metaToUpload = Utility.getRandomOswUpload(); - // Actual method does not give the results as expected - // So we are writing interceptor - -const uploadInterceptor = axios.interceptors.request.use((x) => { - const data = x.data as FormData; - var file = data.get('file') as File; - data.delete('file'); - data.set('file',file,'abc.zip'); - data.delete('meta'); - data.set('meta',JSON.stringify(metaToUpload)); - return x; - }); - - let fileDir = path.dirname(path.dirname(__dirname)); - let payloadFilePath = path.join(fileDir,'assets/payloads/osw/files/valid.zip'); - let filestream = fs.readFileSync(payloadFilePath); - const blob = new Blob([filestream],{type:'application/zip'}) ; - let oswAPI = new OSWApi(configuration); - // try { - const uploadedFileResponse = await oswAPI.uploadOswFileForm(metaToUpload,blob); - console.log(uploadedFileResponse.data); - expect(uploadedFileResponse.status).toBe(202); - expect(uploadedFileResponse.data).not.toBe(''); - axios.interceptors.request.eject(uploadInterceptor); - // } - // catch (e){ - // // console.log(e); - // if (axios.isAxiosError(e)) { - // console.log(e.response?.data); - // } - // axios.interceptors.request.eject(myInterceptor); - // } + await expect(bboxRequest).rejects.toMatchObject({ response: { status: 404 } }); + }); + + it('Admin | un-authenticated , When request made with dataset, should return with unauthenticated request', async () => { + let oswAPI = new OSWApi(Utility.getAdminConfiguration()); + + let bboxRequest = oswAPI.oswUnion({ + tdei_dataset_id_one: uploadedDatasetId, + tdei_dataset_id_two: uploadedDatasetId_PreRelease_poc }); - + await expect(bboxRequest).rejects.toMatchObject({ response: { status: 401 } }); + }); + + it('API-Key | Authenticated , When request made with dataset, should return request job id as response', async () => { + let oswAPI = new OSWApi(apiKeyConfiguration); + + let bboxRequest = await oswAPI.oswUnion({ + tdei_dataset_id_one: apiInput.osw.test_dataset, + tdei_dataset_id_two: uploadedDatasetId_PreRelease_poc + }, { headers: { 'x-api-key': apiKeyConfiguration.apiKey?.toString() } }); + + expect(bboxRequest.status).toBe(202); + expect(bboxRequest.data).toBeNumber(); + }); + +}); + +describe('Check dataset union request job completion status', () => { + jest.retryTimes(1, { logErrorsBeforeRetry: true }); + + it('OSW Data Generator | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(dgConfiguration); + await new Promise((r) => setTimeout(r, 120000)); + + let formatStatus = await generalAPI.listJobs(tdei_project_group_id, datasetUnionJobId, true); + + expect(formatStatus.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + job_id: expect.toBeOneOf([`${datasetUnionJobId}`]), + status: expect.toBeOneOf(["COMPLETED"]) + }) + ]) + ); + }, 130000); + + it('POC | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(pocConfiguration); + let uploadStatus = await generalAPI.listJobs(tdei_project_group_id, datasetUnionJobId, true); + expect(uploadStatus.status).toBe(200); + }, 25000); + + + it('Admin | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(adminConfiguration); + let uploadStatus = await generalAPI.listJobs("", datasetUnionJobId, true); + expect(uploadStatus.status).toBe(200); + }, 25000); + + it('Admin | un-authenticated , When request made, should respond with unauthenticated request', async () => { + let generalAPI = new CommonAPIsApi(Utility.getAdminConfiguration()); + + let bboxStatusResponse = generalAPI.listJobs("", datasetUnionJobId, true); + + await expect(bboxStatusResponse).rejects.toMatchObject({ response: { status: 401 } }); + }); + +}); + +describe('Download Dataset Union request file', () => { + + it('Admin | Authenticated , When request made with tdei_dataset_id, should stream the zip file', async () => { + let generalAPI = new CommonAPIsApi(adminConfiguration); + + let response = await generalAPI.jobDownload(datasetUnionJobId, { responseType: 'arraybuffer' }); + const data: any = response.data; + const contentType = response.headers['content-type']; + + expect(contentType).toBeOneOf(["application/zip"]); + expect(response.data).not.toBeNull(); + expect(response.status).toBe(200); + if (contentType === "application/zip") { + const zip = new AdmZip(data); + const entries = zip.getEntries(); + expect(entries.length).toBeGreaterThanOrEqual(0); + } + }, 20000); + + it('API-Key | Authenticated , When request made with tdei_dataset_id, should stream the zip file', async () => { + let generalAPI = new CommonAPIsApi(apiKeyConfiguration); + + let response = await generalAPI.jobDownload(datasetUnionJobId, { responseType: 'arraybuffer' }); + const data: any = response.data; + const contentType = response.headers['content-type']; + + expect(contentType).toBeOneOf(["application/zip"]); + expect(response.data).not.toBeNull(); + expect(response.status).toBe(200); + if (contentType === "application/zip") { + const zip = new AdmZip(data); + const entries = zip.getEntries(); + expect(entries.length).toBeGreaterThanOrEqual(0); + } + }, 20000); + + it('Admin | un-authenticated , When request made with tdei_dataset_id, should respond with unauthenticated request', async () => { + let generalAPI = new CommonAPIsApi(Utility.getAdminConfiguration()); + + let downloadResponse = generalAPI.jobDownload(datasetUnionJobId); + + await expect(downloadResponse).rejects.toMatchObject({ response: { status: 401 } }); + }); + +}); + +let spacialJoinJobId = ''; +describe('Spatial join Request', () => { + + it('OSW Data Generator | Authenticated , When request made with invalid/missing join input, should return bad response', async () => { + let oswAPI = new OSWApi(dgConfiguration); + let input = Utility.getSpatialJoinInput(); + input.join_condition = ""; + input.target_dimension = "invalid" as any; + + await expect(oswAPI.oswSpatialJoin(input)).rejects.toMatchObject({ response: { status: 400 } }); + }); + + it('OSW Data Generator | Authenticated , When request made with invalid target dataset id input, should return dataset not found response', async () => { + let oswAPI = new OSWApi(dgConfiguration); + let input = Utility.getSpatialJoinInput(); + input.target_dataset_id = "invalid"; + + await expect(oswAPI.oswSpatialJoin(input)).rejects.toMatchObject({ response: { status: 404 } }); + }); + + it('OSW Data Generator | Authenticated , When request made with invalid source dataset id input, should return dataset not found response', async () => { + let oswAPI = new OSWApi(dgConfiguration); + let input = Utility.getSpatialJoinInput(); + input.source_dataset_id = "invalid"; + + await expect(oswAPI.oswSpatialJoin(input)).rejects.toMatchObject({ response: { status: 404 } }); + }); + + it('OSW Data Generator | Authenticated , When request made with SQL Injection command, should return bad request', async () => { + let oswAPI = new OSWApi(dgConfiguration); + let input = Utility.getSpatialJoinInput(); + input.target_dataset_id = "DELETE * FROM Table;--"; + + await expect(oswAPI.oswSpatialJoin(input)).rejects.toMatchObject({ response: { status: 400 } }); + }); + + it('OSW Data Generator | Authenticated , When request made with non osw source dataset id, should return bad request', async () => { + let oswAPI = new OSWApi(dgConfiguration); + let input = Utility.getSpatialJoinInput(); + input.source_dataset_id = apiInput.flex.published_dataset; + + await expect(oswAPI.oswSpatialJoin(input)).rejects.toMatchObject({ response: { status: 400 } }); + }); + + it('OSW Data Generator | Authenticated , When request made with non osw target dataset id, should return bad request', async () => { + let oswAPI = new OSWApi(dgConfiguration); + let input = Utility.getSpatialJoinInput(); + input.target_dataset_id = apiInput.pathways.published_dataset; + + await expect(oswAPI.oswSpatialJoin(input)).rejects.toMatchObject({ response: { status: 400 } }); + }); + + it('OSW Data Generator | Authenticated , When request made with valid join input, should return request job id as response', async () => { + let oswAPI = new OSWApi(dgConfiguration); + + let spatialRequest = await oswAPI.oswSpatialJoin(Utility.getSpatialJoinInput()); + + expect(spatialRequest.status).toBe(202); + expect(spatialRequest.data).toBeNumber(); + spacialJoinJobId = spatialRequest.data!; + console.log("Spatial join job_id", spacialJoinJobId); + //verify location header + expect(spatialRequest.headers.location).toBeDefined(); + expect(spatialRequest.headers.location).toContain(`/api/v1/jobs?job_id=${spacialJoinJobId}`); + }, 20000); + + it('Admin | Authenticated , When request made with valid join input, should return request job id as response', async () => { + let oswAPI = new OSWApi(adminConfiguration); + + let spatialRequest = await oswAPI.oswSpatialJoin(Utility.getSpatialJoinInput()); + + expect(spatialRequest.status).toBe(202); + expect(spatialRequest.data).toBeNumber(); + }); + + it('POC | Authenticated , When request made with valid join input, should return request job id as response', async () => { + let oswAPI = new OSWApi(pocConfiguration); + + let spatialRequest = await oswAPI.oswSpatialJoin(Utility.getSpatialJoinInput()); + + expect(spatialRequest.status).toBe(202); + expect(spatialRequest.data).toBeNumber(); + }); + + it('Admin | un-authenticated , When request made with valid join input, should return with unauthenticated request', async () => { + let oswAPI = new OSWApi(Utility.getAdminConfiguration()); + + let bboxRequest = oswAPI.datasetTagRoad(apiInput.osw.published_dataset, uploadedDatasetId); + + await expect(bboxRequest).rejects.toMatchObject({ response: { status: 401 } }); + }); + +}); + +describe('Check spatial join request job completion status', () => { + jest.retryTimes(1, { logErrorsBeforeRetry: true }); + + it('OSW Data Generator | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(dgConfiguration); + await new Promise((r) => setTimeout(r, 20000)); + + let formatStatus = await generalAPI.listJobs(tdei_project_group_id, spacialJoinJobId, true); + + expect(formatStatus.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + job_id: expect.toBeOneOf([`${spacialJoinJobId}`]), + status: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "RUNNING"]), + progress: expect.objectContaining({ + total_stages: expect.any(Number), + completed_stages: expect.any(Number), + current_state: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "RUNNING"]), + current_stage: expect.any(String) + }) + }) + ]) + ); + }, 45000); + + it('POC | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(pocConfiguration); + let uploadStatus = await generalAPI.listJobs(tdei_project_group_id, spacialJoinJobId, true); + expect(uploadStatus.status).toBe(200); + }, 25000); + + it('Admin | Authenticated , When request made, should respond with job status', async () => { + let generalAPI = new CommonAPIsApi(adminConfiguration); + let uploadStatus = await generalAPI.listJobs("", spacialJoinJobId, true); + expect(uploadStatus.status).toBe(200); + }, 25000); + + it('Admin | un-authenticated , When request made, should respond with unauthenticated request', async () => { + let generalAPI = new CommonAPIsApi(Utility.getAdminConfiguration()); + + let bboxStatusResponse = generalAPI.listJobs("", spacialJoinJobId, true); + + await expect(bboxStatusResponse).rejects.toMatchObject({ response: { status: 401 } }); + }); + +}); + +describe('Download Spatial join request file', () => { + jest.retryTimes(1, { logErrorsBeforeRetry: true }); + + it('Admin | Authenticated , When request made with job_id, should stream the zip file', async () => { + let generalAPI = new CommonAPIsApi(adminConfiguration); + await new Promise((r) => setTimeout(r, 40000)); + let response = await generalAPI.jobDownload(spacialJoinJobId, { responseType: 'arraybuffer' }); + const data: any = response.data; + const contentType = response.headers['content-type']; + + expect(contentType).toBeOneOf(["application/xml", "application/zip"]); + expect(response.data).not.toBeNull(); + expect(response.status).toBe(200); + if (contentType === "application/zip") { + const zip = new AdmZip(data); + const entries = zip.getEntries(); + expect(entries.length).toBeGreaterThanOrEqual(1); + } + }, 50000); + + it('API-Key | Authenticated , When request made with job_id, should stream the zip file', async () => { + let generalAPI = new CommonAPIsApi(apiKeyConfiguration); + let response = await generalAPI.jobDownload(spacialJoinJobId, { responseType: 'arraybuffer' }); + const data: any = response.data; + const contentType = response.headers['content-type']; + + expect(contentType).toBeOneOf(["application/xml", "application/zip"]); + expect(response.data).not.toBeNull(); + expect(response.status).toBe(200); + if (contentType === "application/zip") { + const zip = new AdmZip(data); + const entries = zip.getEntries(); + expect(entries.length).toBeGreaterThanOrEqual(1); + } + }); + + it('Admin | un-authenticated , When request made with job_id, should respond with unauthenticated request', async () => { + let generalAPI = new CommonAPIsApi(Utility.getAdminConfiguration()); + + let downloadResponse = generalAPI.jobDownload(spacialJoinJobId); + + await expect(downloadResponse).rejects.toMatchObject({ response: { status: 401 } }); + }); + +}); + +describe("Tag Quality Metric", () => { + + it('OSW Data Generator | Authenticated , When request made with edge, node tags, expect to return quality metric', async () => { + // Arrange + let oswAPI = new OSWApi(dgConfiguration); + let tagMetricToUpload = Utility.getOSWTagMetricBlob(); + let tdei_dataset_id = uploadedDatasetId; + // Action + const tagQualityInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => tagQualityRequestInterceptor(req, tdei_dataset_id, 'tag-quality.json')) + const metric_result = await oswAPI.qualityMetricTagForm(tagMetricToUpload, tdei_dataset_id); + // Assert + expect(metric_result.status).toBe(200); + expect(metric_result.data).toBeArray(); + expect(metric_result.data.length).toBeGreaterThan(0); + expect(metric_result.data[0]).toContainAllKeys(['entity_type', 'total_entity_count', 'overall_quality_metric', 'metric_details']); + axios.interceptors.request.eject(tagQualityInterceptor); + }, 30000); + + it('POC | Authenticated , When request made with edge, node tags, expect to return quality metric', async () => { + // Arrange + let oswAPI = new OSWApi(pocConfiguration); + let tagMetricToUpload = Utility.getOSWTagMetricBlob(); + let tdei_dataset_id = uploadedDatasetId; + // Action + const tagQualityInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => tagQualityRequestInterceptor(req, tdei_dataset_id, 'tag-quality.json')) + const metric_result = await oswAPI.qualityMetricTagForm(tagMetricToUpload, tdei_dataset_id); + // Assert + expect(metric_result.status).toBe(200); + expect(metric_result.data).toBeArray(); + expect(metric_result.data.length).toBeGreaterThan(0); + expect(metric_result.data[0]).toContainAllKeys(['entity_type', 'total_entity_count', 'overall_quality_metric', 'metric_details']); + axios.interceptors.request.eject(tagQualityInterceptor); + }, 30000); + + it('Admin | Authenticated ,When request made with edge, node tags, expect to return quality metric', async () => { + // Arrange + let oswAPI = new OSWApi(adminConfiguration); + let tagMetricToUpload = Utility.getOSWTagMetricBlob(); + let tdei_dataset_id = uploadedDatasetId; + // Action + const tagQualityInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => tagQualityRequestInterceptor(req, tdei_dataset_id, 'tag-quality.json')) + const metric_result = await oswAPI.qualityMetricTagForm(tagMetricToUpload, tdei_dataset_id); + // Assert + expect(metric_result.status).toBe(200); + expect(metric_result.data).toBeArray(); + expect(metric_result.data.length).toBeGreaterThan(0); + expect(metric_result.data[0]).toContainAllKeys(['entity_type', 'total_entity_count', 'overall_quality_metric', 'metric_details']); + axios.interceptors.request.eject(tagQualityInterceptor); + }, 30000); + + it('API-Key | Authenticated ,When request made with edge, node tags, expect to return quality metric', async () => { + // Arrange + let oswAPI = new OSWApi(apiKeyConfiguration); + let tagMetricToUpload = Utility.getOSWTagMetricBlob(); + let tdei_dataset_id = uploadedDatasetId; + // Action + const tagQualityInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => tagQualityRequestInterceptor(req, tdei_dataset_id, 'tag-quality.json')) + const metric_result = await oswAPI.qualityMetricTagForm(tagMetricToUpload, tdei_dataset_id); + // Assert + expect(metric_result.status).toBe(200); + expect(metric_result.data).toBeArray(); + expect(metric_result.data.length).toBeGreaterThan(0); + expect(metric_result.data[0]).toContainAllKeys(['entity_type', 'total_entity_count', 'overall_quality_metric', 'metric_details']); + axios.interceptors.request.eject(tagQualityInterceptor); + }, 30000); + + it('Admin | Authenticated ,When request made with SQL Injection command, expect to return quality metric', async () => { + // Arrange + let oswAPI = new OSWApi(adminConfiguration); + let tagMetricToUpload = Utility.getOSWTagMetricSQLInjEntityBlob(); + let tdei_dataset_id = uploadedDatasetId; + // Action + const tagQualityInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => tagQualityRequestInterceptor(req, tdei_dataset_id, 'tag-quality.json')) + // Assert + await expect(oswAPI.qualityMetricTagForm(tagMetricToUpload, tdei_dataset_id)).rejects.toMatchObject({ response: { status: 400 } }); + axios.interceptors.request.eject(tagQualityInterceptor); + }, 30000); + + it('POC | authenticated, When request made with invalid dataset, should respond with dataset not found error', async () => { + + // Arrange + let oswAPI = new OSWApi(pocConfiguration); + let tagMetricToUpload = Utility.getOSWTagMetricEmptyBlob(); + // Action + const tagQualityInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => tagQualityRequestInterceptor(req, "invalid_tdei_dataset_id", 'tag-quality.json')) + // Assert + await expect(oswAPI.qualityMetricTagForm(tagMetricToUpload, "invalid_tdei_dataset_id")).rejects.toMatchObject({ response: { status: 404 } }); + axios.interceptors.request.eject(tagQualityInterceptor); + }, 30000); + + it('POC | authenticated, When request made with empty file, should respond with invalid request', async () => { + + // Arrange + let oswAPI = new OSWApi(pocConfiguration); + let tagMetricToUpload = Utility.getOSWTagMetricEmptyBlob(); + let tdei_dataset_id = uploadedDatasetId; + // Action + const tagQualityInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => tagQualityRequestInterceptor(req, tdei_dataset_id, 'tag-quality.json')) + // Assert + await expect(oswAPI.qualityMetricTagForm(tagMetricToUpload, tdei_dataset_id)).rejects.toMatchObject({ response: { status: 400 } }); + axios.interceptors.request.eject(tagQualityInterceptor); + }, 30000); + + it('POC | authenticated, When request made with invalid entity, should respond with invalid request', async () => { + + // Arrange + let oswAPI = new OSWApi(pocConfiguration); + let tagMetricToUpload = Utility.getOSWTagMetricInvalidEntityBlob(); + let tdei_dataset_id = uploadedDatasetId; + // Action + const tagQualityInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => tagQualityRequestInterceptor(req, tdei_dataset_id, 'tag-quality.json')) + // Assert + await expect(oswAPI.qualityMetricTagForm(tagMetricToUpload, tdei_dataset_id)).rejects.toMatchObject({ response: { status: 400 } }); + axios.interceptors.request.eject(tagQualityInterceptor); + }, 30000); + + it('POC | authenticated, When request made with invalid tag, should respond with invalid request', async () => { + + // Arrange + let oswAPI = new OSWApi(pocConfiguration); + let tagMetricToUpload = Utility.getOSWTagMetricInvalidTagBlob(); + let tdei_dataset_id = uploadedDatasetId; + // Action + const tagQualityInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => tagQualityRequestInterceptor(req, tdei_dataset_id, 'tag-quality.json')) + // Assert + await expect(oswAPI.qualityMetricTagForm(tagMetricToUpload, tdei_dataset_id)).rejects.toMatchObject({ response: { status: 400 } }); + axios.interceptors.request.eject(tagQualityInterceptor); + }, 30000); + + it('POC | un-authenticated, When request made with edge, node tags, should respond with unauthenticated request', async () => { + + // Arrange + let oswAPI = new OSWApi(Utility.getPocConfiguration()); + let tagMetricToUpload = Utility.getOSWTagMetricBlob(); + let tdei_dataset_id = uploadedDatasetId; + // Action + const tagQualityInterceptor = axios.interceptors.request.use((req: InternalAxiosRequestConfig) => tagQualityRequestInterceptor(req, tdei_dataset_id, 'tag-quality.json')) + // Assert + await expect(oswAPI.qualityMetricTagForm(tagMetricToUpload, tdei_dataset_id)).rejects.toMatchObject({ response: { status: 401 } }); + axios.interceptors.request.eject(tagQualityInterceptor); + }, 30000); +}); + +//This test should be ran at last as it will invalidate the uploaded file +describe('Invalidate the OSW file', () => { + + it('POC | Authenticated , When request made, should return true if successful', async () => { + let generalAPI = new CommonAPIsApi(pocConfiguration); + + let downloadResponse = generalAPI.deleteDataset(uploadedDatasetId); + + expect((await downloadResponse).status).toBe(200); + }); + + it('POC | Authenticated , When request made with invalid dataset id, should return dataset not found error', async () => { + let generalAPI = new CommonAPIsApi(pocConfiguration); + + let downloadResponse = generalAPI.deleteDataset('invalid_dataset_id'); + + await expect(downloadResponse).rejects.toMatchObject({ response: { status: 404 } }); + }); + + it('Admin | un-authenticated , When request made with dataset, should return with unauthenticated request', async () => { + let generalAPI = new CommonAPIsApi(Utility.getAdminConfiguration()); + + let downloadResponse = generalAPI.deleteDataset(uploadedDatasetId); + + await expect(downloadResponse).rejects.toMatchObject({ response: { status: 401 } }); + }); +}); + + +describe("Job List API", () => { + + it('Admin | Authenticated , When request made, expect to return job list', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(adminConfiguration); + // Action + const list_result = await generalAPI.listJobs("", NULL_PARAM, true); + + // Assert + expect(list_result.status).toBe(200); + expect(list_result.data).not.toBeNull(); + expect(list_result.data).toBeArray(); + + expect(list_result.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + job_id: expect.any(String), + download_url: expect.toBeNullOrString(), + message: expect.toBeNullOrString(), + status: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "FAILED"]), + job_type: expect.any(String), + tdei_project_group_id: expect.toBeNullOrString(), + tdei_project_group_name: expect.toBeNullOrString(), + requested_by: expect.any(String), + request_input: expect.any(Object), + response_props: expect.any(Object), + created_at: expect.any(String), + updated_at: expect.any(String), + data_type: expect.any(String), + current_stage: expect.any(String), + progress: expect.objectContaining({ + total_stages: expect.any(Number), + current_stage: expect.any(String), + completed_stages: expect.any(Number), + last_updated_at: expect.any(String), + current_state: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "FAILED", "RUNNING"]), + current_stage_percent_done: expect.any(Number) + }) + }) + ]) + ); + }, 30000); + + it('POC | Authenticated , When request made, expect to return job list', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(pocConfiguration); + // Action + const list_result = await generalAPI.listJobs(tdei_project_group_id, NULL_PARAM, true); + + // Assert + expect(list_result.status).toBe(200); + expect(list_result.data).not.toBeNull(); + expect(list_result.data).toBeArray(); + + expect(list_result.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + job_id: expect.any(String), + download_url: expect.toBeNullOrString(), + message: expect.toBeNullOrString(), + status: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "FAILED"]), + job_type: expect.any(String), + tdei_project_group_id: expect.toBeNullOrString(), + tdei_project_group_name: expect.toBeNullOrString(), + requested_by: expect.any(String), + request_input: expect.any(Object), + response_props: expect.any(Object), + created_at: expect.any(String), + updated_at: expect.any(String), + data_type: expect.any(String), + current_stage: expect.any(String), + progress: expect.objectContaining({ + total_stages: expect.any(Number), + current_stage: expect.any(String), + completed_stages: expect.any(Number), + last_updated_at: expect.any(String), + current_state: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "FAILED", "RUNNING"]), + current_stage_percent_done: expect.any(Number) + }) + }) + ]) + ); + }, 30000); + + it('Flex Data Generator | Authenticated , When request made, expect to return job list', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(flexDgConfiguration); + // Action + const list_result = await generalAPI.listJobs(tdei_project_group_id, NULL_PARAM, true); + + // Assert + expect(list_result.status).toBe(200); + expect(list_result.data).not.toBeNull(); + expect(list_result.data).toBeArray(); + + expect(list_result.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + job_id: expect.any(String), + download_url: expect.toBeNullOrString(), + message: expect.toBeNullOrString(), + status: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "FAILED"]), + job_type: expect.any(String), + tdei_project_group_id: expect.toBeNullOrString(), + tdei_project_group_name: expect.toBeNullOrString(), + requested_by: expect.any(String), + request_input: expect.any(Object), + response_props: expect.any(Object), + created_at: expect.any(String), + updated_at: expect.any(String), + data_type: expect.any(String), + current_stage: expect.any(String), + progress: expect.objectContaining({ + total_stages: expect.any(Number), + current_stage: expect.any(String), + completed_stages: expect.any(Number), + last_updated_at: expect.any(String), + current_state: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "FAILED", "RUNNING"]), + current_stage_percent_done: expect.any(Number) + }) + }) + ]) + ); + }, 30000); + + it('OSW Data Generator | Authenticated , When request made, expect to return job list', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(dgConfiguration); + // Action + const list_result = await generalAPI.listJobs(tdei_project_group_id, NULL_PARAM, true); + + // Assert + expect(list_result.status).toBe(200); + expect(list_result.data).not.toBeNull(); + expect(list_result.data).toBeArray(); + + expect(list_result.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + job_id: expect.any(String), + download_url: expect.toBeNullOrString(), + message: expect.toBeNullOrString(), + status: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "FAILED"]), + job_type: expect.any(String), + tdei_project_group_id: expect.toBeNullOrString(), + tdei_project_group_name: expect.toBeNullOrString(), + requested_by: expect.any(String), + request_input: expect.any(Object), + response_props: expect.any(Object), + created_at: expect.any(String), + updated_at: expect.any(String), + data_type: expect.any(String), + current_stage: expect.any(String), + progress: expect.objectContaining({ + total_stages: expect.any(Number), + current_stage: expect.any(String), + completed_stages: expect.any(Number), + last_updated_at: expect.any(String), + current_state: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "FAILED", "RUNNING"]), + current_stage_percent_done: expect.any(Number) + }) + }) + ]) + ); + }, 30000); + + it('Pathways Data Generator | Authenticated , When request made, expect to return job list', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(pathwaysDgConfiguration); + // Action + const list_result = await generalAPI.listJobs(tdei_project_group_id, NULL_PARAM, true); + + // Assert + expect(list_result.status).toBe(200); + expect(list_result.data).not.toBeNull(); + expect(list_result.data).toBeArray(); + + expect(list_result.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + job_id: expect.any(String), + download_url: expect.toBeNullOrString(), + message: expect.toBeNullOrString(), + status: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "FAILED"]), + job_type: expect.any(String), + tdei_project_group_id: expect.toBeNullOrString(), + tdei_project_group_name: expect.toBeNullOrString(), + requested_by: expect.any(String), + request_input: expect.any(Object), + response_props: expect.any(Object), + created_at: expect.any(String), + updated_at: expect.any(String), + data_type: expect.any(String), + current_stage: expect.any(String), + progress: expect.objectContaining({ + total_stages: expect.any(Number), + current_stage: expect.any(String), + completed_stages: expect.any(Number), + last_updated_at: expect.any(String), + current_state: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "FAILED", "RUNNING"]), + current_stage_percent_done: expect.any(Number) + }) + }) + ]) + ); + }, 30000); + + it('Admin | Authenticated , When request made with Job type filter `ConfidenceCalculate`, expect to return job list with filter job type', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(adminConfiguration); + // Action + const list_result = await generalAPI.listJobs("", NULL_PARAM, true, JobDetailsJobTypeEnum.ConfidenceCalculate); + + // Assert + expect(list_result.status).toBe(200); + expect(list_result.data).not.toBeNull(); + expect(list_result.data).toBeArray(); + + expect(list_result.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + job_id: expect.any(String), + download_url: expect.toBeNullOrString(), + message: expect.toBeNullOrString(), + status: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "FAILED"]), + job_type: expect.stringContaining(JobDetailsJobTypeEnum.ConfidenceCalculate), + tdei_project_group_id: expect.toBeNullOrString(), + tdei_project_group_name: expect.toBeNullOrString(), + requested_by: expect.any(String), + request_input: expect.any(Object), + response_props: expect.any(Object), + created_at: expect.any(String), + updated_at: expect.any(String), + data_type: expect.any(String), + current_stage: expect.any(String), + progress: expect.objectContaining({ + total_stages: expect.any(Number), + current_stage: expect.any(String), + completed_stages: expect.any(Number), + last_updated_at: expect.any(String), + current_state: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "FAILED", "RUNNING"]), + current_stage_percent_done: expect.any(Number) + }) + }) + ]) + ); + }, 30000); + + it('Admin | Authenticated , When request made with Job type filter `DatasetUpload`, expect to return job list with filter job type', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(adminConfiguration); + // Action + const list_result = await generalAPI.listJobs("", NULL_PARAM, true, JobDetailsJobTypeEnum.DatasetUpload); + + // Assert + expect(list_result.status).toBe(200); + expect(list_result.data).not.toBeNull(); + expect(list_result.data).toBeArray(); + + expect(list_result.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + job_id: expect.any(String), + download_url: expect.toBeNullOrString(), + message: expect.toBeNullOrString(), + status: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "FAILED"]), + job_type: expect.stringContaining(JobDetailsJobTypeEnum.DatasetUpload), + tdei_project_group_id: expect.toBeNullOrString(), + tdei_project_group_name: expect.toBeNullOrString(), + requested_by: expect.any(String), + request_input: expect.any(Object), + response_props: expect.any(Object), + created_at: expect.any(String), + updated_at: expect.any(String), + data_type: expect.any(String), + current_stage: expect.any(String), + progress: expect.objectContaining({ + total_stages: expect.any(Number), + current_stage: expect.any(String), + completed_stages: expect.any(Number), + last_updated_at: expect.any(String), + current_state: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "FAILED", "RUNNING"]), + current_stage_percent_done: expect.any(Number) + }) + }) + ]) + ); + }, 30000); + + it('Admin | Authenticated , When request made with Job type filter `DatasetPublish`, expect to return job list with filter job type', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(adminConfiguration); + // Action + const list_result = await generalAPI.listJobs("", NULL_PARAM, true, JobDetailsJobTypeEnum.DatasetPublish); + + // Assert + expect(list_result.status).toBe(200); + expect(list_result.data).not.toBeNull(); + expect(list_result.data).toBeArray(); + + expect(list_result.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + job_id: expect.any(String), + download_url: expect.toBeNullOrString(), + message: expect.toBeNullOrString(), + status: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "FAILED"]), + job_type: expect.stringContaining(JobDetailsJobTypeEnum.DatasetPublish), + tdei_project_group_id: expect.toBeNullOrString(), + tdei_project_group_name: expect.toBeNullOrString(), + requested_by: expect.any(String), + request_input: expect.any(Object), + response_props: expect.any(Object), + created_at: expect.any(String), + updated_at: expect.any(String), + data_type: expect.any(String), + current_stage: expect.any(String), + progress: expect.objectContaining({ + total_stages: expect.any(Number), + current_stage: expect.any(String), + completed_stages: expect.any(Number), + last_updated_at: expect.any(String), + current_state: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "FAILED", "RUNNING"]), + current_stage_percent_done: expect.any(Number) + }) + }) + ]) + ); + }, 30000); + + it('Admin | Authenticated , When request made with Job type filter `DatasetSpatialJoin`, expect to return job list with filter job type', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(adminConfiguration); + // Action + const list_result = await generalAPI.listJobs("", NULL_PARAM, true, JobDetailsJobTypeEnum.DatasetSpatialJoin); + + // Assert + expect(list_result.status).toBe(200); + expect(list_result.data).not.toBeNull(); + expect(list_result.data).toBeArray(); + + expect(list_result.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + job_id: expect.any(String), + download_url: expect.toBeNullOrString(), + message: expect.toBeNullOrString(), + status: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "FAILED"]), + job_type: expect.stringContaining(JobDetailsJobTypeEnum.DatasetSpatialJoin), + tdei_project_group_id: expect.toBeNullOrString(), + tdei_project_group_name: expect.toBeNullOrString(), + requested_by: expect.any(String), + request_input: expect.any(Object), + response_props: expect.any(Object), + created_at: expect.any(String), + updated_at: expect.any(String), + data_type: expect.any(String), + current_stage: expect.any(String), + progress: expect.objectContaining({ + total_stages: expect.any(Number), + current_stage: expect.any(String), + completed_stages: expect.any(Number), + last_updated_at: expect.any(String), + current_state: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "FAILED", "RUNNING"]), + current_stage_percent_done: expect.any(Number) + }) + }) + ]) + ); + }, 30000); + + it('Admin | Authenticated , When request made with Job type filter `DatasetReformat`, expect to return job list with filter job type', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(adminConfiguration); + // Action + const list_result = await generalAPI.listJobs("", NULL_PARAM, true, JobDetailsJobTypeEnum.DatasetReformat); + + // Assert + expect(list_result.status).toBe(200); + expect(list_result.data).not.toBeNull(); + expect(list_result.data).toBeArray(); + + expect(list_result.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + job_id: expect.any(String), + download_url: expect.toBeNullOrString(), + message: expect.toBeNullOrString(), + status: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "FAILED"]), + job_type: expect.stringContaining(JobDetailsJobTypeEnum.DatasetReformat), + tdei_project_group_id: expect.toBeNullOrString(), + tdei_project_group_name: expect.toBeNullOrString(), + requested_by: expect.any(String), + request_input: expect.any(Object), + response_props: expect.any(Object), + created_at: expect.any(String), + updated_at: expect.any(String), + data_type: expect.any(String), + current_stage: expect.any(String), + progress: expect.objectContaining({ + total_stages: expect.any(Number), + current_stage: expect.any(String), + completed_stages: expect.any(Number), + last_updated_at: expect.any(String), + current_state: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "FAILED", "RUNNING"]), + current_stage_percent_done: expect.any(Number) + }) + }) + ]) + ); + }, 30000); + + it('Admin | Authenticated , When request made with Job type filter `DatasetValidate`, expect to return job list with filter job type', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(adminConfiguration); + // Action + const list_result = await generalAPI.listJobs("", NULL_PARAM, true, JobDetailsJobTypeEnum.DatasetValidate); + + // Assert + expect(list_result.status).toBe(200); + expect(list_result.data).not.toBeNull(); + expect(list_result.data).toBeArray(); + + expect(list_result.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + job_id: expect.any(String), + download_url: expect.toBeNullOrString(), + message: expect.toBeNullOrString(), + status: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "FAILED"]), + job_type: expect.stringContaining(JobDetailsJobTypeEnum.DatasetValidate), + tdei_project_group_id: expect.toBeNullOrString(), + tdei_project_group_name: expect.toBeNullOrString(), + requested_by: expect.any(String), + request_input: expect.any(Object), + response_props: expect.any(Object), + created_at: expect.any(String), + updated_at: expect.any(String), + data_type: expect.any(String), + current_stage: expect.any(String), + progress: expect.objectContaining({ + total_stages: expect.any(Number), + current_stage: expect.any(String), + completed_stages: expect.any(Number), + last_updated_at: expect.any(String), + current_state: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "FAILED", "RUNNING"]), + current_stage_percent_done: expect.any(Number) + }) + }) + ]) + ); + }, 30000); + + it('Admin | Authenticated , When request made with Job type filter `DatasetInclineTag`, expect to return job list with filter job type', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(adminConfiguration); + // Action + const list_result = await generalAPI.listJobs("", NULL_PARAM, true, JobDetailsJobTypeEnum.DatasetInclineTag); + + // Assert + expect(list_result.status).toBe(200); + expect(list_result.data).not.toBeNull(); + expect(list_result.data).toBeArray(); + + expect(list_result.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + job_id: expect.any(String), + download_url: expect.toBeNullOrString(), + message: expect.toBeNullOrString(), + status: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "FAILED"]), + job_type: expect.stringContaining(JobDetailsJobTypeEnum.DatasetInclineTag), + tdei_project_group_id: expect.toBeNullOrString(), + tdei_project_group_name: expect.toBeNullOrString(), + requested_by: expect.any(String), + request_input: expect.any(Object), + response_props: expect.any(Object), + created_at: expect.any(String), + updated_at: expect.any(String), + data_type: expect.any(String), + current_stage: expect.any(String), + progress: expect.objectContaining({ + total_stages: expect.any(Number), + current_stage: expect.any(String), + completed_stages: expect.any(Number), + last_updated_at: expect.any(String), + current_state: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "FAILED", "RUNNING"]), + current_stage_percent_done: expect.any(Number) + }) + }) + ]) + ); + }, 30000); + + it('Admin | Authenticated , When request made with Job type filter `DatasetRoadTag`, expect to return job list with filter job type', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(adminConfiguration); + // Action + const list_result = await generalAPI.listJobs("", NULL_PARAM, true, JobDetailsJobTypeEnum.DatasetRoadTag); + + // Assert + expect(list_result.status).toBe(200); + expect(list_result.data).not.toBeNull(); + expect(list_result.data).toBeArray(); + + expect(list_result.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + job_id: expect.any(String), + download_url: expect.toBeNullOrString(), + message: expect.toBeNullOrString(), + status: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "FAILED"]), + job_type: expect.stringContaining(JobDetailsJobTypeEnum.DatasetRoadTag), + tdei_project_group_id: expect.toBeNullOrString(), + tdei_project_group_name: expect.toBeNullOrString(), + requested_by: expect.any(String), + request_input: expect.any(Object), + response_props: expect.any(Object), + created_at: expect.any(String), + updated_at: expect.any(String), + data_type: expect.any(String), + current_stage: expect.any(String), + progress: expect.objectContaining({ + total_stages: expect.any(Number), + current_stage: expect.any(String), + completed_stages: expect.any(Number), + last_updated_at: expect.any(String), + current_state: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "FAILED", "RUNNING"]), + current_stage_percent_done: expect.any(Number) + }) + }) + ]) + ); + }, 30000); + + it('Admin | Authenticated , When request made with Job type filter `DatasetUnion`, expect to return job list with filter job type', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(adminConfiguration); + // Action + const list_result = await generalAPI.listJobs("", NULL_PARAM, true, JobDetailsJobTypeEnum.DatasetUnion); + + // Assert + expect(list_result.status).toBe(200); + expect(list_result.data).not.toBeNull(); + expect(list_result.data).toBeArray(); + + expect(list_result.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + job_id: expect.any(String), + download_url: expect.toBeNullOrString(), + message: expect.toBeNullOrString(), + status: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "FAILED"]), + job_type: expect.stringContaining(JobDetailsJobTypeEnum.DatasetUnion), + tdei_project_group_id: expect.toBeNullOrString(), + tdei_project_group_name: expect.toBeNullOrString(), + requested_by: expect.any(String), + request_input: expect.any(Object), + response_props: expect.any(Object), + created_at: expect.any(String), + updated_at: expect.any(String), + data_type: expect.any(String), + current_stage: expect.any(String), + progress: expect.objectContaining({ + total_stages: expect.any(Number), + current_stage: expect.any(String), + completed_stages: expect.any(Number), + last_updated_at: expect.any(String), + current_state: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "FAILED", "RUNNING"]), + current_stage_percent_done: expect.any(Number) + }) + }) + ]) + ); + }, 30000); + + it('Admin | Authenticated , When request made with Job type filter `DatasetBBox`, expect to return job list with filter job type', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(adminConfiguration); + // Action + const list_result = await generalAPI.listJobs("", NULL_PARAM, true, JobDetailsJobTypeEnum.DatasetBBox); + + // Assert + expect(list_result.status).toBe(200); + expect(list_result.data).not.toBeNull(); + expect(list_result.data).toBeArray(); + + expect(list_result.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + job_id: expect.any(String), + download_url: expect.toBeNullOrString(), + message: expect.toBeNullOrString(), + status: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "FAILED"]), + job_type: expect.stringContaining(JobDetailsJobTypeEnum.DatasetBBox), + tdei_project_group_id: expect.toBeNullOrString(), + tdei_project_group_name: expect.toBeNullOrString(), + requested_by: expect.any(String), + request_input: expect.any(Object), + response_props: expect.any(Object), + created_at: expect.any(String), + updated_at: expect.any(String), + data_type: expect.any(String), + current_stage: expect.any(String), + progress: expect.objectContaining({ + total_stages: expect.any(Number), + current_stage: expect.any(String), + completed_stages: expect.any(Number), + last_updated_at: expect.any(String), + current_state: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "FAILED", "RUNNING"]), + current_stage_percent_done: expect.any(Number) + }) + }) + ]) + ); + }, 30000); + + it('Admin | Authenticated , When request made with Status `COMPLETED`, expect to return job list with COMPLETED status', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(adminConfiguration); + // Action + const list_result = await generalAPI.listJobs("", NULL_PARAM, true, NULL_PARAM, JobDetailsStatusEnum.COMPLETED); + + // Assert + expect(list_result.status).toBe(200); + expect(list_result.data).not.toBeNull(); + expect(list_result.data).toBeArray(); + + expect(list_result.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + job_id: expect.any(String), + download_url: expect.toBeNullOrString(), + message: expect.toBeNullOrString(), + status: expect.stringContaining(JobDetailsStatusEnum.COMPLETED), + job_type: expect.any(String), + tdei_project_group_id: expect.toBeNullOrString(), + tdei_project_group_name: expect.toBeNullOrString(), + requested_by: expect.any(String), + request_input: expect.any(Object), + response_props: expect.any(Object), + created_at: expect.any(String), + updated_at: expect.any(String), + data_type: expect.any(String), + current_stage: expect.any(String), + progress: expect.objectContaining({ + total_stages: expect.any(Number), + current_stage: expect.any(String), + completed_stages: expect.any(Number), + last_updated_at: expect.any(String), + current_state: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "FAILED", "RUNNING"]), + current_stage_percent_done: expect.any(Number) + }) + }) + ]) + ); + }, 30000); + + it('Admin | Authenticated , When request made with Status `INPROGRESS`, expect to return job list with INPROGRESS status', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(adminConfiguration); + // Action + const list_result = await generalAPI.listJobs("", NULL_PARAM, true, NULL_PARAM, JobDetailsStatusEnum.INPROGRESS); + + // Assert + expect(list_result.status).toBe(200); + expect(list_result.data).not.toBeNull(); + expect(list_result.data).toBeArray(); + if (list_result.data.length > 0) { + expect(list_result.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + job_id: expect.any(String), + download_url: expect.toBeNullOrString(), + message: expect.toBeNullOrString(), + status: expect.stringContaining(JobDetailsStatusEnum.INPROGRESS), + job_type: expect.any(String), + tdei_project_group_id: expect.toBeNullOrString(), + tdei_project_group_name: expect.toBeNullOrString(), + requested_by: expect.any(String), + request_input: expect.any(Object), + response_props: expect.any(Object), + created_at: expect.any(String), + updated_at: expect.any(String), + data_type: expect.any(String), + current_stage: expect.any(String), + progress: expect.objectContaining({ + total_stages: expect.any(Number), + current_stage: expect.any(String), + completed_stages: expect.any(Number), + last_updated_at: expect.any(String), + current_state: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "FAILED", "RUNNING"]), + current_stage_percent_done: expect.any(Number) + }) + }) + ]) + ); + } + }, 30000); + + it('Admin | Authenticated , When request made with Status `FAILED`, expect to return job list with FAILED status', async () => { + // Arrange + let generalAPI = new CommonAPIsApi(adminConfiguration); + // Action + const list_result = await generalAPI.listJobs("", NULL_PARAM, true, NULL_PARAM, JobDetailsStatusEnum.FAILED); + + // Assert + expect(list_result.status).toBe(200); + expect(list_result.data).not.toBeNull(); + expect(list_result.data).toBeArray(); + if (list_result.data.length > 0) { + expect(list_result.data).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + job_id: expect.any(String), + download_url: expect.toBeNullOrString(), + message: expect.toBeNullOrString(), + status: expect.stringContaining(JobDetailsStatusEnum.FAILED), + job_type: expect.any(String), + tdei_project_group_id: expect.toBeNullOrString(), + tdei_project_group_name: expect.toBeNullOrString(), + requested_by: expect.any(String), + request_input: expect.any(Object), + response_props: expect.any(Object), + created_at: expect.any(String), + updated_at: expect.any(String), + data_type: expect.any(String), + current_stage: expect.any(String), + progress: expect.objectContaining({ + total_stages: expect.any(Number), + current_stage: expect.any(String), + completed_stages: expect.any(Number), + last_updated_at: expect.any(String), + current_state: expect.toBeOneOf(["COMPLETED", "IN-PROGRESS", "FAILED", "RUNNING"]), + current_stage_percent_done: expect.any(Number) + }) + }) + ]) + ); + } + }, 30000); + + it('Admin | Authenticated , When request made with invalid job id, should return job id not found error', async () => { + let generalAPI = new CommonAPIsApi(adminConfiguration); + + let jobResponse = generalAPI.listJobs("", "000", true); + + await expect(jobResponse).rejects.toMatchObject({ response: { status: 404 } }); + }); + + it('Admin | Authenticated , When request made with invalid project group id, should return project group id not found error', async () => { + let generalAPI = new CommonAPIsApi(adminConfiguration); + + let jobResponse = generalAPI.listJobs("project_group_id", NULL_PARAM, true); + + await expect(jobResponse).rejects.toMatchObject({ response: { status: 404 } }); + }); +}); + +describe("Job Download API", () => { + it('Admin | un-authenticated , When request made with invalid job id, should return job id not found error', async () => { + let generalAPI = new CommonAPIsApi(adminConfiguration); + + let response = generalAPI.jobDownload("000", { responseType: 'arraybuffer' }); + + await expect(response).rejects.toMatchObject({ response: { status: 404 } }); + }); + + it('Admin | un-authenticated , When request made with job id, should return unauthenticated error', async () => { + let generalAPI = new CommonAPIsApi(Utility.getAdminConfiguration()); + + let response = generalAPI.jobDownload(convertJobId, { responseType: 'arraybuffer' }); + + await expect(response).rejects.toMatchObject({ response: { status: 401 } }); + }); +}); + +async function authenticate() { + await Utility.setAuthToken(adminConfiguration); + await Utility.setAuthToken(pocConfiguration); + await Utility.setAuthToken(dgConfiguration); + await Utility.setAuthToken(flexDgConfiguration); + await Utility.setAuthToken(pathwaysDgConfiguration); +} -}); \ No newline at end of file diff --git a/src/environment/environment.ts b/src/environment/environment.ts new file mode 100644 index 0000000..c02f594 --- /dev/null +++ b/src/environment/environment.ts @@ -0,0 +1,15 @@ +import dotenv from 'dotenv'; +dotenv.config(); + +export const environment = { + appName: process.env.npm_package_name, + seed: { + baseUrl: process.env.SEED_BASE_URL, + adminUser: process.env.SEED_ADMIN_USER, + adminPassword: process.env.SEED_ADMIN_PASSWORD, + }, + system: { + baseUrl: process.env.SYSTEM_BASE_URL + }, + environment: process.env.ENVIRONMENT ?? "dev", +} \ No newline at end of file diff --git a/src/global.setup.ts b/src/global.setup.ts new file mode 100644 index 0000000..ae2729c --- /dev/null +++ b/src/global.setup.ts @@ -0,0 +1,14 @@ +import { Seeder } from "./seeder"; + +export default async function globalSetup() { + try { + console.log('Starting global setup...'); + const seeder = new Seeder(); + console.log('Seeder instance created.'); + + global.seedData = await seeder.seed(); + console.log('Seeding completed successfully.'); + } catch (error) { + console.error('Global setup error:', error); + } +} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 941e6b9..4f2021b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,2 @@ import { Configuration } from "tdei-client"; -let configuration = new Configuration({}); -console.log('hello'); \ No newline at end of file +let configuration = new Configuration({}); \ No newline at end of file diff --git a/src/models/types.ts b/src/models/types.ts new file mode 100644 index 0000000..4cee399 --- /dev/null +++ b/src/models/types.ts @@ -0,0 +1,31 @@ + +export interface Credentials { + username: string + password: string +} + +export interface Users { + poc: Credentials + flex_data_generator: Credentials + pathways_data_generator: Credentials + osw_data_generator: Credentials + api_key_tester: Credentials + default_user: Credentials +} + + +export interface SeedData { + project_group: { + tdei_project_group_id: string, + name: string, + }; + services: [{ + tdei_project_group_id: string, + service_type: string, + service_name: string, + tdei_service_id: string + }]; + users: Users; + api_key: string; + api_key_tester: string +} \ No newline at end of file diff --git a/src/seeder.ts b/src/seeder.ts new file mode 100644 index 0000000..c28edbe --- /dev/null +++ b/src/seeder.ts @@ -0,0 +1,274 @@ +import { Utility } from './utils' +import { SeedData, Users } from './models/types' +import axios, { AxiosInstance } from "axios"; +import { environment } from './environment/environment'; +import { existsSync } from "fs"; +import { readFile, writeFile } from "fs/promises"; + +export class Seeder { + private client: APIUtility; + private readonly roles: Array; + private readonly data_types: Array; + + constructor() { + this.client = new APIUtility() + this.roles = ['poc', 'flex_data_generator', 'pathways_data_generator', 'osw_data_generator'] + this.data_types = ['osw', 'flex', 'pathways'] + } + + public async seed(freshSeed = false): Promise<{} | SeedData> { + try { + if (!freshSeed && existsSync('seed.data.json')) { + const data = await readFile('seed.data.json', { encoding: 'utf8' }); + if (data) { + console.log("Serving from local seed data!"); + return JSON.parse(data); + } + return {}; + } else { + console.log('Seeding...'); + await this.client.login() + let seedData: SeedData = {} as any; + const project_group = await this.client.createProjectGroup() + seedData.project_group = project_group + const services = await this.createService(project_group.tdei_project_group_id) + seedData.services = services + seedData.users = await this.assignUserRoles(project_group.tdei_project_group_id) + let userProfile = (await this.getUserProfile((seedData.users as Users).poc.username)); + seedData.api_key = userProfile.apiKey; + if (seedData.users.api_key_tester) { + let apiTesterProfile = await this.getUserProfile(seedData.users.api_key_tester.username); + seedData.api_key_tester = apiTesterProfile.apiKey; + } + + await this.writeFile(seedData); + console.info('Seeding complete'); + return seedData; + } + } catch (error) { + console.error('seed error ', error); + throw error; + } + } + + private async writeFile(data) { + await writeFile('./seed.data.json', JSON.stringify(data), 'utf8'); + } + + public async getUserProfile(user_name: string): Promise { + try { + await this.client.login(); + const result = await this.client.getUserProfile(user_name, 'Pa$s1word') + return result; + } catch (error) { + console.log(user_name) + console.error('getUserProfile', error); + throw error; + } + } + + public async createService(project_group_id: string): Promise<[{ + tdei_project_group_id: string, + service_type: string, + service_name: string, + tdei_service_id: string + }]> { + await this.client.login(); + let list: [{ + tdei_project_group_id: string, + service_type: string, + service_name: string, + tdei_service_id: string + }] = [] as any; + for await (const data_type of this.data_types) { + const service = await this.client.createService(project_group_id, data_type) + console.info(`Created Service with ID: ${service.tdei_service_id}`); + list.push(service); + + } + return list; + } + + public async removeHeader() { + axios.defaults.headers.common.Authorization = null; + } + + private async assignUserRoles(project_group_id: string): Promise { + console.log('Assigning user roles...'); + + const users = Utility.getApiInput().users; + let usersDictionary = {} as Users; + try { + for await (const role of this.roles) { + await this.client.addPermission(project_group_id, users[role], role) + console.info(`Added ${role} permission to username: ${users[role]}`) + usersDictionary[role] = { + username: users[role], + password: 'Pa$s1word' + } + } + // Assugn api_key_tester user to poc + if (users.api_key_tester) { + await this.client.addPermission(project_group_id, users.api_key_tester, 'poc') + console.info(`Added poc permission to username: ${users.api_key_tester}`) + usersDictionary['api_key_tester'] = { + username: users.api_key_tester, + password: 'Pa$s1word' + } + } + //add default user + usersDictionary['default_user'] = { + username: users.default_user, + password: 'Pa$s1word' + } + return usersDictionary + } catch (error) { + console.error('assignUserRoles', error); + throw error; + } + } + + // private async createUsers(project_group_id): Promise { + // const users = {} + // for await (const role of this.roles) { + // const userDetails = await this.client.createUser() + // await this.client.addPermission(project_group_id, userDetails.username, role) + // console.info(`Added ${role} permission to username: ${userDetails.username}`) + // users[role] = { + // username: userDetails.username, + // password: 'Pa$s1word' + // } + // } + // return users + // } + + // public async deactivateProjectGroup(project_group_id: string): Promise { + // return await this.client.activateOrDeactivateProjectGroup(project_group_id, false) + // } + + // public async activateProjectGroup(project_group_id: string): Promise { + // return await this.client.activateOrDeactivateProjectGroup(project_group_id, true) + // } +} + + +class APIUtility { + private instance: AxiosInstance; + + constructor() { + axios.defaults.baseURL = environment.seed.baseUrl; + this.instance = axios.create(); + // console.log(Utility.getRandomProjectGroupUpload()) + } + + async login(userName: string = environment.seed.adminUser!, password: string = environment.seed.adminPassword!): Promise { + try { + const resp = await axios({ + method: 'post', + url: '/api/v1/authenticate', + data: { + username: userName, + password: password + } + }); + const accessToken = resp?.data?.access_token + axios.defaults.headers.common['Authorization'] = `Bearer ${accessToken}` + } catch (err: any) { + throw err; + } + } + + async createProjectGroup(): Promise<{ + tdei_project_group_id: string; + name: string; + }> { + try { + let data: any = Utility.getRandomProjectGroupUpload(); + const resp = await axios({ + method: 'post', + url: '/api/v1/project-group', + data: data + }); + + data.tdei_project_group_id = resp?.data?.data; + + return { tdei_project_group_id: data.tdei_project_group_id, name: data.project_group_name }; + } catch (err: any) { + throw err; + } + } + + async createUser(): Promise { + try { + const resp = await axios({ + method: 'post', + url: '/api/v1/register', + data: Utility.getUserUpload() + }) + return resp?.data?.data + } catch (err: any) { + throw err; + } + } + + async addPermission(project_group_id: string, username: string, role: string): Promise { + try { + const resp = await axios({ + method: 'post', + url: '/api/v1/permission', + data: { + tdei_project_group_id: project_group_id, + user_name: username, + roles: [role] + } + }) + return resp?.data?.data + } catch (err: any) { + console.error(err) + throw err; + } + } + + async createService(project_group_id: string, service_type: string): Promise { + try { + let data: any = Utility.getServiceUpload(project_group_id, service_type); + const resp = await axios({ + method: 'post', + url: '/api/v1/service', + data: data + }) + data.tdei_service_id = resp?.data?.data; + return { tdei_service_id: data.tdei_service_id, service_type: data.service_type, service_name: data.service_name, tdei_project_group_id: data.tdei_project_group_id }; + } catch (err: any) { + throw err; + } + } + + async activateOrDeactivateProjectGroup(project_group_id: string, isActive: boolean): Promise { + if (!axios.defaults.headers.common['Authorization']) { + await this.login() + } + try { + const resp = await axios({ + method: 'delete', + url: `/api/v1/project-group/${project_group_id}/active/${isActive}`, + }) + return resp?.data + } catch (err: any) { + throw err; + } + } + + async getUserProfile(user_name: string, password: string): Promise { + this.login(user_name, password); + try { + const resp = await axios({ + method: 'get', + url: '/api/v1/user-profile?user_name=' + user_name, + }) + return resp?.data; + } catch (err: any) { + throw err; + } + } +} diff --git a/src/test-harness.example.json b/src/test-harness.example.json deleted file mode 100644 index 425a8b1..0000000 --- a/src/test-harness.example.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "seed":{ - "baseUrl":"https://tdei-usermanagement-ts-stage.azurewebsites.net", - "adminUser":"<>", - "adminPassword":"" - }, - - "system":{ - "baseUrl":"https://tdei-gateway-stage.azurewebsites.net", - "username":"", - "password":"" - } -} \ No newline at end of file diff --git a/src/utils.ts b/src/utils.ts index 0369122..932c270 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,67 +1,424 @@ -import { FeatureTypeEnum, GeoJsonObject, GeoJsonObjectTypeEnum, OswUpload, OswUploadCollectionMethodEnum, OswUploadDataSourceEnum } from "tdei-client"; - +import { + AuthenticationApi, + Configuration, + FeatureTypeEnum, + GeoJsonObject, + GeoJsonObjectTypeEnum, + OswSpatialjoinBody, + OswSpatialjoinBodySourceDimensionEnum, + OswSpatialjoinBodyTargetDimensionEnum +} from "tdei-client"; +import { environment } from "./environment/environment"; +import { faker } from '@faker-js/faker' +import path from "path"; +import * as fs from "fs"; +import metadata_flex from "../assets/payloads/gtfs-flex/metadata.json"; +import metadata_osw from "../assets/payloads/osw/metadata.json"; +import metadata_pathways from "../assets/payloads/gtfs-pathways/metadata.json"; +import apiInput from "../api.input.json"; +import { SeedData } from "./models/types"; /** * Utility class. */ export class Utility { + static get seedData() { + const seedData = JSON.parse(fs.readFileSync(path.resolve(__dirname, '../seed.data.json'), 'utf-8')); + return seedData as SeedData; + } + + static async setAuthToken(configuration: Configuration) { + let authAPI = new AuthenticationApi(configuration); + const loginResponse = await authAPI.authenticate({ + username: configuration.username, + password: configuration.password + }); + configuration.baseOptions = { + headers: { ...Utility.addAuthZHeader(loginResponse.data.access_token) } + }; + } + + static getApiInput() { + return apiInput[`${environment.environment}`]; + } + + static getDefaultUserConfiguration(): Configuration { + return new Configuration({ + username: this.seedData.users.default_user.username, + password: this.seedData.users.default_user.password, + basePath: environment.system.baseUrl + }); + } + + static getApiKeyConfiguration() { + let configuration = new Configuration({ + basePath: environment.system.baseUrl, + apiKey: this.seedData.api_key + }); + return configuration; + } + + static getAdminConfiguration(): Configuration { + return new Configuration({ + username: environment.seed.adminUser, + password: environment.seed.adminPassword, + basePath: environment.system.baseUrl + }); + } + + static getPocConfiguration(): Configuration { + return new Configuration({ + username: this.seedData.users.poc.username, + password: this.seedData.users.poc.password, + basePath: environment.system.baseUrl + }); + } + + static getOSWDataGeneratorConfiguration(): Configuration { + return new Configuration({ + username: this.seedData.users.osw_data_generator.username, + password: this.seedData.users.osw_data_generator.password, + basePath: environment.system.baseUrl + }); + } + + static getPathwaysDataGeneratorConfiguration(): Configuration { + return new Configuration({ + username: this.seedData.users.pathways_data_generator.username, + password: this.seedData.users.pathways_data_generator.password, + basePath: environment.system.baseUrl + }); + } + + static getFlexDataGeneratorConfiguration(): Configuration { + return new Configuration({ + username: this.seedData.users.flex_data_generator.username, + password: this.seedData.users.flex_data_generator.password, + basePath: environment.system.baseUrl + }); + } + + static getAPITesterConfiguration(): Configuration { + return new Configuration({ + username: this.seedData.users.api_key_tester.username, + password: this.seedData.users.api_key_tester.password, + basePath: environment.system.baseUrl + }); + } + + static getApiTesterKeyConfiguration() { + let configuration = new Configuration({ + basePath: environment.system.baseUrl, + apiKey: this.seedData.api_key_tester + }); + return configuration; + } + + static addAuthZHeader(accessToken) { + return { Authorization: `Bearer ${accessToken}` }; + } + static getRandomPolygon(): GeoJsonObject { return { - type : GeoJsonObjectTypeEnum.FeatureCollection, - features:[ + type: GeoJsonObjectTypeEnum.FeatureCollection, + features: [ { type: FeatureTypeEnum.Feature, geometry: { - type:"Polygon", - coordinates:[this.generateRandomCoordinates()] + type: "Polygon", + coordinates: [this.generateRandomCoordinates()] } } ] - } - + }; } - static generateRandomCoordinates():number[][]{ - var randomCoordinates : number[][] = []; - var firstRandom = [this.getRandomNumber(70,79),this.getRandomNumber(12,15)]; + static generateRandomCoordinates(): number[][] { + var randomCoordinates: number[][] = []; + var firstRandom = [ + this.getRandomNumber(70, 79), + this.getRandomNumber(12, 15) + ]; randomCoordinates.push(firstRandom); - for(let i=3;i--;){ - randomCoordinates.push([this.getRandomNumber(70,79),this.getRandomNumber(12,15)]); + for (let i = 3; i--;) { + randomCoordinates.push([ + this.getRandomNumber(70, 79), + this.getRandomNumber(12, 15) + ]); } randomCoordinates.push(firstRandom); return randomCoordinates; - } - static getRandomNumber(min:number,max:number): number{ + static getRandomNumber(min: number, max: number): number { var diff = max - min; - return parseFloat((min + Math.random()*diff).toFixed(6)); - } - - static getRandomOswUpload():OswUpload { - /** - * {"tdei_org_id":"66c85a5a-2335-4b97-a0a3-0bb93cba1ae5", - * "collected_by":"sfsd", - * "collection_date":"2023-03-03T02:22:45.374Z", - * "collection_method":"manual", - * "publication_date":"2023-03-02T04:22:42.493Z", - * "data_source":"InHouse", - * "polygon":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[77.588807608,12.976222962],[77.589285425,12.972094479],[77.593012392,12.974608826],[77.588839463,12.976254003],[77.588807608,12.976222962]]]}}]}, - * "osw_schema_version":"v0.1"} - */ - - return { - tdei_org_id:"66c85a5a-2335-4b97-a0a3-0bb93cba1ae5", - collected_by:"Collector name", - collection_date:"2023-03-03T02:22:45.374Z", - collection_method:OswUploadCollectionMethodEnum.Manual, - data_source:OswUploadDataSourceEnum.InHouse, - publication_date:"2023-03-02T04:22:42.493Z", - polygon:this.getRandomPolygon(), - osw_schema_version:"v0.1" - }; + return parseFloat((min + Math.random() * diff).toFixed(6)); + } + + static getRandomProjectGroupUpload() { + return { + project_group_name: faker.company.name(), + phone: faker.phone.number('###-###-####'), + url: faker.internet.url(), + address: `${faker.address.streetAddress()}, ${faker.address.stateAbbr()}, ${faker.address.country()}`, + dataset_area: this.getRandomPolygon() + } + } + + static getUserUpload() { + return { + firstName: faker.name.firstName(), + lastName: faker.name.lastName(), + email: faker.internet.email(), + phone: faker.phone.number('##########'), + password: 'Pa$s1word' + } + } + + static getStationUpload(project_group_id: string) { + return { + tdei_project_group_id: project_group_id, + station_name: `${faker.animal.dog()} Station`, + dataset_area: this.getRandomPolygon() + } + } + + static getServiceUpload(project_group_id: string, service_type: string) { + return { + tdei_project_group_id: project_group_id, + service_type: service_type, + service_name: `${faker.company.name()} Service`, + dataset_area: this.getRandomPolygon() + } + } + + /** + * All the file blob datas + */ + static getFlexBlob(): Blob { + return this.getFileBlob('gtfs-flex', 'otterexpress-mn-us--flex-v2.zip'); + } + + static getPathwaysBlob(): Blob { + return this.getFileBlob('gtfs-pathways', 'gtfs-pathways-valid.zip'); + } + + static getOSWBlob(): Blob { + return this.getFileBlob('osw', 'osw-la.zip'); + } + + // Change the implementation + static getChangesetBlob(): Blob { + return this.getFileBlob('osw', 'changeset.zip'); + } + // Change the implementation here + static getMetadataBlob(type: string): Blob { + //const blob = new Blob([jsonString], { type: 'application/json' }); + let randomMetadata = {}; + if (type == 'flex') { + randomMetadata = metadata_flex; + randomMetadata['dataset_detail']['schema_version'] = 'v2.0'; + } else if (type == 'pathways') { + randomMetadata = metadata_pathways; + randomMetadata['dataset_detail']['schema_version'] = 'v1.0'; + } else if (type == 'osw') { + randomMetadata = metadata_osw; + randomMetadata['dataset_detail']['schema_version'] = 'v0.2'; + } + + randomMetadata['dataset_detail']['name'] = faker.random.alphaNumeric(9) + `_${type}`; + let jsonString = JSON.stringify(randomMetadata); + const blob = new Blob([jsonString], { type: 'application/json' }); + + return blob; + } + + static replaceValues(obj: any, keyMap: { [key: string]: string }): any { + if (typeof obj !== 'object' || obj === null) { + return obj; + } + + if (Array.isArray(obj)) { + return obj.map(item => this.replaceValues(item, keyMap)); + } + + return Object.keys(obj).reduce((acc, key) => { + acc[key] = keyMap.hasOwnProperty(key) ? keyMap[key] : this.replaceValues(obj[key], keyMap); + return acc; + }, {} as any); + } + + static getEditMetadataBlob(type: string, keyMap: any): Blob { + //const blob = new Blob([jsonString], { type: 'application/json' }); + let randomMetadata = {}; + if (type == 'flex') { + randomMetadata = metadata_flex; + randomMetadata['dataset_detail']['schema_version'] = 'v2.0'; + } else if (type == 'pathways') { + randomMetadata = metadata_pathways; + randomMetadata['dataset_detail']['schema_version'] = 'v1.0'; + } else if (type == 'osw') { + randomMetadata = metadata_osw; + randomMetadata['dataset_detail']['schema_version'] = 'v0.2'; + } + + randomMetadata = this.replaceValues(randomMetadata, keyMap); + + randomMetadata['dataset_detail']['name'] = faker.random.alphaNumeric(9) + `_${type}`; + let jsonString = JSON.stringify(randomMetadata); + const blob = new Blob([jsonString], { type: 'application/json' }); + + return blob; + } + + static getOSWSubRegionBlob(): Blob { + let filePath = path.join(__dirname, '../assets/payloads/osw/sub-region.geojson'); + console.log(filePath); + let filestream = fs.readFileSync(filePath); + // let jsonString = JSON.stringify(osw_sub_region); + const blob = new Blob([filestream], { type: 'application/json' }); + return blob; + } + + static getOSWInvalidSubRegionBlob(): Blob { + let randomMetadata = [ + { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon" + } + } + ] + }]; + let jsonString = JSON.stringify(randomMetadata); + const blob = new Blob([jsonString], { type: 'application/json' }); + + return blob; + } + + static getOSWTagMetricBlob(): Blob { + let filePath = path.join(__dirname, '../assets/payloads/osw/tag-quality.json'); + console.log(filePath); + let filestream = fs.readFileSync(filePath); + const blob = new Blob([filestream], { type: 'application/json' }); + return blob; + } + + static getOSWTagMetricEmptyBlob(): Blob { + let randomMetadata = [{}]; + let jsonString = JSON.stringify(randomMetadata); + const blob = new Blob([jsonString], { type: 'application/json' }); + + return blob; + } + + static getOSWTagMetricSQLInjEntityBlob(): Blob { + let randomMetadata = [ + { + "entity_type": "Footway; Delete * from table;--", + "tags": [ + "surface", + "width", + "incline", + "length", + "description", + "name", + "foot" + ] + }]; + let jsonString = JSON.stringify(randomMetadata); + const blob = new Blob([jsonString], { type: 'application/json' }); + + return blob; + } + + static getOSWTagMetricInvalidEntityBlob(): Blob { + let randomMetadata = [ + { + "entity_type": "Footway_invalid", + "tags": [ + "surface", + "width", + "incline", + "length", + "description", + "name", + "foot" + ] + }]; + let jsonString = JSON.stringify(randomMetadata); + const blob = new Blob([jsonString], { type: 'application/json' }); + + return blob; + } + + static getOSWTagMetricInvalidTagBlob(): Blob { + let randomMetadata = [ + { + "entity_type": "Footway", + "tags": [ + "surface_old", + "width", + "incline", + "length", + "description", + "name", + "foot" + ] + }]; + let jsonString = JSON.stringify(randomMetadata); + const blob = new Blob([jsonString], { type: 'application/json' }); + + return blob; + } + + static getInvalidMetadataBlob(type: string): Blob { + //no name and version required fields + let randomMetadata = { + "description": "Bootstrap", + "custom_metadata": { + "name": "Lara", + "gender": "female" + }, + "collected_by": "John Doe", + "collection_date": "2019-02-10T09:30Z", + "collection_method": "manual", + "data_source": "3rdParty", + "schema_version": "v0.1" + } + randomMetadata['name'] = faker.random.alphaNumeric(9) + `_${type}`; + let jsonString = JSON.stringify(randomMetadata); + const blob = new Blob([jsonString], { type: 'application/json' }); + + return blob; + } + + static getFileBlob(directory: string, filename: string, type: string = "application/zip"): Blob { + let fileDir = path.dirname(__dirname); + let payloadFilePath = path.join(fileDir, "assets/payloads/" + directory + "/files/" + filename); + let filestream = fs.readFileSync(payloadFilePath); + const blob = new Blob([filestream], { type: type }); + return blob + + } + + static getSpatialJoinInput() { + let model: OswSpatialjoinBody = { + target_dataset_id: Utility.getApiInput().osw.spatial_target_dataset, + target_dimension: OswSpatialjoinBodyTargetDimensionEnum.Edge, + source_dataset_id: Utility.getApiInput().osw.spatial_source_dataset, + source_dimension: OswSpatialjoinBodySourceDimensionEnum.Point, + join_condition: "ST_Contains(ST_Buffer(geometry_target, 5), geometry_source)", + join_filter_target: "highway='footway' AND footway='sidewalk'", + join_filter_source: "highway='street_lamp'", + aggregate: ["ARRAY_AGG(highway) as my_highway"] + } + return model; } +} - -} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 60ecaf8..f1700eb 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,6 @@ { "compilerOptions": { /* Visit https://aka.ms/tsconfig to read more about this file */ - /* Projects */ // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ @@ -9,13 +8,15 @@ // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ - /* Language and Environment */ - "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ - "lib": ["es6","DOM"], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + "target": "es2017", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + "lib": [ + "es6", + "DOM" + ], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ // "jsx": "preserve", /* Specify what JSX code is generated. */ - "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ - "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ @@ -23,11 +24,10 @@ // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ - /* Modules */ - "module": "commonjs", /* Specify what module code is generated. */ - "rootDir": "src", /* Specify the root folder within your source files. */ - "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + "module": "esnext", /* Specify what module code is generated. */ + "rootDir": "src", /* Specify the root folder within your source files. */ + "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ // "baseUrl": ".", /* Specify the base directory to resolve non-relative module names. */ // "paths": { // "@core/storage":["./src/core/storage"], @@ -38,21 +38,19 @@ // "types": [], /* Specify type package names to be included without being referenced in a source file. */ // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ - "resolveJsonModule": true, /* Enable importing .json files. */ + "resolveJsonModule": true, /* Enable importing .json files. */ // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ - /* JavaScript Support */ - "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ - /* Emit */ // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ // "declarationMap": true, /* Create sourcemaps for d.ts files. */ // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ - "outDir": "build", /* Specify an output folder for all emitted files. */ + "outDir": "build", /* Specify an output folder for all emitted files. */ // "removeComments": true, /* Disable emitting comments. */ // "noEmit": true, /* Disable emitting files from a compilation. */ // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ @@ -70,17 +68,15 @@ // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ - /* Interop Constraints */ // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ - "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ - "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ - + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ /* Type Checking */ - "strict": true, /* Enable all strict type-checking options. */ - "noImplicitAny": false, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + "strict": true, /* Enable all strict type-checking options. */ + "noImplicitAny": false, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ @@ -98,14 +94,13 @@ // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ - /* Completeness */ // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ - "skipLibCheck": true /* Skip type checking all .d.ts files. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ }, "exclude": [ "*.config.ts", "build", "node_modules" ] -} +} \ No newline at end of file