diff --git a/.circleci/config.yml b/.circleci/config.yml index f43db31dea7..a8690c2f9c6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,6 +1,7 @@ version: 2 jobs: bundle: + resource_class: large docker: - image: $AWS_ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/ef-cms-us-east-1:latest aws_auth: @@ -71,7 +72,7 @@ jobs: aws_secret_access_key: $AWS_SECRET_ACCESS_KEY environment: _JAVA_OPTIONS: '-Xms1024m -Xmx2024m' - resource_class: 2xlarge + resource_class: xlarge steps: - attach_workspace: at: ~/ @@ -102,7 +103,7 @@ jobs: aws_secret_access_key: $AWS_SECRET_ACCESS_KEY environment: _JAVA_OPTIONS: '-Xms2048m -Xmx4096m' - resource_class: 2xlarge + resource_class: xlarge steps: - attach_workspace: at: ~/ @@ -122,7 +123,7 @@ jobs: aws_secret_access_key: $AWS_SECRET_ACCESS_KEY environment: _JAVA_OPTIONS: '-Xms2048m -Xmx4096m' - resource_class: 2xlarge + resource_class: xlarge parallelism: 2 steps: - attach_workspace: @@ -177,8 +178,6 @@ jobs: -Dproject.settings="web-client/sonar-project.properties" \ -Dsonar.login="${UI_SONAR_TOKEN}" \ -Dsonar.host.url="https://sonarcloud.io" - - store_artifacts: - path: ~/project/combined-coverage e2e-pa11y: docker: @@ -188,7 +187,7 @@ jobs: aws_secret_access_key: $AWS_SECRET_ACCESS_KEY environment: _JAVA_OPTIONS: '-Xms2048m -Xmx4096m' - resource_class: 2xlarge + resource_class: xlarge steps: - attach_workspace: at: ~/ @@ -239,7 +238,7 @@ jobs: aws_secret_access_key: $AWS_SECRET_ACCESS_KEY environment: _JAVA_OPTIONS: '-Xms1024m -Xmx2048m' - resource_class: 2xlarge + resource_class: xlarge steps: - attach_workspace: at: ~/ @@ -276,14 +275,8 @@ jobs: - run: name: Build Docker Image command: | - if [[ $(./web-api/deploy-diff.sh $ENV web-api/runtimes/puppeteer) = "true" ]]; then - cd web-api/runtimes/puppeteer && ./build.sh && cd ../../.. - fi - - if [[ $(./web-api/deploy-diff.sh $ENV web-api/runtimes/clamav) = "true" ]]; then - cd web-api/runtimes/clamav && ./build.sh && cd ../../.. - fi - + cd web-api/runtimes/puppeteer && ./build.sh && cd ../../.. + cd web-api/runtimes/clamav && ./build.sh && cd ../../.. docker build -t efcms -f Dockerfile . - run: name: Setup Dynamsoft Keys @@ -291,6 +284,9 @@ jobs: - run: name: Setup ES Instance Count command: echo "export ES_INSTANCE_COUNT='$(./get-es-instance-count.sh $CIRCLE_BRANCH)'" >> $BASH_ENV + - run: + name: Setup Honeybadger Keys + command: echo "export CIRCLE_HONEYBADGER_API_KEY='$(./get-honeybadger-keys.sh $CIRCLE_BRANCH)'" >> $BASH_ENV - run: name: 'Deploy - Web API - Terraform' command: docker run -e "AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}" -e "AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}" -e "COGNITO_SUFFIX=${COGNITO_SUFFIX}" -e "EFCMS_DOMAIN=${EFCMS_DOMAIN}" -e "SES_DMARC_EMAIL=${SES_DMARC_EMAIL}" -e "ES_INSTANCE_COUNT=${ES_INSTANCE_COUNT}" --rm efcms /bin/sh -c "cd web-api/terraform/main && ../bin/deploy-app.sh ${ENV}" @@ -315,24 +311,18 @@ jobs: - run: name: Build Docker Image command: | - if [[ $(./web-api/deploy-diff.sh $ENV web-api/runtimes/puppeteer) = "true" ]]; then - cd web-api/runtimes/puppeteer && ./build.sh && cd ../../.. - fi - - if [[ $(./web-api/deploy-diff.sh $ENV web-api/runtimes/clamav) = "true" ]]; then - cd web-api/runtimes/clamav && ./build.sh && cd ../../.. - fi - + cd web-api/runtimes/puppeteer && ./build.sh && cd ../../.. + cd web-api/runtimes/clamav && ./build.sh && cd ../../.. docker build -t efcms -f Dockerfile . - run: name: Setup Honeybadger Keys command: echo "export CIRCLE_HONEYBADGER_API_KEY='$(./get-honeybadger-keys.sh $CIRCLE_BRANCH)'" >> $BASH_ENV - run: name: 'Deploy - Web API - Layers - Puppeteer - us-east-1' - command: if [[ $(./web-api/deploy-diff.sh $ENV web-api/runtimes/puppeteer) = "true" ]]; then docker run -e "AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}" -e "AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}" -e "EFCMS_DOMAIN=${EFCMS_DOMAIN}" --rm efcms /bin/sh -c "./web-api/run-serverless-puppeteer.sh ${ENV} us-east-1"; fi; + command: docker run -e "AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}" -e "AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}" -e "EFCMS_DOMAIN=${EFCMS_DOMAIN}" --rm efcms /bin/sh -c "./web-api/run-serverless-puppeteer.sh ${ENV} us-east-1" - run: name: 'Deploy - Web API - Layers - ClamAV - us-east-1' - command: if [[ $(./web-api/deploy-diff.sh $ENV web-api/runtimes/clamav) = "true" ]]; then docker run -e "AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}" -e "AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}" -e "EFCMS_DOMAIN=${EFCMS_DOMAIN}" --rm efcms /bin/sh -c "./web-api/run-serverless-clamav.sh ${ENV} us-east-1"; fi; + command: docker run -e "AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}" -e "AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}" -e "EFCMS_DOMAIN=${EFCMS_DOMAIN}" --rm efcms /bin/sh -c "./web-api/run-serverless-clamav.sh ${ENV} us-east-1" - run: name: 'Deploy - Web API - Serverless - Public API - us-east-1' command: docker run -e "AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}" -e "AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}" -e "EFCMS_DOMAIN=${EFCMS_DOMAIN}" -e "CIRCLE_HONEYBADGER_API_KEY=${CIRCLE_HONEYBADGER_API_KEY}" -v $(pwd)/.cache:/home/app/.cache --rm efcms /bin/sh -c "./web-api/run-serverless-public-api.sh ${ENV} us-east-1" @@ -399,24 +389,18 @@ jobs: - run: name: Build Docker Image command: | - if [[ $(./web-api/deploy-diff.sh $ENV web-api/runtimes/puppeteer) = "true" ]]; then - cd web-api/runtimes/puppeteer && ./build.sh && cd ../../.. - fi - - if [[ $(./web-api/deploy-diff.sh $ENV web-api/runtimes/clamav) = "true" ]]; then - cd web-api/runtimes/clamav && ./build.sh && cd ../../.. - fi - + cd web-api/runtimes/puppeteer && ./build.sh && cd ../../.. + cd web-api/runtimes/clamav && ./build.sh && cd ../../.. docker build -t efcms -f Dockerfile . - run: name: Setup Honeybadger Keys command: echo "export CIRCLE_HONEYBADGER_API_KEY='$(./get-honeybadger-keys.sh $CIRCLE_BRANCH)'" >> $BASH_ENV - run: name: 'Deploy - Web API - Layers - Puppeteer - us-west-1' - command: if [[ $(./web-api/deploy-diff.sh $ENV web-api/runtimes/puppeteer) = "true" ]]; then docker run -e "AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}" -e "AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}" -e "EFCMS_DOMAIN=${EFCMS_DOMAIN}" --rm efcms /bin/sh -c "./web-api/run-serverless-puppeteer.sh ${ENV} us-west-1"; fi; + command: docker run -e "AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}" -e "AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}" -e "EFCMS_DOMAIN=${EFCMS_DOMAIN}" --rm efcms /bin/sh -c "./web-api/run-serverless-puppeteer.sh ${ENV} us-west-1" - run: name: 'Deploy - Web API - Layers - ClamAV - us-west-1' - command: if [[ $(./web-api/deploy-diff.sh $ENV web-api/runtimes/clamav) = "true" ]]; then docker run -e "AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}" -e "AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}" -e "EFCMS_DOMAIN=${EFCMS_DOMAIN}" --rm efcms /bin/sh -c "./web-api/run-serverless-clamav.sh ${ENV} us-west-1"; fi; + command: docker run -e "AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}" -e "AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}" -e "EFCMS_DOMAIN=${EFCMS_DOMAIN}" --rm efcms /bin/sh -c "./web-api/run-serverless-clamav.sh ${ENV} us-west-1" - run: name: 'Deploy - Web API - Serverless - Public API - us-west-1' command: docker run -e "AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}" -e "AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}" -e "EFCMS_DOMAIN=${EFCMS_DOMAIN}" -e "CIRCLE_HONEYBADGER_API_KEY=${CIRCLE_HONEYBADGER_API_KEY}" -v $(pwd)/.cache:/home/app/.cache --rm efcms /bin/sh -c "./web-api/run-serverless-public-api.sh ${ENV} us-west-1" @@ -477,14 +461,8 @@ jobs: - run: name: Build Docker Image command: | - if [[ $(./web-api/deploy-diff.sh $ENV web-api/runtimes/puppeteer) = "true" ]]; then - cd web-api/runtimes/puppeteer && ./build.sh && cd ../../.. - fi - - if [[ $(./web-api/deploy-diff.sh $ENV web-api/runtimes/clamav) = "true" ]]; then - cd web-api/runtimes/clamav && ./build.sh && cd ../../.. - fi - + cd web-api/runtimes/puppeteer && ./build.sh && cd ../../.. + cd web-api/runtimes/clamav && ./build.sh && cd ../../.. docker build -t efcms -f Dockerfile . - run: name: Setup Honeybadger Keys @@ -522,9 +500,68 @@ jobs: - run: name: 'Deploy - Web API - Cognito Customize' command: docker run -e "AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}" -e "AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}" --rm efcms /bin/sh -c "cd web-api && ./setup-cognito-ui.sh ${ENV}" + - run: + name: 'Deploy - Web API - Cognito Create Users' + command: | + if [ "${CIRCLE_BRANCH}" != "migration" ] && [ "${CIRCLE_BRANCH}" != "master"]; then + docker run -e "AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}" -e "AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}" -e "USTC_ADMIN_PASS=${USTC_ADMIN_PASS}" --rm efcms /bin/sh -c "cd web-api && ./setup-cognito-users.sh ${ENV}" + else + echo "skipping…" + fi + - run: + name: 'Deploy - Web API - Cognito Create Court Users' + command: | + if [ "${CIRCLE_BRANCH}" != "migration" ] && [ "${CIRCLE_BRANCH}" != "master"]; then + docker run -e "AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}" -e "AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}" -e "USTC_ADMIN_PASS=${USTC_ADMIN_PASS}" --rm efcms /bin/sh -c "cd web-api && ./setup-court-users.sh ${ENV}" + else + echo "skipping…" + fi + - run: + name: 'Deploy - Web API - Cognito Create IRS User' + command: | + if [ "${CIRCLE_BRANCH}" != "migration" ] && [ "${CIRCLE_BRANCH}" != "master"]; then + docker run -e "AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}" -e "AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}" -e "USTC_ADMIN_PASS=${USTC_ADMIN_PASS}" --rm efcms /bin/sh -c "cd web-api && ./setup-irs-user.sh ${ENV}" + else + echo "skipping…" + fi - run: name: 'Deploy - Web API - Run Migrations' command: docker run -e "AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}" -e "AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}" -e "DYNAMODB_ENDPOINT=dynamodb.us-east-1.amazonaws.com" --rm efcms /bin/sh -c "npm run build:assets && ./web-api/run-umzug.sh ${ENV}" + - run: + name: 'Deploy - Web API - Smoke Tests - us-east-1' + command: | + if [ "${CIRCLE_BRANCH}" != "migration" ] && [ "${CIRCLE_BRANCH}" != "master"]; then + docker run -e "AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}" -e "AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}" --rm efcms /bin/sh -c "cd web-api && node smoke-tests.js ${ENV} us-east-1" + else + echo "skipping…" + fi + - run: + name: 'Deploy - Web API - Smoke Tests - us-west-1' + command: | + if [ "${CIRCLE_BRANCH}" != "migration" ] && [ "${CIRCLE_BRANCH}" != "master"]; then + docker run -e "AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}" -e "AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}" --rm efcms /bin/sh -c "cd web-api && node smoke-tests.js ${ENV} us-west-1" + else + echo "skipping…" + fi + - run: + name: 'Deploy - Cypress Smoke Tests' + command: | + if [ "${CIRCLE_BRANCH}" != "migration" ] && [ "${CIRCLE_BRANCH}" != "master"]; then + docker run -e "AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}" -e "AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}" --rm efcms /bin/sh -c "CYPRESS_BASE_URL='https://ui-$ENV.$EFCMS_DOMAIN' ENV=${ENV} npm run cypress:smoketests" + else + echo "skipping…" + fi + - run: + name: 'Deploy - Pa11y Smoke Tests' + command: | + if [ "${CIRCLE_BRANCH}" != "migration" ] && [ "${CIRCLE_BRANCH}" != "master"]; then + docker run -e "AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}" -e "AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}" -e "EFCMS_DOMAIN=${EFCMS_DOMAIN}" --rm efcms /bin/sh -c "ENV=${ENV} npm run test:pa11y:smoketests" + else + echo "skipping…" + fi + - run: + name: 'Deploy - Cognito Authorizer Check' + command: docker run -e "AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}" -e "AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}" -e "EFCMS_DOMAIN=${EFCMS_DOMAIN}" --rm efcms /bin/sh -c "find web-api/*.yml | ENV=${ENV} xargs node web-api/verify-authorizers.js" - store_artifacts: path: /home/app/cypress-smoketests/videos/ diff --git a/.gitignore b/.gitignore index 5b740380fe4..8b4d2ce9a2b 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,8 @@ web-api/runtimes/clamav/clamav_lambda_layer.tar.gz web-api/runtimes/clamav/lib web-api/storage/s3/* web-api/terraform/template/cognito-triggers/index.js.zip +web-api/terraform/template/cognito-authorizer/index.js.zip +web-api/terraform/template/log-forwarder/index.js.zip web-client/.cache/ web-client/coverage-e2e web-client/coverage-integration/* diff --git a/Dockerfile b/Dockerfile index 106ba5d9eb3..d4f79756001 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM cypress/base:12.13.0 +FROM cypress/base:12.16.0 RUN echo "recache again" diff --git a/Dockerfile-CI b/Dockerfile-CI index 9455370fc9c..442976e4ad9 100644 --- a/Dockerfile-CI +++ b/Dockerfile-CI @@ -1,4 +1,4 @@ -FROM cypress/base:12.13.0 +FROM cypress/base:12.16.0 WORKDIR /home/app/ef-cms @@ -24,4 +24,4 @@ RUN apt-get install -y gconf-service libasound2 libatk1.0-0 libc6 libcairo2 libc git bash openssh-client python python-dev python-pip python-setuptools ca-certificates less \ unzip wget jq shellcheck clamav -RUN freshclam \ No newline at end of file +RUN freshclam diff --git a/README.md b/README.md index 544e9492a6d..77417646dcc 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ The backlog is stored [in GitHub Issues in Flexion’s repository](https://githu To exercise the CI/CD pipeline locally, run the following: -`./test-all.sh` +`./docker-test-all.sh` This will run the linter, Shellcheck, audit, build, test, Cypress, Cerebral tests, Pa11y, etc. over all the components. diff --git a/cypress/integration/petitions-clerk-creates-a-case.spec.js b/cypress/integration/petitions-clerk-creates-a-case.spec.js index 83f9db55b42..98443d89eed 100644 --- a/cypress/integration/petitions-clerk-creates-a-case.spec.js +++ b/cypress/integration/petitions-clerk-creates-a-case.spec.js @@ -22,31 +22,12 @@ describe('Create case and submit to IRS', function () { fillInCreateCaseFromPaperForm(); + cy.server(); + cy.route('POST', '**/paper').as('postPaperCase'); cy.get('#submit-case').click(); - }); - - it('should display a create case header', () => { - const banner = cy.get('.big-blue-header'); - banner.contains('Create Case'); - }); - - it('should display a tile for party information, case information, irs notice, and attachments each with edit buttons', () => { - cy.get('#parties-card').contains('Parties').find('button'); - - cy.get('#case-information-card') - .contains('Case Information') - .find('button'); - - cy.get('#irs-notice-card').contains('IRS Notice').find('button'); - - cy.get('#attachments-card').contains('Attachments').find('button'); - }); - - it('should display serve to irs button', () => { - cy.get('#submit-case').should('exist'); - }); - - it('should display save for later button', () => { - cy.get('#save-for-later').should('exist'); + cy.wait('@postPaperCase'); + cy.get('@postPaperCase').should(xhr => { + expect(xhr.responseBody).to.have.property('docketNumber'); + }); }); }); diff --git a/cypress/integration/start-a-case-practitioner.spec.js b/cypress/integration/start-a-case-practitioner.spec.js index a35085d1b82..05118b94d93 100644 --- a/cypress/integration/start-a-case-practitioner.spec.js +++ b/cypress/integration/start-a-case-practitioner.spec.js @@ -11,9 +11,9 @@ describe('Start a case as a practitioner ', () => { cy.task('seed'); }); - it('go to the practitioner dashboard and expect that a case list table is displayed with 2 cases', () => { + it('go to the practitioner dashboard and expect that a case list table is displayed with 3 cases', () => { navigateToDashboard('privatePractitioner'); - getCaseList().should('have.length', 2); + getCaseList().should('have.length', 3); }); it('click the start a case button', () => { @@ -24,8 +24,8 @@ describe('Start a case as a practitioner ', () => { fillInAndSubmitForm(); }); - it('expect the case list to be displayed with 3 items now', () => { + it('expect the case list to be displayed with 4 items now', () => { getCaseList().should('exist'); - getCaseList().should('have.length', 3); + getCaseList().should('have.length', 4); }); }); diff --git a/docker-test-all.sh b/docker-test-all.sh index f99cde3e769..979a238d0ed 100755 --- a/docker-test-all.sh +++ b/docker-test-all.sh @@ -2,15 +2,23 @@ # This runs the same build steps that run in Circle, except sonar rm -rf node_modules dist .elasticsearch .dynamodb -npm i +npm ci + docker build -t efcms -f Dockerfile . + docker run --rm efcms /bin/sh -c 'npm run lint' + docker run --rm efcms /bin/sh -c './run-shellcheck.sh' + docker run -v "$(pwd)/shared/coverage:/home/app/shared/coverage" --rm efcms /bin/sh -c 'npm run test:shared' + docker run -v "$(pwd)/web-api/coverage:/home/app/web-api/coverage" --rm efcms /bin/sh -c 'npm run test:api' + docker run -v "$(pwd)/web-client/coverage:/home/app/web-client/coverage" --rm -e SKIP_CACHE_INVALIDATION=true efcms /bin/sh -c \ '(npm run start:api &) && ./wait-until.sh http://localhost:3000/api/swagger && npm run test:client' + docker run --rm -e SKIP_CACHE_INVALIDATION=true -e AWS_ACCESS_KEY_ID=noop -e AWS_SECRET_ACCESS_KEY=noop efcms /bin/sh -c \ '(npx run-p start:api start:client:ci &) && ./wait-until.sh http://localhost:3000/api/swagger && ./wait-until.sh http://localhost:1234 && npm run test:pa11y' + docker run --rm -e SKIP_CACHE_INVALIDATION=true -e SLS_DEBUG=* -e AWS_ACCESS_KEY_ID=noop -e AWS_SECRET_ACCESS_KEY=noop efcms /bin/sh -c \ '(npx run-p start:api start:client:ci &) && ./wait-until.sh http://localhost:3000/api/swagger && ./wait-until.sh http://localhost:1234 && npm run cypress' diff --git a/docs/CASE_NAMES.md b/docs/CASE_NAMES.md new file mode 100644 index 00000000000..edd2c36eb08 --- /dev/null +++ b/docs/CASE_NAMES.md @@ -0,0 +1,22 @@ +# Case Names + +There are several values used throughout the system to identify cases by name. + +`caseCaptionWithPostfix`: +* Not stored directly on the case but can be computed when needed by appending the `CASE_CAPTION_POSTFIX` constant to the `caseCaption` +* Example: `Selma Horn & Cairo Harris, Petitioners v. Commissioner of Internal Revenue, Respondent` + +`caseCaption`: +* The only computed name value stored directly on the case in persistence +* Example: `Selma Horn & Cairo Harris, Petitioners` + +`caseTitle`: +* Not stored directly on the case - use method `Case.getCaseTitle(caseCaption)` to retrieve value +* Displayed in tables and work queues in the UI to identify a case for internal users +* Persisted on work items to be displayed in the work queues to eliminate the need to retrieve the value from each individual case +* Example: `Selma Horn & Cairo Harris` + +`caseCaptionExtension`: +* Not stored on the case, but can be computed by getting the `caseTitle` and replacing it with '' in the `caseCaption` +* Typically used in PDFs for proper case caption placement +* Example: `Petitioner(s)` \ No newline at end of file diff --git a/docs/TROUBLESHOOTING.md b/docs/TROUBLESHOOTING.md index 06209ef87b7..3e787a5fed1 100644 --- a/docs/TROUBLESHOOTING.md +++ b/docs/TROUBLESHOOTING.md @@ -15,6 +15,10 @@ If you're standing up a new environment, it is critical that you run the scripts > ``` ROLLBACK_COMPLETE ``` If you see this error in the AWS Cloudformation Stacks for your `$ENVIRONMENT`, there was an error configuring this stack. This stack will need to be DELETED prior to attempting to deploy again. We hope to identify the causes of these situations as well as avoid downtime by utilizing blue/green deploy strategies. +#### Limit for stack has been exceeded + +If the deploy process fails with `ServerlessError: Limit for stack has been exceeded`, that means that the number of stacks in CloudFormation has exceeded AWS’s allowable limits. By default, [the maximum number is 200](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cloudformation-limits.html), and AWS’s proposed solution is to "delete stacks that you don't need or request an increase in the maximum number of stacks in your AWS account." + #### repository xxxxx.dkr.ecr.us-east-1.amazonaws.com/ef-cms-us-east-1 not found > ```Error response from daemon: repository xxxxx.dkr.ecr.us-east-1.amazonaws.com/ef-cms-us-east-1 not found``` @@ -73,7 +77,7 @@ If this occurs, rerun the build. ``` Serverless Error --------------------------------------- - + ServerlessError: An error occurred: CasePublicSearchLambdaFunction - Code storage limit exceeded. (Service: AWSLambdaInternal; Status Code: 400; Error Code: CodeStorageExceededException ``` @@ -109,8 +113,6 @@ To revert your `serverless-prune-plugin`, just change `before` back to `after` o `[illegal_argument_exception] Limit of total fields [4000] in index [efcms] has been exceeded` -This error often occurs when we are indexing too many dynamic keys or nested objects with Elasticsearch and reach our total field limit. To investigate, run the command - -`./web-api/check-elasticsearch-mappings.sh [ENV]` +This error often occurs when we are indexing too many dynamic keys or nested objects with Elasticsearch and reach our total field limit. -The script will output data related to the mapping for the environment and can help pinpoint areas to look into further. To filter data from indexing, add fields or keys to the filtering functions in `processStreamRecordsInteractor.js`. \ No newline at end of file +The script will output data related to the mapping for the environment and can help pinpoint areas to look into further. To filter data from indexing, add fields or keys to the filtering functions in `processStreamRecordsInteractor.js`. diff --git a/docs/entities/Case.md b/docs/entities/Case.md index ecf218e8273..d98b54f9dfe 100644 --- a/docs/entities/Case.md +++ b/docs/entities/Case.md @@ -10,6 +10,11 @@ Restricted > `string` | optional +##### Maximum limit + + +`50` + ### automaticBlocked @@ -80,6 +85,11 @@ The name of the party bringing the case, e.g. "Carol Williams, Petitioner," "Mar > `string` | required +##### Maximum limit + + +`500` + ### caseId @@ -94,6 +104,11 @@ Restricted > `string` | optional +##### Maximum limit + + +`500` + ### caseType > `string` | required @@ -239,6 +254,11 @@ Case caption before modification. > `string` | optional +##### Maximum limit + + +`500` + ##### Can be null. ### initialDocketNumberSuffix @@ -248,6 +268,11 @@ Case docket number suffix before modification. > `string` | optional +##### Maximum limit + + +`2` + ##### Can be null. ### irsNoticeDate @@ -257,6 +282,11 @@ Last date that the petitioner is allowed to file before. > `date` | optional +##### Maximum date + + +`now` + ##### Can be null. ### irsPractitioners @@ -311,6 +341,13 @@ Reminder for clerks to review the notice of trial date. > `date` | optional +### orderDesignatingPlaceOfTrial + + +Reminder for clerks to review the Order Designating Place of Trial. + +> `boolean` | optional + ### orderForAmendedPetition @@ -761,7 +798,7 @@ Time of day when this case goes to trial. ##### Regex Pattern -`/^[0-9]+:([0-5][0-9])$/` +`/^[0-9]{1,2}:([0-5][0-9])$/` ### userId @@ -773,6 +810,11 @@ Restricted > `string` | optional +##### Maximum limit + + +`50` + ### workItems diff --git a/docs/entities/CaseDeadline.md b/docs/entities/CaseDeadline.md index d89d3c34204..110b63e438a 100644 --- a/docs/entities/CaseDeadline.md +++ b/docs/entities/CaseDeadline.md @@ -34,3 +34,19 @@ When the Case Deadline expires. User provided description of the Case Deadline. > `string` | required + +##### Maximum limit + + +`120` + +##### Minimum limit + + +`1` + +### entityName + +> `string` | required + +##### Can be CaseDeadline. diff --git a/docs/entities/DocketRecord.md b/docs/entities/DocketRecord.md index 5db452af047..3384831688e 100644 --- a/docs/entities/DocketRecord.md +++ b/docs/entities/DocketRecord.md @@ -37,6 +37,12 @@ Restricted ##### Can be null. +### entityName + +> `string` | required + +##### Can be DocketRecord. + ### eventCode @@ -408,6 +414,11 @@ Date that this Docket Record item was filed. > `date` | required +##### Maximum date + + +`now` + ### index diff --git a/docs/entities/Document.md b/docs/entities/Document.md index 499d308e22f..db3ba9bee43 100644 --- a/docs/entities/Document.md +++ b/docs/entities/Document.md @@ -14,6 +14,9 @@ ### archived + +A document that was archived instead of added to the Docket Record. + > `boolean` | optional ### caseId @@ -44,6 +47,15 @@ When the Document was added to the system. > `date` | required +### date + + +An optional date used when generating a fully concatenated document title. + +> `date` | optional + +##### Can be null. + ### docketNumber @@ -56,7 +68,17 @@ Docket Number of the associated Case in XXXXX-YY format. `/^(\d{3,5}-\d{2})$/` -### documentContents +### docketNumbers + + +Optional Docket Number text used when generating a fully concatenated document title. + +> `string` | optional + +### documentContentsId + + +The S3 ID containing the text contents of the document. > `string` | optional @@ -438,6 +460,12 @@ The type of this document. ##### Can be null. +### entityName + +> `string` | required + +##### Can be Document. + ### eventCode > `string` | optional @@ -455,6 +483,11 @@ Date that this Document was filed. > `date` | required +##### Maximum date + + +`now` + ### freeText > `string` | optional @@ -491,6 +524,12 @@ A lodged document is awaiting action by the judge to enact or refuse. > `boolean` | optional +### numberOfPages + +> `number` | optional + +##### Can be null. + ### objections > `string` | optional @@ -505,10 +544,16 @@ A lodged document is awaiting action by the judge to enact or refuse. ### partyPrimary + +Use the primary contact to compose the filedBy text. + > `boolean` | optional ### partySecondary + +Use the secondary contact to compose the filedBy text. + > `boolean` | optional ### pending @@ -521,8 +566,14 @@ A lodged document is awaiting action by the judge to enact or refuse. ### privatePractitioners + +Practitioner names to be used to compose the filedBy text. + > `array` | optional + +An array of objects. + ### processingStatus > `string` | optional @@ -531,10 +582,6 @@ A lodged document is awaiting action by the judge to enact or refuse. > `date` | optional -### qcByUser - -> `object` | optional - ### qcByUserId > `string` | optional @@ -549,10 +596,40 @@ A lodged document is awaiting action by the judge to enact or refuse. > `string` | optional +##### Allowed Values + + + - `primaryDocument` + - `primarySupportingDocument` + - `secondaryDocument` + - `secondarySupportingDocument` + - `supportingDocument` + ### scenario > `string` | optional +##### Allowed Values + + + - `Standard` + - `Nonstandard A` + - `Nonstandard B` + - `Nonstandard C` + - `Nonstandard D` + - `Nonstandard E` + - `Nonstandard F` + - `Nonstandard G` + - `Nonstandard H` + - `Type A` + - `Type B` + - `Type C` + - `Type D` + - `Type E` + - `Type F` + - `Type G` + - `Type H` + ### secondaryDate @@ -560,11 +637,10 @@ A secondary date associated with the document, typically related to time-restric > `date` | optional -### secondaryDocument +### servedAt -> `object` | optional -### servedAt +When the document is served on the parties. > `date` | optional @@ -572,10 +648,21 @@ A secondary date associated with the document, typically related to time-restric > `array` | optional + +An array of objects. + ### serviceDate + +Certificate of service date. + > `date` | optional +##### Maximum date + + +`now` + ##### Can be null. ### serviceStamp @@ -600,12 +687,6 @@ A secondary date associated with the document, typically related to time-restric ##### Can be null. -### status - -> `string` | optional - -##### Can be served. - ### supportingDocument > `string` | optional @@ -614,105 +695,10 @@ A secondary date associated with the document, typically related to time-restric ### trialLocation -> `conditional` | optional - - -*Must match 1 of the following conditions:* - -#### Condition #1 for `trialLocation`: - -> `string` -##### Allowed Values - - - - `Fresno, California` - - `Tallahassee, Florida` - - `Pocatello, Idaho` - - `Peoria, Illinois` - - `Wichita, Kansas` - - `Shreveport, Louisiana` - - `Portland, Maine` - - `Billings, Montana` - - `Albany, New York` - - `Syracuse, New York` - - `Bismarck, North Dakota` - - `Aberdeen, South Dakota` - - `Burlington, Vermont` - - `Roanoke, Virginia` - - `Cheyenne, Wyoming` - - `Birmingham, Alabama` - - `Mobile, Alabama` - - `Anchorage, Alaska` - - `Phoenix, Arizona` - - `Little Rock, Arkansas` - - `Los Angeles, California` - - `San Diego, California` - - `San Francisco, California` - - `Denver, Colorado` - - `Hartford, Connecticut` - - `Washington, District of Columbia` - - `Jacksonville, Florida` - - `Miami, Florida` - - `Tampa, Florida` - - `Atlanta, Georgia` - - `Honolulu, Hawaii` - - `Boise, Idaho` - - `Chicago, Illinois` - - `Indianapolis, Indiana` - - `Des Moines, Iowa` - - `Louisville, Kentucky` - - `New Orleans, Louisiana` - - `Baltimore, Maryland` - - `Boston, Massachusetts` - - `Detroit, Michigan` - - `St. Paul, Minnesota` - - `Jackson, Mississippi` - - `Kansas City, Missouri` - - `St. Louis, Missouri` - - `Helena, Montana` - - `Omaha, Nebraska` - - `Las Vegas, Nevada` - - `Reno, Nevada` - - `Albuquerque, New Mexico` - - `Buffalo, New York` - - `New York City, New York` - - `Winston-Salem, North Carolina` - - `Cincinnati, Ohio` - - `Cleveland, Ohio` - - `Columbus, Ohio` - - `Oklahoma City, Oklahoma` - - `Portland, Oregon` - - `Philadelphia, Pennsylvania` - - `Pittsburgh, Pennsylvania` - - `Columbia, South Carolina` - - `Knoxville, Tennessee` - - `Memphis, Tennessee` - - `Nashville, Tennessee` - - `Dallas, Texas` - - `El Paso, Texas` - - `Houston, Texas` - - `Lubbock, Texas` - - `San Antonio, Texas` - - `Salt Lake City, Utah` - - `Richmond, Virginia` - - `Seattle, Washington` - - `Spokane, Washington` - - `Charleston, West Virginia` - - `Milwaukee, Wisconsin` - -#### Condition #2 for `trialLocation`: - -> `string` - -##### Regex Pattern +An optional trial location used when generating a fully concatenated document title. - -`/^[a-zA-Z ]+, [a-zA-Z ]+, [0-9]+$/` - -#### Condition #3 for `trialLocation`: - -> `string` +> `string` | optional ##### Can be null. diff --git a/docs/images/client-dependencies.jpg b/docs/images/client-dependencies.jpg index 25530d3cb19..7505698dc5e 100644 Binary files a/docs/images/client-dependencies.jpg and b/docs/images/client-dependencies.jpg differ diff --git a/docs/images/server-dependencies.jpg b/docs/images/server-dependencies.jpg index f8e38500041..6826f0dda84 100644 Binary files a/docs/images/server-dependencies.jpg and b/docs/images/server-dependencies.jpg differ diff --git a/docs/zap-report.html b/docs/zap-report.html index 5512b7df2d9..dbaae9e97ab 100644 --- a/docs/zap-report.html +++ b/docs/zap-report.html @@ -85,13 +85,13 @@

Summary of Alerts

High0 - Medium1 + Medium0 - Low4 + Low1 - Informational3 + Informational2
@@ -101,1128 +101,138 @@

Alerts

NameRisk LevelNumber of Instances - Cross-Domain MisconfigurationMedium10 + Strict-Transport-Security Header Not SetLow1 - Content Security Policy (CSP) Header Not SetLow1 + A Client Error response code was returned by the serverInformational9 - Cross-Domain JavaScript Source File InclusionLow1 - - - Strict-Transport-Security Header Not SetLow207 - - - Unexpected Content-Type was returnedLow872 - - - A Client Error response code was returned by the serverInformational2104 - - - ELMAH Information LeakInformational1 - - - Timestamp Disclosure - UnixInformational10 - - -
-

Alert Detail

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Medium (Medium)Cross-Domain Misconfiguration
Description

Web browser data loading may be possible, due to a Cross Origin Resource Sharing (CORS) misconfiguration on the web server

URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/documents/filing-receipt-pdf
MethodPOST
EvidenceAccess-Control-Allow-Origin: *
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/documents/documentId/validate
MethodPOST
EvidenceAccess-Control-Allow-Origin: *
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/case-documents/caseId/documentId/document-download-url
MethodGET
EvidenceAccess-Control-Allow-Origin: *
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/public-api/search
MethodGET
EvidenceAccess-Control-Allow-Origin: *
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/public-api/caseId/documentId/public-document-download-url
MethodGET
EvidenceAccess-Control-Allow-Origin: *
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/documents/documentId/virus-scan
MethodPOST
EvidenceAccess-Control-Allow-Origin: *
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/public-api/cases/caseId
MethodGET
EvidenceAccess-Control-Allow-Origin: *
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/api/swagger
MethodGET
EvidenceAccess-Control-Allow-Origin: *
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/public-api/order-search
MethodGET
EvidenceAccess-Control-Allow-Origin: *
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/api/swagger.json
MethodGET
EvidenceAccess-Control-Allow-Origin: *
Instances10
Solution

Ensure that sensitive data is not available in an unauthenticated manner (using IP address white-listing, for instance).

Configure the "Access-Control-Allow-Origin" HTTP header to a more restrictive set of domains, or remove all CORS headers entirely, to allow the web browser to enforce the Same Origin Policy (SOP) in a more restrictive manner.

Other information

The CORS misconfiguration on the web server permits cross-domain read requests from arbitrary third party domains, using unauthenticated APIs on this domain. Web browser implementations do not permit arbitrary third parties to read the response from authenticated APIs, however. This reduces the risk somewhat. This misconfiguration could be used by an attacker to access data that is available in an unauthenticated manner, but which uses some other form of security, such as IP address white-listing.

Reference

http://www.hpenterprisesecurity.com/vulncat/en/vulncat/vb/html5_overly_permissive_cors_policy.html

CWE Id264
WASC Id14
Source ID3
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Low (Medium)Content Security Policy (CSP) Header Not Set
Description

Content Security Policy (CSP) is an added layer of security that helps to detect and mitigate certain types of attacks, including Cross Site Scripting (XSS) and data injection attacks. These attacks are used for everything from data theft to site defacement or distribution of malware. CSP provides a set of standard HTTP headers that allow website owners to declare approved sources of content that browsers should be allowed to load on that page — covered types are JavaScript, CSS, HTML frames, fonts, images and embeddable objects such as Java applets, ActiveX, audio and video files.

URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/api/swagger
MethodGET
Instances1
Solution

Ensure that your web server, application server, load balancer, etc. is configured to set the Content-Security-Policy header, to achieve optimal browser support: "Content-Security-Policy" for Chrome 25+, Firefox 23+ and Safari 7+, "X-Content-Security-Policy" for Firefox 4.0+ and Internet Explorer 10+, and "X-WebKit-CSP" for Chrome 14+ and Safari 6+.

Reference

https://developer.mozilla.org/en-US/docs/Web/Security/CSP/Introducing_Content_Security_Policy

https://www.owasp.org/index.php/Content_Security_Policy

http://www.w3.org/TR/CSP/

http://w3c.github.io/webappsec/specs/content-security-policy/csp-specification.dev.html

http://www.html5rocks.com/en/tutorials/security/content-security-policy/

http://caniuse.com/#feat=contentsecuritypolicy

http://content-security-policy.com/

CWE Id16
WASC Id15
Source ID3
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Low (Medium)Cross-Domain JavaScript Source File Inclusion
Description

The page includes one or more script files from a third-party domain.

URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/api/swagger
MethodGET
Parameterhttps://cdnjs.cloudflare.com/ajax/libs/swagger-ui/3.24.2/swagger-ui-bundle.js
Evidence<script src="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/3.24.2/swagger-ui-bundle.js"></script>
Instances1
Solution

Ensure JavaScript source files are loaded from only trusted sources, and the sources can't be controlled by end users of the application.

Reference

CWE Id829
WASC Id15
Source ID3
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Low (High)Strict-Transport-Security Header Not Set
Description

HTTP Strict Transport Security (HSTS) is a web security policy mechanism whereby a web server declares that complying user agents (such as a web browser) are to interact with it using only secure HTTPS connections (i.e. HTTP layered over TLS/SSL). HSTS is an IETF standards track protocol and is specified in RFC 6797.

URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/practitioners/barNumber
MethodGET
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/cases/caseId
MethodGET
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/case-documents/caseId/court-issued-orders/documentId
MethodPUT
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/case-deadlines/caseId/caseDeadlineId
MethodDELETE
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/users/userId/document-qc/served
MethodGET
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/case-documents/caseId/court-issued-docket-entry
MethodOPTION
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/practitioners?name=ZAP
MethodPOST
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/public-api/order-search
MethodOPTION
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/case-documents/caseId/docket-entry
MethodPUT
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/case-meta/caseId/consolidate-case
MethodPUT
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/case-documents/caseId/docket-entry-meta
MethodPUT
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/case-parties/caseId/petitioner-info
MethodOPTION
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/irsPractitioners/respondentId/cases
MethodGET
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/api/court-issued-order
MethodOPTION
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/case-parties/caseId/petition-details
MethodPUT
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/users/userId/contact-info
MethodOPTION
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/users
MethodOPTION
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/users/userId/case/caseId/pending
MethodPUT
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/case-parties/caseId/counsel/userId
MethodPUT
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/api/cases/caseId/generate-docket-record
MethodOPTION
Instances207
Solution

Ensure that your web server, application server, load balancer, etc. is configured to enforce Strict-Transport-Security.

Reference

https://www.owasp.org/index.php/HTTP_Strict_Transport_Security

https://www.owasp.org/index.php/List_of_useful_HTTP_headers

http://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security

http://caniuse.com/stricttransportsecurity

http://tools.ietf.org/html/rfc6797

CWE Id16
WASC Id15
Source ID3
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Low (High)Unexpected Content-Type was returned
Description

A Content-Type of null was returned by the server.

This is not one of the types expected to be returned by an API.

Raised by the 'Alert on Unexpected Content Types' script

URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/reports/case-inventory-report?associatedJudge=associatedJudge&from=1.2%26sleep+15%26&pageSize=1.2&status=status
MethodOPTION
Evidencenull
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/case-meta/caseId/high-priority/
MethodOPTION
Evidencenull
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/reports/case-inventory-report?associatedJudge=associatedJudge&from=1.2&pageSize=1.2&status=any%3F%0D%0ASet-cookie%3A+Tamper%3D065a5613-315d-40e3-bc6c-b9267111449e%0D%0A
MethodOPTION
Evidencenull
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/reports/printable-case-inventory-report?associatedJudge=associatedJudge%27+AND+%271%27%3D%271%27+--+&status=status
MethodOPTION
Evidencenull
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/reports/case-inventory-report?associatedJudge=associatedJudge&from=1.2&pageSize=www.google.com&status=status
MethodOPTION
Evidencenull
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/reports/case-inventory-report?associatedJudge=associatedJudge&from=1.2%27%7Ctimeout+%2FT+15&pageSize=1.2&status=status
MethodOPTION
Evidencenull
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/reports/printable-case-inventory-report?associatedJudge=%22%3Bprint%28chr%28122%29.chr%2897%29.chr%28112%29.chr%2895%29.chr%28116%29.chr%28111%29.chr%28107%29.chr%28101%29.chr%28110%29%29%3B%24var%3D%22&status=status
MethodOPTION
Evidencenull
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/reports/case-inventory-report?associatedJudge=associatedJudge&from=1.2&pageSize=1.2&status=%24%7B%40print%28chr%28122%29.chr%2897%29.chr%28112%29.chr%2895%29.chr%28116%29.chr%28111%29.chr%28107%29.chr%28101%29.chr%28110%29%29%7D
MethodOPTION
Evidencenull
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/practitioners?name=ZAP%27%29+UNION+ALL+select+NULL+--+
MethodOPTION
Evidencenull
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/reports/case-inventory-report?associatedJudge=%22%27&from=1.2&pageSize=1.2&status=status
MethodOPTION
Evidencenull
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/reports/case-inventory-report?associatedJudge=associatedJudge&from=1.2&pageSize=1.2&status=http%3A%2F%2F594803987206587882.owasp.org
MethodOPTION
Evidencenull
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/work-items/workItemId/
MethodOPTION
Evidencenull
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/reports/printable-case-inventory-report?associatedJudge=associatedJudge&status=HtTpS%3A%2F%2F594803987206587882.owasp.org
MethodOPTION
Evidencenull
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/reports/case-inventory-report?associatedJudge=%22%3E%3C%21--%23EXEC+cmd%3D%22ls+%2F%22--%3E%3C&from=1.2&pageSize=1.2&status=status
MethodOPTION
Evidencenull
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/reports/case-inventory-report?associatedJudge=associatedJudge&from=1.2&pageSize=1.2&status=%2F%2F594803987206587882.owasp.org
MethodOPTION
Evidencenull
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/reports/case-inventory-report?associatedJudge=associatedJudge&from=1.2&pageSize=1.2%3B&status=status
MethodOPTION
Evidencenull
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/case-meta/caseId/qc-complete
MethodOPTION
Evidencenull
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/reports/printable-case-inventory-report?associatedJudge=associatedJudge%29+WAITFOR+DELAY+%270%3A0%3A15%27+--+&status=status
MethodOPTION
Evidencenull
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/practitioners?name=http%3A%2F%2F594803987206587882.owasp.org
MethodOPTION
Evidencenull
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/reports/printable-case-inventory-report?associatedJudge=associatedJudge&status=%3B
MethodOPTION
Evidencenull
Instances872
Solution

Reference

Source ID4
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +
Informational (High)A Client Error response code was returned by the server
Description

A response code of 405 was returned by the server.

This may indicate that the application is failing to handle unexpected input correctly.

Raised by the 'Alert on HTTP Response Code Error' script

URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/reports/case-inventory-report?associatedJudge=associatedJudge&from=1.2&pageSize=1.2&status=status%29+UNION+ALL+select+NULL+--+
MethodOPTION
EvidenceHTTP/1.1 405
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/practitioners?name=%3B
MethodPOST
EvidenceHTTP/1.1 401
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/reports/printable-case-inventory-report?associatedJudge=associatedJudge%26cat+%2Fetc%2Fpasswd%26&status=status
MethodGET
EvidenceHTTP/1.1 401ELMAH Information LeakInformational1
+
+

Alert Detail

+
+ - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - + + + + - + - - - - - + - + - + - - - + - + - + + +
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/case-parties/caseId/contact-secondary
MethodPUT
EvidenceHTTP/1.1 401
Low (High)Strict-Transport-Security Header Not Set
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/reports/case-inventory-report?associatedJudge=associatedJudge&from=1.2&pageSize=1.2&status=ZAP
MethodOPTION
EvidenceHTTP/1.1 405
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/practitioners?name=%5D%5D%3E
MethodPOST
EvidenceHTTP/1.1 401Description

HTTP Strict Transport Security (HSTS) is a web security policy mechanism whereby a web server declares that complying user agents (such as a web browser) are to interact with it using only secure HTTPS connections (i.e. HTTP layered over TLS/SSL). HSTS is an IETF standards track protocol and is specified in RFC 6797.

URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/reports/printable-case-inventory-report?associatedJudge=associatedJudge&status=%27URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/api/swagger.json
MethodGET
EvidenceHTTP/1.1 401
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/reports/printable-case-inventory-report?associatedJudge=594803987206587882.owasp.org&status=statusInstances1
MethodGETSolution

Ensure that your web server, application server, load balancer, etc. is configured to enforce Strict-Transport-Security.

EvidenceHTTP/1.1 401Reference

https://www.owasp.org/index.php/HTTP_Strict_Transport_Security

https://www.owasp.org/index.php/List_of_useful_HTTP_headers

http://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security

http://caniuse.com/stricttransportsecurity

http://tools.ietf.org/html/rfc6797

URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/practitioners?name=ZAP%22%26timeout+%2FT+15%26%22CWE Id16
MethodGETWASC Id15
EvidenceHTTP/1.1 401Source ID3
+
+ - - - - - - - - - - + + + - - - - - - - - - + + + + - + - + - + - + - + - + - + - + - + - + @@ -1236,35 +246,35 @@

Alert Detail

- + - + - + - + - + - + - + @@ -1272,13 +282,13 @@

Alert Detail

- + - + @@ -1286,13 +296,13 @@

Alert Detail

- + - + @@ -1300,13 +310,13 @@

Alert Detail

- + - + @@ -1397,198 +407,5 @@

Alert Detail

URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/reports/case-inventory-report?associatedJudge=associatedJudge&from=1.2&pageSize=1.2&status=status%22%26timeout+%2FT+15%26%22
MethodOPTION
EvidenceHTTP/1.1 405
Informational (High)A Client Error response code was returned by the server
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/api/cases/caseId/generate-docket-record/
MethodPOST
EvidenceHTTP/1.1 403Description

A response code of 401 was returned by the server.

This may indicate that the application is failing to handle unexpected input correctly.

Raised by the 'Alert on HTTP Response Code Error' script

URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/reports/case-inventory-report?associatedJudge=associatedJudge%22+UNION+ALL+select+NULL+--+&from=1.2&pageSize=1.2&status=statusURLhttps://efcms-dev.ustc-case-mgmt.flexion.us/api/swagger.json
MethodOPTIONMethodGET
EvidenceHTTP/1.1 405EvidenceHTTP/1.1 401
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/reports/printable-case-inventory-report?associatedJudge=associatedJudge&status=https%3A%5C%5C594803987206587882.owasp.orgURLhttps://efcms-dev.ustc-case-mgmt.flexion.us/api/424448955668695100
MethodOPTIONMethodGET
EvidenceHTTP/1.1 405EvidenceHTTP/1.1 403
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/practitioners/URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/
MethodPOSTMethodGET
EvidenceHTTP/1.1 401EvidenceHTTP/1.1 403
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/reports/case-inventory-report?associatedJudge=associatedJudge&from=1.2&pageSize=1.2&status=any%0D%0ASet-cookie%3A+Tamper%3D414225ba-8d11-4208-aff0-2c95401cad39URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/api/swagger.json/
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/practitioners?name=PLuxhWSkINMCEKTmFvNaWgYZibSGsHLLrfcoKDQJduXCLQLvADFoHElKwXmHIkEteEmnsxOkrlYhYfMFiaKOhphjRFRhYeqJtWQljVBpMpHcFUgpwQjEGlnbAmgQBXQYvjwEFsskLycXGSvxqTSLbLBXxicuLEIaIQfDFwuXmyEayaEEgtiZZGllnEWMTQLWqkTgjnbAdRJptSPJsEZIpXGHWUGrvuLQoEOmtmvHPQgMnUTjBoobtcmudNVUiuBbHIUhkbJjslmWXgpiqpHNgoKJyLLuOJMQqEIufGSWKhATosVaXgESEiUkJTXvcbNPQYhLtPQRGCtGTEuHBwoRTEjEACPGbfiNEImGChkgdTCSbVqDQoIXHaoZsXBhMRewIhqiYYxVoTUiGqClRChyPSOVZMgrIIdnscPGIPZYsTHnCnqsHAerCsLoTWhcPKUVcUQyflJZFwZENNkoLZMmATUIdUbPiksEOPWQlwQuAtlelZdKyCYXugCykOvHQUwSPKLSEKWGNrblGIbRFIhRSLdnxIaDmTifVnKflVtqEZvnEUgVOfOfTlMgTQmIaJibEeaHPPQOtEtiMFLaXfCkVNyRfldUsSaKPkpwPdVOtKoNArViJghFEuBQJHyCqGxtujKCWaCTxeugWvTtrBrbSVnZsRfqCvcaMOWyfoExQjLRcQUhHboiuDRPIHXKlhLFDwJmTSZACCpSeXTXaUOTiEFkPuTHNOiXPKrUNSpBVIPAnYYvSbMCbUZpFJfISpFnstEgalvPuXyHodXLrmQfBtIwGNSGMBVDccvMkKniKUfovpvexFGPOeqdhlHnOcyiHwIgxuOBpErBZynCeVmQBZNyrWoMCobxsTEWpJHSebitPyKKLXjVHCKFnfhNksSOaSVLJspAAJFOcqkoNeHpYsNrEBKvCpObbAfnDOKOHTJxuvgEwLQFIkNBoguCeCiVmlGElMNhGcDFGxDvVroKBLUIxDxhHYLjsHsSyfcNfqwnAvbMMyVOVBdBDTeGkTgcXMGePOVqZSGpComnJxycdpasjyRqMqFEbiaVYgohoXyalPTgCqSdknXnHnQAVxhFyOIYGDYQvtFTPArIgrfAqpkytLQBUBGnrTMoraDHCdWvXSinCWJeyrIMutlNoexhFnZArANdXOFgtsdMXSAHYWQDAUBvlNgufgFPVfWJUVuhYngCTmglnTekWhcMeQxDGSAGrmEyBaMoVJwwCVgXCEXHvNTOVxEUOCkIUmxxkMcsjdeSNWZXngUBdhmthYRTbSpfrLUvdANLPFPsLklssKrwSpoBQtHtVXHZqiSaofqQUZpJOTQHtjrySGFDajikRmysjLObLUEJRafDXKgVUpOVxpLiFaPOCdATrmKFRcndTiZJecjWhLUgqEaUHnavVyeiKbGegApvxHgVarBAdupSywjHBqAJTwXCyntPrcLwmaOQeiCKWNeAZMYeqIjjwrjPVSSZIUdmRHHwwMEnjZpuiylYhQyshNCEDPpjLfMQRHhQebvfgHEbnjprhMPevQiuPJLaZpbbdfxFUiOqsmdwlZhfTuFvMklEVfWPMVhSpMouPoYAAuErInsFedXqevyNllnLRPQQTGJpVOKAueupQhuRsqXBtciVydgrEDRrLrbmOFTqHIOOEfQsqbmpHYmhDWVinULWtkAViLtElLcYjriinuGMCDtavBZITiCWkJMVMuOykCFUxjkUAucUkFlhkTJNurjQEwNHThZeyKNqsArDwTVsbeMpMMjDqWdnUYiSkVxJXyoWovfIalBowkroCEnCKdTMJJulUEZxwZnBIcBXDuRrMGssgoQvjEYxAOjObCCwwTMgZdWLedeMwJyDJyYUKqLYJuYpWhrvhcIDRXZAlDVIobXGQuwalGlIxUyfJhOSEaTADHyHYXpVhBXEIqsSZdDWRgfpsgJGyGukNQbOMsaARehgqCGlqfJDNQnQfcCpfKVWqPdCxQYTUulWBolnruftfjlVjiOHsrfQuGrWjOGVTNFJowZRjGLwEZaIejBjgvTfRvPwdOwGJCswSBxKhnRqeJRIqIZwDawViPoISZsDvxduUNPTLyiExanVjXnZURLhttps://efcms-dev.ustc-case-mgmt.flexion.us
MethodPOSTMethodGET
EvidenceHTTP/1.1 401EvidenceHTTP/1.1 403
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/case-parties/caseId/petitioner-infoURLhttps://efcms-dev.ustc-case-mgmt.flexion.us/api
MethodOPTIONMethodGET
EvidenceHTTP/1.1 405EvidenceHTTP/1.1 403
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/reports/case-inventory-report?associatedJudge=%2F%2F594803987206587882.owasp.org&from=1.2&pageSize=1.2&status=statusURLhttps://efcms-dev.ustc-case-mgmt.flexion.us/721854983376784850
EvidenceHTTP/1.1 401EvidenceHTTP/1.1 403
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/public-api/cases/caseId/URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/api/
EvidenceHTTP/1.1 404EvidenceHTTP/1.1 403
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/practitioners?name=any%3F%0ASet-cookie%3A+Tamper%3D3b37a7e6-70e3-4d5d-84b0-d553581563ecURLhttps://efcms-dev.ustc-case-mgmt.flexion.us/elmah.axd
EvidenceHTTP/1.1 401EvidenceHTTP/1.1 403
Instances2104Instances9
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Informational (Low)Timestamp Disclosure - Unix
Description

A timestamp was disclosed by the application/web server - Unix

URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/reports/pending-report
MethodOPTION
Evidence09261399
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/public-api/order-search
MethodGET
Evidence53178981
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/api/docket-record-pdf
MethodPOST
Evidence58954958
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/case-documents/caseId/docket-entry
MethodPOST
Evidence29042066
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/trial-sessions/trialSessionId/getAssociatedCases
MethodOPTION
Evidence75814246
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/case-meta/caseId/block
MethodOPTION
Evidence18152264
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/public-api/order-search
MethodGET
Evidence08439178
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/case-documents/caseId/documentId/document-download-url
MethodOPTION
Evidence12282687
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/sections/section/users
MethodGET
Evidence93232388
URLhttps://efcms-dev.ustc-case-mgmt.flexion.us/reports/printable-case-inventory-report?associatedJudge=associatedJudge&status=status
MethodOPTION
Evidence07827687
Instances10
Solution

Manually confirm that the timestamp data is not sensitive, and that the data cannot be aggregated to disclose exploitable patterns.

Other information

09261399, which evaluates to: 1970-04-18 04:36:39

Reference

https://www.owasp.org/index.php/Top_10_2013-A6-Sensitive_Data_Exposure

http://projects.webappsec.org/w/page/13246936/Information%20Leakage

CWE Id200
WASC Id13
Source ID3
diff --git a/enzyme.config.js b/enzyme.config.js new file mode 100644 index 00000000000..4ded99e3158 --- /dev/null +++ b/enzyme.config.js @@ -0,0 +1,4 @@ +const Adapter = require('enzyme-adapter-react-16'); +const { configure } = require('enzyme'); + +configure({ adapter: new Adapter() }); diff --git a/iam/terraform/account-specific/main/circle-ci.tf b/iam/terraform/account-specific/main/circle-ci.tf index 31bf42c8b62..766575def99 100644 --- a/iam/terraform/account-specific/main/circle-ci.tf +++ b/iam/terraform/account-specific/main/circle-ci.tf @@ -54,7 +54,8 @@ resource "aws_iam_policy" "circle_ci_policy" { "cognito-idp:DescribeUserPoolDomain", "cognito-idp:SetUICustomization", "cognito-idp:DeleteUserPoolDomain", - "cognito-idp:GetUserPoolMfaConfig" + "cognito-idp:GetUserPoolMfaConfig", + "cognito-idp:SetUserPoolMfaConfig" ], "Resource": "*" }, diff --git a/iam/terraform/environment-specific/main/cognito-authorizer.tf b/iam/terraform/environment-specific/main/cognito-authorizer.tf new file mode 100644 index 00000000000..388013af66a --- /dev/null +++ b/iam/terraform/environment-specific/main/cognito-authorizer.tf @@ -0,0 +1,50 @@ + +resource "aws_iam_role_policy" "authorizer_invocation_policy" { + name = "cognito_authorizer_policy_${var.environment}" + role = "${aws_iam_role.authorizer_lambda.id}" + + policy = < { + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, + }); + + return new Promise(resolve => + rl.question(query, ans => { + rl.close(); + resolve(ans); + }), + ); +}; + +const registerUser = async () => { + let response; + + response = await cognito + .initiateAuth({ + AuthFlow: 'USER_PASSWORD_AUTH', + AuthParameters: { + PASSWORD: 'Testing1234$', + USERNAME: email, + }, + ClientId, + }) + .promise(); + console.log('logged in'); + + if (response.ChallengeName === 'NEW_PASSWORD_REQUIRED') { + response = await cognito + .respondToAuthChallenge({ + ChallengeName: 'NEW_PASSWORD_REQUIRED', + ChallengeResponses: { + NEW_PASSWORD: 'Testing1234$', + USERNAME: email, + }, + ClientId, + Session: response.Session, + }) + .promise(); + } + console.log('password changed'); + + response = await cognito + .initiateAuth({ + AuthFlow: 'USER_PASSWORD_AUTH', + AuthParameters: { + PASSWORD: 'Testing1234$', + USERNAME: email, + }, + ClientId, + }) + .promise(); + console.log('logged in second time'); + + if (response.ChallengeName === 'MFA_SETUP') { + response = await cognito + .associateSoftwareToken({ + Session: response.Session, + }) + .promise(); + + console.log('associate software'); + console.log('your secret code: ', response.SecretCode); + + const UserCode = await askQuestion('enter your MFA code\n'); + + response = await cognito + .verifySoftwareToken({ + Session: response.Session, + UserCode, + }) + .promise(); + } + return response; +}; + +const login = async () => { + let response = await cognito + .initiateAuth({ + AuthFlow: 'USER_PASSWORD_AUTH', + AuthParameters: { + PASSWORD: 'Testing1234$', + USERNAME: email, + }, + ClientId, + }) + .promise(); + + console.log(response); + + if (response.ChallengeName === 'SOFTWARE_TOKEN_MFA') { + const mfa = await askQuestion('enter your MFA code\n'); + response = await cognito + .respondToAuthChallenge({ + ChallengeName: 'SOFTWARE_TOKEN_MFA', + ChallengeResponses: { + SOFTWARE_TOKEN_MFA_CODE: mfa, + USERNAME: email, + }, + ClientId, + Session: response.Session, + }) + .promise(); + console.log(response); + } +}; + +const main = async () => { + await registerUser(); + await login(); +}; +main(); diff --git a/jest.config.js b/jest.config.js index e0f3e35466c..bc147069230 100644 --- a/jest.config.js +++ b/jest.config.js @@ -14,5 +14,6 @@ module.exports = { statements: 95, }, }, + setupFilesAfterEnv: [`${__dirname}/enzyme.config.js`], verbose: false, }; diff --git a/package-lock.json b/package-lock.json index fa5eb605b11..a0cecb8aa0c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -79,30 +79,30 @@ } }, "@babel/compat-data": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.9.0.tgz", - "integrity": "sha512-zeFQrr+284Ekvd9e7KAX954LkapWiOmQtsfHirhxqfdlX6MEC32iRE+pqUGlYIBchdevaCwvzxWGSy/YBNI85g==", + "version": "7.9.6", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.9.6.tgz", + "integrity": "sha512-5QPTrNen2bm7RBc7dsOmcA5hbrS4O2Vhmk5XOL4zWW/zD/hV0iinpefDlkm+tBBy8kDtFaaeEvmAqt+nURAV2g==", "dev": true, "requires": { - "browserslist": "^4.9.1", + "browserslist": "^4.11.1", "invariant": "^2.2.4", "semver": "^5.5.0" } }, "@babel/core": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.9.0.tgz", - "integrity": "sha512-kWc7L0fw1xwvI0zi8OKVBuxRVefwGOrKSQMvrQ3dW+bIIavBY3/NpXmpjMy7bQnLgwgzWQZ8TlM57YHpHNHz4w==", + "version": "7.9.6", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.9.6.tgz", + "integrity": "sha512-nD3deLvbsApbHAHttzIssYqgb883yU/d9roe4RZymBCDaZryMJDbptVpEpeQuRh4BJ+SYI8le9YGxKvFEvl1Wg==", "dev": true, "requires": { "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.9.0", + "@babel/generator": "^7.9.6", "@babel/helper-module-transforms": "^7.9.0", - "@babel/helpers": "^7.9.0", - "@babel/parser": "^7.9.0", + "@babel/helpers": "^7.9.6", + "@babel/parser": "^7.9.6", "@babel/template": "^7.8.6", - "@babel/traverse": "^7.9.0", - "@babel/types": "^7.9.0", + "@babel/traverse": "^7.9.6", + "@babel/types": "^7.9.6", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.1", @@ -131,12 +131,12 @@ } }, "@babel/generator": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.5.tgz", - "integrity": "sha512-GbNIxVB3ZJe3tLeDm1HSn2AhuD/mVcyLDpgtLXa5tplmWrJdF/elxB56XNqCuD6szyNkDi6wuoKXln3QeBmCHQ==", + "version": "7.9.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.6.tgz", + "integrity": "sha512-+htwWKJbH2bL72HRluF8zumBxzuX0ZZUFl3JLNyoUjM/Ho8wnVpPXM6aUz8cfKDqQ/h7zHqKt4xzJteUosckqQ==", "dev": true, "requires": { - "@babel/types": "^7.9.5", + "@babel/types": "^7.9.6", "jsesc": "^2.5.1", "lodash": "^4.17.13", "source-map": "^0.5.0" @@ -183,13 +183,13 @@ } }, "@babel/helper-compilation-targets": { - "version": "7.8.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.7.tgz", - "integrity": "sha512-4mWm8DCK2LugIS+p1yArqvG1Pf162upsIsjE7cNBjez+NjliQpVhj20obE520nao0o14DaTnFJv+Fw5a0JpoUw==", + "version": "7.9.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.9.6.tgz", + "integrity": "sha512-x2Nvu0igO0ejXzx09B/1fGBxY9NXQlBW2kZsSxCJft+KHN8t9XWzIvFxtPHnBOAXpVsdxZKZFbRUC8TsNKajMw==", "dev": true, "requires": { - "@babel/compat-data": "^7.8.6", - "browserslist": "^4.9.1", + "@babel/compat-data": "^7.9.6", + "browserslist": "^4.11.1", "invariant": "^2.2.4", "levenary": "^1.1.1", "semver": "^5.5.0" @@ -327,15 +327,15 @@ } }, "@babel/helper-replace-supers": { - "version": "7.8.6", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.8.6.tgz", - "integrity": "sha512-PeMArdA4Sv/Wf4zXwBKPqVj7n9UF/xg6slNRtZW84FM7JpE1CbG8B612FyM4cxrf4fMAMGO0kR7voy1ForHHFA==", + "version": "7.9.6", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.9.6.tgz", + "integrity": "sha512-qX+chbxkbArLyCImk3bWV+jB5gTNU/rsze+JlcF6Nf8tVTigPJSI1o1oBow/9Resa1yehUO9lIipsmu9oG4RzA==", "dev": true, "requires": { "@babel/helper-member-expression-to-functions": "^7.8.3", "@babel/helper-optimise-call-expression": "^7.8.3", - "@babel/traverse": "^7.8.6", - "@babel/types": "^7.8.6" + "@babel/traverse": "^7.9.6", + "@babel/types": "^7.9.6" } }, "@babel/helper-simple-access": { @@ -376,14 +376,14 @@ } }, "@babel/helpers": { - "version": "7.9.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.9.2.tgz", - "integrity": "sha512-JwLvzlXVPjO8eU9c/wF9/zOIN7X6h8DYf7mG4CiFRZRvZNKEF5dQ3H3V+ASkHoIB3mWhatgl5ONhyqHRI6MppA==", + "version": "7.9.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.9.6.tgz", + "integrity": "sha512-tI4bUbldloLcHWoRUMAj4g1bF313M/o6fBKhIsb3QnGVPwRm9JsNf/gqMkQ7zjqReABiffPV6RWj7hEglID5Iw==", "dev": true, "requires": { "@babel/template": "^7.8.3", - "@babel/traverse": "^7.9.0", - "@babel/types": "^7.9.0" + "@babel/traverse": "^7.9.6", + "@babel/types": "^7.9.6" } }, "@babel/highlight": { @@ -398,9 +398,9 @@ } }, "@babel/parser": { - "version": "7.9.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.4.tgz", - "integrity": "sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA==", + "version": "7.9.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.6.tgz", + "integrity": "sha512-AoeIEJn8vt+d/6+PXDRPaksYhnlbMIiejioBZvvMQsOjW/JYK6k/0dKnvvP3EhK5GfMBWDPtrxRtegWdAcdq9Q==", "dev": true }, "@babel/plugin-proposal-async-generator-functions": { @@ -455,9 +455,9 @@ } }, "@babel/plugin-proposal-object-rest-spread": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.9.5.tgz", - "integrity": "sha512-VP2oXvAf7KCYTthbUHwBlewbl1Iq059f6seJGsxMizaCdgHIeczOr7FBqELhSqfkIl04Fi8okzWzl63UKbQmmg==", + "version": "7.9.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.9.6.tgz", + "integrity": "sha512-Ga6/fhGqA9Hj+y6whNpPv8psyaK5xzrQwSPsGPloVkvmH+PqW1ixdnfJ9uIO06OjQNYol3PMnfmJ8vfZtkzF+A==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.3", @@ -771,38 +771,38 @@ } }, "@babel/plugin-transform-modules-amd": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.9.0.tgz", - "integrity": "sha512-vZgDDF003B14O8zJy0XXLnPH4sg+9X5hFBBGN1V+B2rgrB+J2xIypSN6Rk9imB2hSTHQi5OHLrFWsZab1GMk+Q==", + "version": "7.9.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.9.6.tgz", + "integrity": "sha512-zoT0kgC3EixAyIAU+9vfaUVKTv9IxBDSabgHoUCBP6FqEJ+iNiN7ip7NBKcYqbfUDfuC2mFCbM7vbu4qJgOnDw==", "dev": true, "requires": { "@babel/helper-module-transforms": "^7.9.0", "@babel/helper-plugin-utils": "^7.8.3", - "babel-plugin-dynamic-import-node": "^2.3.0" + "babel-plugin-dynamic-import-node": "^2.3.3" } }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.9.0.tgz", - "integrity": "sha512-qzlCrLnKqio4SlgJ6FMMLBe4bySNis8DFn1VkGmOcxG9gqEyPIOzeQrA//u0HAKrWpJlpZbZMPB1n/OPa4+n8g==", + "version": "7.9.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.9.6.tgz", + "integrity": "sha512-7H25fSlLcn+iYimmsNe3uK1at79IE6SKW9q0/QeEHTMC9MdOZ+4bA+T1VFB5fgOqBWoqlifXRzYD0JPdmIrgSQ==", "dev": true, "requires": { "@babel/helper-module-transforms": "^7.9.0", "@babel/helper-plugin-utils": "^7.8.3", "@babel/helper-simple-access": "^7.8.3", - "babel-plugin-dynamic-import-node": "^2.3.0" + "babel-plugin-dynamic-import-node": "^2.3.3" } }, "@babel/plugin-transform-modules-systemjs": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.9.0.tgz", - "integrity": "sha512-FsiAv/nao/ud2ZWy4wFacoLOm5uxl0ExSQ7ErvP7jpoihLR6Cq90ilOFyX9UXct3rbtKsAiZ9kFt5XGfPe/5SQ==", + "version": "7.9.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.9.6.tgz", + "integrity": "sha512-NW5XQuW3N2tTHim8e1b7qGy7s0kZ2OH3m5octc49K1SdAKGxYxeIx7hiIz05kS1R2R+hOWcsr1eYwcGhrdHsrg==", "dev": true, "requires": { "@babel/helper-hoist-variables": "^7.8.3", "@babel/helper-module-transforms": "^7.9.0", "@babel/helper-plugin-utils": "^7.8.3", - "babel-plugin-dynamic-import-node": "^2.3.0" + "babel-plugin-dynamic-import-node": "^2.3.3" } }, "@babel/plugin-transform-modules-umd": { @@ -990,13 +990,13 @@ } }, "@babel/preset-env": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.9.5.tgz", - "integrity": "sha512-eWGYeADTlPJH+wq1F0wNfPbVS1w1wtmMJiYk55Td5Yu28AsdR9AsC97sZ0Qq8fHqQuslVSIYSGJMcblr345GfQ==", + "version": "7.9.6", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.9.6.tgz", + "integrity": "sha512-0gQJ9RTzO0heXOhzftog+a/WyOuqMrAIugVYxMYf83gh1CQaQDjMtsOpqOwXyDL/5JcWsrCm8l4ju8QC97O7EQ==", "dev": true, "requires": { - "@babel/compat-data": "^7.9.0", - "@babel/helper-compilation-targets": "^7.8.7", + "@babel/compat-data": "^7.9.6", + "@babel/helper-compilation-targets": "^7.9.6", "@babel/helper-module-imports": "^7.8.3", "@babel/helper-plugin-utils": "^7.8.3", "@babel/plugin-proposal-async-generator-functions": "^7.8.3", @@ -1004,7 +1004,7 @@ "@babel/plugin-proposal-json-strings": "^7.8.3", "@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3", "@babel/plugin-proposal-numeric-separator": "^7.8.3", - "@babel/plugin-proposal-object-rest-spread": "^7.9.5", + "@babel/plugin-proposal-object-rest-spread": "^7.9.6", "@babel/plugin-proposal-optional-catch-binding": "^7.8.3", "@babel/plugin-proposal-optional-chaining": "^7.9.0", "@babel/plugin-proposal-unicode-property-regex": "^7.8.3", @@ -1031,9 +1031,9 @@ "@babel/plugin-transform-function-name": "^7.8.3", "@babel/plugin-transform-literals": "^7.8.3", "@babel/plugin-transform-member-expression-literals": "^7.8.3", - "@babel/plugin-transform-modules-amd": "^7.9.0", - "@babel/plugin-transform-modules-commonjs": "^7.9.0", - "@babel/plugin-transform-modules-systemjs": "^7.9.0", + "@babel/plugin-transform-modules-amd": "^7.9.6", + "@babel/plugin-transform-modules-commonjs": "^7.9.6", + "@babel/plugin-transform-modules-systemjs": "^7.9.6", "@babel/plugin-transform-modules-umd": "^7.9.0", "@babel/plugin-transform-named-capturing-groups-regex": "^7.8.3", "@babel/plugin-transform-new-target": "^7.8.3", @@ -1049,8 +1049,8 @@ "@babel/plugin-transform-typeof-symbol": "^7.8.4", "@babel/plugin-transform-unicode-regex": "^7.8.3", "@babel/preset-modules": "^0.1.3", - "@babel/types": "^7.9.5", - "browserslist": "^4.9.1", + "@babel/types": "^7.9.6", + "browserslist": "^4.11.1", "core-js-compat": "^3.6.2", "invariant": "^2.2.2", "levenary": "^1.1.1", @@ -1098,18 +1098,18 @@ } }, "@babel/runtime": { - "version": "7.9.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz", - "integrity": "sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q==", + "version": "7.9.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.6.tgz", + "integrity": "sha512-64AF1xY3OAkFHqOb9s4jpgk1Mm5vDZ4L3acHvAml+53nO1XbXLuDodsVpO4OIUsmemlUHMxNdYMNJmsvOwLrvQ==", "dev": true, "requires": { "regenerator-runtime": "^0.13.4" } }, "@babel/runtime-corejs3": { - "version": "7.9.2", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.9.2.tgz", - "integrity": "sha512-HHxmgxbIzOfFlZ+tdeRKtaxWOMUoCG5Mu3wKeUmOxjYrwb3AAHgnmtCUbPPK11/raIWLIBK250t8E2BPO0p7jA==", + "version": "7.9.6", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.9.6.tgz", + "integrity": "sha512-6toWAfaALQjt3KMZQc6fABqZwUDDuWzz+cAfPhqyEnzxvdWOAkjwPNxgF8xlmo7OWLsSjaKjsskpKHRLaMArOA==", "dev": true, "requires": { "core-js-pure": "^3.0.0", @@ -1128,17 +1128,17 @@ } }, "@babel/traverse": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.5.tgz", - "integrity": "sha512-c4gH3jsvSuGUezlP6rzSJ6jf8fYjLj3hsMZRx/nX0h+fmHN0w+ekubRrHPqnMec0meycA2nwCsJ7dC8IPem2FQ==", + "version": "7.9.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.6.tgz", + "integrity": "sha512-b3rAHSjbxy6VEAvlxM8OV/0X4XrG72zoxme6q1MOoe2vd0bEc+TwayhuC1+Dfgqh1QEG+pj7atQqvUprHIccsg==", "dev": true, "requires": { "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.9.5", + "@babel/generator": "^7.9.6", "@babel/helper-function-name": "^7.9.5", "@babel/helper-split-export-declaration": "^7.8.3", - "@babel/parser": "^7.9.0", - "@babel/types": "^7.9.5", + "@babel/parser": "^7.9.6", + "@babel/types": "^7.9.6", "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.13" @@ -1162,9 +1162,9 @@ } }, "@babel/types": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.5.tgz", - "integrity": "sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg==", + "version": "7.9.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.6.tgz", + "integrity": "sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.9.5", @@ -1903,6 +1903,15 @@ "@hapi/topo": "^5.0.0" } }, + "@hapi/joi-date": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@hapi/joi-date/-/joi-date-2.0.1.tgz", + "integrity": "sha512-8be8JUEC8Wm1Do3ryJy+TXmkAL13b2JwXn7gILBoor8LopY/M+hJskodzOOxfJdckkfWnbmbnMEyJW3d/gZMfA==", + "dev": true, + "requires": { + "moment": "2.x.x" + } + }, "@hapi/mimos": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/@hapi/mimos/-/mimos-4.1.1.tgz", @@ -2238,9 +2247,9 @@ } }, "@iarna/toml": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.3.tgz", - "integrity": "sha512-FmuxfCuolpLl0AnQ2NHSzoUKWEJDFl63qXjzdoWBVyFCXzMGm1spBzk7LeHNoVCiWCF7mRVms9e6jEV9+MoPbg==", + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz", + "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==", "dev": true }, "@istanbuljs/load-nyc-config": { @@ -2313,15 +2322,15 @@ "dev": true }, "@jest/console": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-25.4.0.tgz", - "integrity": "sha512-CfE0erx4hdJ6t7RzAcE1wLG6ZzsHSmybvIBQDoCkDM1QaSeWL9wJMzID/2BbHHa7ll9SsbbK43HjbERbBaFX2A==", + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-25.5.0.tgz", + "integrity": "sha512-T48kZa6MK1Y6k4b89sexwmSF4YLeZS/Udqg3Jj3jG/cHH+N/sLFCEoXEDMOKugJQ9FxPN1osxIknvKkxt6MKyw==", "dev": true, "requires": { - "@jest/types": "^25.4.0", + "@jest/types": "^25.5.0", "chalk": "^3.0.0", - "jest-message-util": "^25.4.0", - "jest-util": "^25.4.0", + "jest-message-util": "^25.5.0", + "jest-util": "^25.5.0", "slash": "^3.0.0" }, "dependencies": { @@ -2384,33 +2393,33 @@ } }, "@jest/core": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-25.4.0.tgz", - "integrity": "sha512-h1x9WSVV0+TKVtATGjyQIMJENs8aF6eUjnCoi4jyRemYZmekLr8EJOGQqTWEX8W6SbZ6Skesy9pGXrKeAolUJw==", + "version": "25.5.4", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-25.5.4.tgz", + "integrity": "sha512-3uSo7laYxF00Dg/DMgbn4xMJKmDdWvZnf89n8Xj/5/AeQ2dOQmn6b6Hkj/MleyzZWXpwv+WSdYWl4cLsy2JsoA==", "dev": true, "requires": { - "@jest/console": "^25.4.0", - "@jest/reporters": "^25.4.0", - "@jest/test-result": "^25.4.0", - "@jest/transform": "^25.4.0", - "@jest/types": "^25.4.0", + "@jest/console": "^25.5.0", + "@jest/reporters": "^25.5.1", + "@jest/test-result": "^25.5.0", + "@jest/transform": "^25.5.1", + "@jest/types": "^25.5.0", "ansi-escapes": "^4.2.1", "chalk": "^3.0.0", "exit": "^0.1.2", - "graceful-fs": "^4.2.3", - "jest-changed-files": "^25.4.0", - "jest-config": "^25.4.0", - "jest-haste-map": "^25.4.0", - "jest-message-util": "^25.4.0", + "graceful-fs": "^4.2.4", + "jest-changed-files": "^25.5.0", + "jest-config": "^25.5.4", + "jest-haste-map": "^25.5.1", + "jest-message-util": "^25.5.0", "jest-regex-util": "^25.2.6", - "jest-resolve": "^25.4.0", - "jest-resolve-dependencies": "^25.4.0", - "jest-runner": "^25.4.0", - "jest-runtime": "^25.4.0", - "jest-snapshot": "^25.4.0", - "jest-util": "^25.4.0", - "jest-validate": "^25.4.0", - "jest-watcher": "^25.4.0", + "jest-resolve": "^25.5.1", + "jest-resolve-dependencies": "^25.5.4", + "jest-runner": "^25.5.4", + "jest-runtime": "^25.5.4", + "jest-snapshot": "^25.5.1", + "jest-util": "^25.5.0", + "jest-validate": "^25.5.0", + "jest-watcher": "^25.5.0", "micromatch": "^4.0.2", "p-each-series": "^2.1.0", "realpath-native": "^2.0.0", @@ -2560,53 +2569,65 @@ } }, "@jest/environment": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-25.4.0.tgz", - "integrity": "sha512-KDctiak4mu7b4J6BIoN/+LUL3pscBzoUCP+EtSPd2tK9fqyDY5OF+CmkBywkFWezS9tyH5ACOQNtpjtueEDH6Q==", + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-25.5.0.tgz", + "integrity": "sha512-U2VXPEqL07E/V7pSZMSQCvV5Ea4lqOlT+0ZFijl/i316cRMHvZ4qC+jBdryd+lmRetjQo0YIQr6cVPNxxK87mA==", "dev": true, "requires": { - "@jest/fake-timers": "^25.4.0", - "@jest/types": "^25.4.0", - "jest-mock": "^25.4.0" + "@jest/fake-timers": "^25.5.0", + "@jest/types": "^25.5.0", + "jest-mock": "^25.5.0" } }, "@jest/fake-timers": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-25.4.0.tgz", - "integrity": "sha512-lI9z+VOmVX4dPPFzyj0vm+UtaB8dCJJ852lcDnY0uCPRvZAaVGnMwBBc1wxtf+h7Vz6KszoOvKAt4QijDnHDkg==", + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-25.5.0.tgz", + "integrity": "sha512-9y2+uGnESw/oyOI3eww9yaxdZyHq7XvprfP/eeoCsjqKYts2yRlsHS/SgjPDV8FyMfn2nbMy8YzUk6nyvdLOpQ==", "dev": true, "requires": { - "@jest/types": "^25.4.0", - "jest-message-util": "^25.4.0", - "jest-mock": "^25.4.0", - "jest-util": "^25.4.0", + "@jest/types": "^25.5.0", + "jest-message-util": "^25.5.0", + "jest-mock": "^25.5.0", + "jest-util": "^25.5.0", "lolex": "^5.0.0" } }, + "@jest/globals": { + "version": "25.5.2", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-25.5.2.tgz", + "integrity": "sha512-AgAS/Ny7Q2RCIj5kZ+0MuKM1wbF0WMLxbCVl/GOMoCNbODRdJ541IxJ98xnZdVSZXivKpJlNPIWa3QmY0l4CXA==", + "dev": true, + "requires": { + "@jest/environment": "^25.5.0", + "@jest/types": "^25.5.0", + "expect": "^25.5.0" + } + }, "@jest/reporters": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-25.4.0.tgz", - "integrity": "sha512-bhx/buYbZgLZm4JWLcRJ/q9Gvmd3oUh7k2V7gA4ZYBx6J28pIuykIouclRdiAC6eGVX1uRZT+GK4CQJLd/PwPg==", + "version": "25.5.1", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-25.5.1.tgz", + "integrity": "sha512-3jbd8pPDTuhYJ7vqiHXbSwTJQNavczPs+f1kRprRDxETeE3u6srJ+f0NPuwvOmk+lmunZzPkYWIFZDLHQPkviw==", "dev": true, "requires": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^25.4.0", - "@jest/test-result": "^25.4.0", - "@jest/transform": "^25.4.0", - "@jest/types": "^25.4.0", + "@jest/console": "^25.5.0", + "@jest/test-result": "^25.5.0", + "@jest/transform": "^25.5.1", + "@jest/types": "^25.5.0", "chalk": "^3.0.0", "collect-v8-coverage": "^1.0.0", "exit": "^0.1.2", "glob": "^7.1.2", + "graceful-fs": "^4.2.4", "istanbul-lib-coverage": "^3.0.0", "istanbul-lib-instrument": "^4.0.0", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.0.2", - "jest-haste-map": "^25.4.0", - "jest-resolve": "^25.4.0", - "jest-util": "^25.4.0", - "jest-worker": "^25.4.0", + "jest-haste-map": "^25.5.1", + "jest-resolve": "^25.5.1", + "jest-util": "^25.5.0", + "jest-worker": "^25.5.0", "node-notifier": "^6.0.0", "slash": "^3.0.0", "source-map": "^0.6.0", @@ -2680,13 +2701,13 @@ } }, "@jest/source-map": { - "version": "25.2.6", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-25.2.6.tgz", - "integrity": "sha512-VuIRZF8M2zxYFGTEhkNSvQkUKafQro4y+mwUxy5ewRqs5N/ynSFUODYp3fy1zCnbCMy1pz3k+u57uCqx8QRSQQ==", + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-25.5.0.tgz", + "integrity": "sha512-eIGx0xN12yVpMcPaVpjXPnn3N30QGJCJQSkEDUt9x1fI1Gdvb07Ml6K5iN2hG7NmMP6FDmtPEssE3z6doOYUwQ==", "dev": true, "requires": { "callsites": "^3.0.0", - "graceful-fs": "^4.2.3", + "graceful-fs": "^4.2.4", "source-map": "^0.6.0" }, "dependencies": { @@ -2699,45 +2720,46 @@ } }, "@jest/test-result": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-25.4.0.tgz", - "integrity": "sha512-8BAKPaMCHlL941eyfqhWbmp3MebtzywlxzV+qtngQ3FH+RBqnoSAhNEPj4MG7d2NVUrMOVfrwuzGpVIK+QnMAA==", + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-25.5.0.tgz", + "integrity": "sha512-oV+hPJgXN7IQf/fHWkcS99y0smKLU2czLBJ9WA0jHITLst58HpQMtzSYxzaBvYc6U5U6jfoMthqsUlUlbRXs0A==", "dev": true, "requires": { - "@jest/console": "^25.4.0", - "@jest/types": "^25.4.0", + "@jest/console": "^25.5.0", + "@jest/types": "^25.5.0", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" } }, "@jest/test-sequencer": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-25.4.0.tgz", - "integrity": "sha512-240cI+nsM3attx2bMp9uGjjHrwrpvxxrZi8Tyqp/cfOzl98oZXVakXBgxODGyBYAy/UGXPKXLvNc2GaqItrsJg==", + "version": "25.5.4", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-25.5.4.tgz", + "integrity": "sha512-pTJGEkSeg1EkCO2YWq6hbFvKNXk8ejqlxiOg1jBNLnWrgXOkdY6UmqZpwGFXNnRt9B8nO1uWMzLLZ4eCmhkPNA==", "dev": true, "requires": { - "@jest/test-result": "^25.4.0", - "jest-haste-map": "^25.4.0", - "jest-runner": "^25.4.0", - "jest-runtime": "^25.4.0" + "@jest/test-result": "^25.5.0", + "graceful-fs": "^4.2.4", + "jest-haste-map": "^25.5.1", + "jest-runner": "^25.5.4", + "jest-runtime": "^25.5.4" } }, "@jest/transform": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-25.4.0.tgz", - "integrity": "sha512-t1w2S6V1sk++1HHsxboWxPEuSpN8pxEvNrZN+Ud/knkROWtf8LeUmz73A4ezE8476a5AM00IZr9a8FO9x1+j3g==", + "version": "25.5.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-25.5.1.tgz", + "integrity": "sha512-Y8CEoVwXb4QwA6Y/9uDkn0Xfz0finGkieuV0xkdF9UtZGJeLukD5nLkaVrVsODB1ojRWlaoD0AJZpVHCSnJEvg==", "dev": true, "requires": { "@babel/core": "^7.1.0", - "@jest/types": "^25.4.0", + "@jest/types": "^25.5.0", "babel-plugin-istanbul": "^6.0.0", "chalk": "^3.0.0", "convert-source-map": "^1.4.0", "fast-json-stable-stringify": "^2.0.0", - "graceful-fs": "^4.2.3", - "jest-haste-map": "^25.4.0", + "graceful-fs": "^4.2.4", + "jest-haste-map": "^25.5.1", "jest-regex-util": "^25.2.6", - "jest-util": "^25.4.0", + "jest-util": "^25.5.0", "micromatch": "^4.0.2", "pirates": "^4.0.1", "realpath-native": "^2.0.0", @@ -2854,9 +2876,9 @@ } }, "@jest/types": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.4.0.tgz", - "integrity": "sha512-XBeaWNzw2PPnGW5aXvZt3+VO60M+34RY3XDsCK5tW7kyj3RK0XClRutCfjqcBuaR2aBQTbluEDME9b5MB9UAPw==", + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.5.0.tgz", + "integrity": "sha512-OXD0RgQ86Tu3MazKo8bnrkDRaDXXMGUqd+kTtLtK1Zb7CRzQcaSRPPPV37SvYTdevXEBVxe0HXylEjs8ibkmCw==", "dev": true, "requires": { "@types/istanbul-lib-coverage": "^2.0.0", @@ -3186,9 +3208,9 @@ } }, "chokidar": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.1.tgz", - "integrity": "sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.0.tgz", + "integrity": "sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ==", "dev": true, "requires": { "anymatch": "~3.1.1", @@ -3198,7 +3220,7 @@ "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.3.0" + "readdirp": "~3.4.0" } }, "dotenv": { @@ -3226,9 +3248,9 @@ } }, "fsevents": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz", - "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", "dev": true, "optional": true }, @@ -3260,12 +3282,12 @@ "version": "^1.2.5" }, "readdirp": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.3.0.tgz", - "integrity": "sha512-zz0pAkSPOXXm1viEwygWIPSPkcBYjW1xU5j/JBh5t9bGCJwa6f9+BJa6VaB2g+b55yVrmXzqkyLf4xaWYM0IkQ==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", + "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", "dev": true, "requires": { - "picomatch": "^2.0.7" + "picomatch": "^2.2.1" } }, "strip-ansi": { @@ -3345,17 +3367,17 @@ } }, "@serverless/enterprise-plugin": { - "version": "3.6.6", - "resolved": "https://registry.npmjs.org/@serverless/enterprise-plugin/-/enterprise-plugin-3.6.6.tgz", - "integrity": "sha512-ZkzHp8WVOQv2opdXSYES39uorZV3m61+QDPK5W2PtV6InddYlYNTVuhH8vIynNYFrK8tZ95ZjpPi0BQkQ8q2EQ==", + "version": "3.6.11", + "resolved": "https://registry.npmjs.org/@serverless/enterprise-plugin/-/enterprise-plugin-3.6.11.tgz", + "integrity": "sha512-cnn9A9ebpdW5Q1v9FHB7nbcFHkAttcownaw2AALXIld04hrIMpR3YILa47WxdXFyvyPg0dyKT5OhEly9Cc2BMQ==", "dev": true, "requires": { "@serverless/event-mocks": "^1.1.1", - "@serverless/platform-client": "^0.24.0", + "@serverless/platform-client": "^0.25.7", "@serverless/platform-sdk": "^2.3.0", "chalk": "^2.4.2", - "child-process-ext": "^2.1.0", - "chokidar": "^3.3.1", + "child-process-ext": "^2.1.1", + "chokidar": "^3.4.0", "cli-color": "^2.0.0", "dependency-tree": "^7.2.1", "find-process": "^1.4.3", @@ -3364,17 +3386,17 @@ "iso8601-duration": "^1.2.0", "isomorphic-fetch": "^2.2.1", "js-yaml": "^3.13.1", - "jsonata": "^1.8.1", - "jszip": "^3.2.2", + "jsonata": "^1.8.3", + "jszip": "^3.4.0", "lodash": "^4.17.15", "memoizee": "^0.4.14", - "moment": "^2.24.0", + "moment": "^2.25.3", "node-dir": "^0.1.17", "node-fetch": "^2.6.0", "regenerator-runtime": "^0.13.5", "semver": "^6.3.0", "simple-git": "^1.132.0", - "source-map-support": "^0.5.16", + "source-map-support": "^0.5.19", "update-notifier": "^2.5.0", "uuid": "^3.4.0", "yamljs": "^0.3.0" @@ -3406,9 +3428,9 @@ } }, "chokidar": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.1.tgz", - "integrity": "sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.0.tgz", + "integrity": "sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ==", "dev": true, "requires": { "anymatch": "~3.1.1", @@ -3418,7 +3440,7 @@ "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.3.0" + "readdirp": "~3.4.0" } }, "fill-range": { @@ -3431,9 +3453,9 @@ } }, "fsevents": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz", - "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", "dev": true, "optional": true }, @@ -3461,6 +3483,12 @@ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, + "moment": { + "version": "2.25.3", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.25.3.tgz", + "integrity": "sha512-PuYv0PHxZvzc15Sp8ybUCoQ+xpyPWvjOuK72a5ovzp2LI32rJXOiIfyoFoYvG3s6EwwrdkMyWuRiEHSZRLJNdg==", + "dev": true + }, "node-fetch": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", @@ -3468,12 +3496,12 @@ "dev": true }, "readdirp": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.3.0.tgz", - "integrity": "sha512-zz0pAkSPOXXm1viEwygWIPSPkcBYjW1xU5j/JBh5t9bGCJwa6f9+BJa6VaB2g+b55yVrmXzqkyLf4xaWYM0IkQ==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", + "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", "dev": true, "requires": { - "picomatch": "^2.0.7" + "picomatch": "^2.2.1" } }, "semver": { @@ -3510,9 +3538,9 @@ } }, "@serverless/platform-client": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@serverless/platform-client/-/platform-client-0.24.0.tgz", - "integrity": "sha512-ppxR5wONzzxNSmt/9agfSzC0F4yrkHZWAR5IPLm4yj+dMxb+768XrbqBU6vnOfCcmjb89OX5Bk0GvyQh+T5gLw==", + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/@serverless/platform-client/-/platform-client-0.25.7.tgz", + "integrity": "sha512-ZOKgT49qQPGjv0tDN46INO0gkc5syL2y5t0pau5ljQPtQpJzHrUL87xRlDj3BD+4Y9QFZV1UXXNsOQZsyCBsPw==", "dev": true, "requires": { "adm-zip": "^0.4.13", @@ -3521,6 +3549,7 @@ "isomorphic-ws": "^4.0.1", "js-yaml": "^3.13.1", "jwt-decode": "^2.2.0", + "minimatch": "^3.0.4", "querystring": "^0.2.0", "traverse": "^0.6.6", "ws": "^7.2.1" @@ -3561,9 +3590,9 @@ "dev": true }, "ws": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.3.tgz", - "integrity": "sha512-HTDl9G9hbkNDk98naoR/cHDws7+EyYMOdL1BmjsZXRUjf7d+MficC4B7HLUPlSiho0vg+CWKrGIt/VJBd1xunQ==", + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.5.tgz", + "integrity": "sha512-C34cIU4+DB2vMyAbmEKossWq2ZQDr6QEyuuCzWrM9zfw1sGc0mYiJ0UnG9zzNykt49C2Fi34hvr2vssFQRS6EA==", "dev": true } } @@ -3782,9 +3811,9 @@ } }, "@types/babel__traverse": { - "version": "7.0.10", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.10.tgz", - "integrity": "sha512-74fNdUGrWsgIB/V9kTO5FGHPWYY6Eqn+3Z7L6Hc4e/BxjYV7puvBqp5HwsVYYfLm6iURYBNCx4Ut37OF9yitCw==", + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.11.tgz", + "integrity": "sha512-ddHK5icION5U6q11+tV2f9Mo6CZVuT8GJKld2q9LqHSZbvLbH34Kcu2yFGckZut453+eQU6btIA3RihmnRgI+Q==", "dev": true, "requires": { "@babel/types": "^7.3.0" @@ -3880,12 +3909,13 @@ } }, "@types/express-serve-static-core": { - "version": "4.17.5", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.5.tgz", - "integrity": "sha512-578YH5Lt88AKoADy0b2jQGwJtrBxezXtVe/MBqWXKZpqx91SnC0pVkVCcxcytz3lWW+cHBYDi3Ysh0WXc+rAYw==", + "version": "4.17.6", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.6.tgz", + "integrity": "sha512-U2oynuRIB17GIbEdvjFrrEACOy7GQkzsX7bPEBz1H41vZYEU4j0fLL97sawmHDwHUXpUQDBMHIyM9vejqP9o1A==", "dev": true, "requires": { "@types/node": "*", + "@types/qs": "*", "@types/range-parser": "*" } }, @@ -3900,6 +3930,15 @@ "@types/node": "*" } }, + "@types/graceful-fs": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.3.tgz", + "integrity": "sha512-AiHRaEB50LQg0pZmm659vNBb9f4SJ0qrAnteuzhSeAUcJKxoYgEnprg/83kppCnc2zvtCKbdZry1a5pVY3lOTQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/http-proxy": { "version": "1.17.4", "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.4.tgz", @@ -3989,9 +4028,9 @@ } }, "@types/node": { - "version": "13.13.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.1.tgz", - "integrity": "sha512-uysqysLJ+As9jqI5yqjwP3QJrhOcUwBjHUlUxPxjbplwKoILvXVsmYWEhfmAQlrPfbRZmhJB007o4L9sKqtHqQ==", + "version": "13.13.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.5.tgz", + "integrity": "sha512-3ySmiBYJPqgjiHA7oEaIo2Rzz0HrOZ7yrNO5HWyaE5q0lQ3BppDZ3N53Miz8bw2I7gh1/zir2MGVZBvpb1zq9g==", "dev": true }, "@types/normalize-package-data": { @@ -4035,9 +4074,9 @@ "dev": true }, "@types/qs": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.1.tgz", - "integrity": "sha512-lhbQXx9HKZAPgBkISrBcmAcMpZsmpe/Cd/hY7LGZS5OfkySUBItnPZHgQPssWYUET8elF+yCFBbP1Q0RZPTdaw==", + "version": "6.9.2", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.2.tgz", + "integrity": "sha512-a9bDi4Z3zCZf4Lv1X/vwnvbbDYSNz59h3i3KdyuYYN+YrLjSeJD0dnphdULDfySvUv6Exy/O0K6wX/kQpnPQ+A==", "dev": true }, "@types/quill": { @@ -4115,13 +4154,13 @@ "dev": true }, "@typescript-eslint/experimental-utils": { - "version": "2.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.28.0.tgz", - "integrity": "sha512-4SL9OWjvFbHumM/Zh/ZeEjUFxrYKtdCi7At4GyKTbQlrj1HcphIDXlje4Uu4cY+qzszR5NdVin4CCm6AXCjd6w==", + "version": "2.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.31.0.tgz", + "integrity": "sha512-MI6IWkutLYQYTQgZ48IVnRXmLR/0Q6oAyJgiOror74arUMh7EWjJkADfirZhRsUMHeLJ85U2iySDwHTSnNi9vA==", "dev": true, "requires": { "@types/json-schema": "^7.0.3", - "@typescript-eslint/typescript-estree": "2.28.0", + "@typescript-eslint/typescript-estree": "2.31.0", "eslint-scope": "^5.0.0", "eslint-utils": "^2.0.0" }, @@ -4138,9 +4177,9 @@ } }, "@typescript-eslint/typescript-estree": { - "version": "2.28.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.28.0.tgz", - "integrity": "sha512-HDr8MP9wfwkiuqzRVkuM3BeDrOC4cKbO5a6BymZBHUt5y/2pL0BXD6I/C/ceq2IZoHWhcASk+5/zo+dwgu9V8Q==", + "version": "2.31.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.31.0.tgz", + "integrity": "sha512-vxW149bXFXXuBrAak0eKHOzbcu9cvi6iNcJDzEtOkRwGHxJG15chiAQAwhLOsk+86p9GTr/TziYvw+H9kMaIgA==", "dev": true, "requires": { "debug": "^4.1.1", @@ -4487,6 +4526,24 @@ } } }, + "airbnb-prop-types": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/airbnb-prop-types/-/airbnb-prop-types-2.15.0.tgz", + "integrity": "sha512-jUh2/hfKsRjNFC4XONQrxo/n/3GG4Tn6Hl0WlFQN5PY9OMC9loSCoAYKnZsWaP8wEfd5xcrPloK0Zg6iS1xwVA==", + "dev": true, + "requires": { + "array.prototype.find": "^2.1.0", + "function.prototype.name": "^1.1.1", + "has": "^1.0.3", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", + "object.assign": "^4.1.0", + "object.entries": "^1.1.0", + "prop-types": "^15.7.2", + "prop-types-exact": "^1.2.0", + "react-is": "^16.9.0" + } + }, "ajv": { "version": "6.12.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz", @@ -4582,14 +4639,6 @@ "dev": true, "requires": { "entities": "^1.1.2" - }, - "dependencies": { - "entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", - "dev": true - } } }, "any-observable": { @@ -4661,18 +4710,18 @@ } }, "archiver": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/archiver/-/archiver-4.0.1.tgz", - "integrity": "sha512-/YV1pU4Nhpf/rJArM23W6GTUjT0l++VbjykrCRua1TSXrn+yM8Qs7XvtwSiRse0iCe49EPNf7ktXnPsWuSb91Q==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-3.1.1.tgz", + "integrity": "sha512-5Hxxcig7gw5Jod/8Gq0OneVgLYET+oNHcxgWItq4TbhOzRLKNAFUb9edAftiMKXvXfCB0vbGrJdZDNq0dWMsxg==", "dev": true, "requires": { "archiver-utils": "^2.1.0", "async": "^2.6.3", "buffer-crc32": "^0.2.1", - "glob": "^7.1.6", - "readable-stream": "^3.6.0", - "tar-stream": "^2.1.2", - "zip-stream": "^3.0.1" + "glob": "^7.1.4", + "readable-stream": "^3.4.0", + "tar-stream": "^2.1.0", + "zip-stream": "^2.1.2" }, "dependencies": { "readable-stream": { @@ -4767,6 +4816,12 @@ "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=", "dev": true }, + "array-filter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz", + "integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM=", + "dev": true + }, "array-find-index": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", @@ -4808,6 +4863,16 @@ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", "dev": true }, + "array.prototype.find": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/array.prototype.find/-/array.prototype.find-2.1.1.tgz", + "integrity": "sha512-mi+MYNJYLTx2eNYy+Yh6raoQacCsNeeMUaspFPh9Y141lFSsWxxB8V9mM2ye+eqiRs917J6/pJ4M9ZPzenWckA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.4" + } + }, "array.prototype.flat": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz", @@ -4840,14 +4905,15 @@ } }, "asn1.js": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", - "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.3.0.tgz", + "integrity": "sha512-WHnQJFcOrIWT1RLOkFFBQkFVvyt9BPOOrH+Dp152Zk4R993rSzXUGPmkybIcUFhHE2d/iHH+nCaOWVCDbO8fgA==", "dev": true, "requires": { "bn.js": "^4.0.0", "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" } }, "assert": { @@ -4990,9 +5056,9 @@ "dev": true }, "aws-sdk": { - "version": "2.658.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.658.0.tgz", - "integrity": "sha512-vb+CorOG2lod4ZztrVaE3hcSjTwnB9HhTOnD/2R9YJtIUGTJqL0CIDTwo0Q384GFROtDhp7j6SX7oKFwdzDEuA==", + "version": "2.671.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.671.0.tgz", + "integrity": "sha512-i83+/TIOLlhAxvV2xVLz5+XGtNqJgQJwP/e8J49rzDkyMV6OE2FgxU8utujGrComrSJFpITqMFqug+ZfdHoLIQ==", "dev": true, "requires": { "buffer": "4.9.1", @@ -5140,17 +5206,18 @@ } }, "babel-jest": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-25.4.0.tgz", - "integrity": "sha512-p+epx4K0ypmHuCnd8BapfyOwWwosNCYhedetQey1awddtfmEX0MmdxctGl956uwUmjwXR5VSS5xJcGX9DvdIog==", + "version": "25.5.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-25.5.1.tgz", + "integrity": "sha512-9dA9+GmMjIzgPnYtkhBg73gOo/RHqPmLruP3BaGL4KEX3Dwz6pI8auSN8G8+iuEG90+GSswyKvslN+JYSaacaQ==", "dev": true, "requires": { - "@jest/transform": "^25.4.0", - "@jest/types": "^25.4.0", + "@jest/transform": "^25.5.1", + "@jest/types": "^25.5.0", "@types/babel__core": "^7.1.7", "babel-plugin-istanbul": "^6.0.0", - "babel-preset-jest": "^25.4.0", + "babel-preset-jest": "^25.5.0", "chalk": "^3.0.0", + "graceful-fs": "^4.2.4", "slash": "^3.0.0" }, "dependencies": { @@ -5219,9 +5286,9 @@ "dev": true }, "babel-plugin-dynamic-import-node": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz", - "integrity": "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", "dev": true, "requires": { "object.assign": "^4.1.0" @@ -5259,11 +5326,13 @@ } }, "babel-plugin-jest-hoist": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-25.4.0.tgz", - "integrity": "sha512-M3a10JCtTyKevb0MjuH6tU+cP/NVQZ82QPADqI1RQYY1OphztsCeIeQmTsHmF/NS6m0E51Zl4QNsI3odXSQF5w==", + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-25.5.0.tgz", + "integrity": "sha512-u+/W+WAjMlvoocYGTwthAiQSxDcJAyHpQ6oWlHdFZaaN+Rlk8Q7iiwDPg2lN/FyJtAYnKjFxbn7xus4HCFkg5g==", "dev": true, "requires": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", "@types/babel__traverse": "^7.0.6" } }, @@ -5342,12 +5411,12 @@ } }, "babel-preset-jest": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-25.4.0.tgz", - "integrity": "sha512-PwFiEWflHdu3JCeTr0Pb9NcHHE34qWFnPQRVPvqQITx4CsDCzs6o05923I10XvLvn9nNsRHuiVgB72wG/90ZHQ==", + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-25.5.0.tgz", + "integrity": "sha512-8ZczygctQkBU+63DtSOKGh7tFL0CeCuz+1ieud9lJ1WPQ9O6A1a/r+LGn6Y705PA6whHQ3T1XuB/PmpfNYf8Fw==", "dev": true, "requires": { - "babel-plugin-jest-hoist": "^25.4.0", + "babel-plugin-jest-hoist": "^25.5.0", "babel-preset-current-node-syntax": "^0.1.2" } }, @@ -6089,18 +6158,38 @@ } }, "browserify-sign": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", - "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.1.0.tgz", + "integrity": "sha512-VYxo7cDCeYUoBZ0ZCy4UyEUCP3smyBd4DRQM5nrFS1jJjPJjX7rP3oLRpPoWfkhQfyJ0I9ZbHbKafrFD/SGlrg==", "dev": true, "requires": { - "bn.js": "^4.1.1", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.2", - "elliptic": "^6.0.0", - "inherits": "^2.0.1", - "parse-asn1": "^5.0.0" + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.2", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "bn.js": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.1.tgz", + "integrity": "sha512-IUTD/REb78Z2eodka1QZyyEk66pciRcP6Sroka0aI3tG/iwIdYLrBD62RsubR7vqdt3WyX8p4jxeatzmRSphtA==", + "dev": true + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } } }, "browserify-zlib": { @@ -6121,13 +6210,13 @@ } }, "browserslist": { - "version": "4.11.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.11.1.tgz", - "integrity": "sha512-DCTr3kDrKEYNw6Jb9HFxVLQNaue8z+0ZfRBRjmCunKDEXEBajKDj2Y+Uelg+Pi29OnvaSGwjOsnRyNEkXzHg5g==", + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.12.0.tgz", + "integrity": "sha512-UH2GkcEDSI0k/lRkuDSzFl9ZZ87skSy9w2XAn1MsZnL+4c4rqbBd3e82UWHbYDpztABrPBhZsTEeuxVfHppqDg==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001038", - "electron-to-chromium": "^1.3.390", + "caniuse-lite": "^1.0.30001043", + "electron-to-chromium": "^1.3.413", "node-releases": "^1.1.53", "pkg-up": "^2.0.0" } @@ -6404,9 +6493,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001043", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001043.tgz", - "integrity": "sha512-MrBDRPJPDBYwACtSQvxg9+fkna5jPXhJlKmuxenl/ml9uf8LHKlDmLpElu+zTW/bEz7lC1m0wTDD7jiIB+hgFg==", + "version": "1.0.30001053", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001053.tgz", + "integrity": "sha512-HtV4wwIZl6GA4Oznse8aR274XUOYGZnQLcf/P8vHgmlfqSNelwD+id8CyHOceqLqt9yfKmo7DUZTh1EuS9pukg==", "dev": true }, "capture-exit": { @@ -6556,35 +6645,17 @@ "dev": true }, "cheerio": { - "version": "0.22.0", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz", - "integrity": "sha1-qbqoYKP5tZWmuBsahocxIe06Jp4=", + "version": "1.0.0-rc.3", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.3.tgz", + "integrity": "sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA==", "dev": true, "requires": { "css-select": "~1.2.0", - "dom-serializer": "~0.1.0", + "dom-serializer": "~0.1.1", "entities": "~1.1.1", "htmlparser2": "^3.9.1", - "lodash.assignin": "^4.0.9", - "lodash.bind": "^4.1.4", - "lodash.defaults": "^4.0.1", - "lodash.filter": "^4.4.0", - "lodash.flatten": "^4.2.0", - "lodash.foreach": "^4.3.0", - "lodash.map": "^4.4.0", - "lodash.merge": "^4.4.0", - "lodash.pick": "^4.2.1", - "lodash.reduce": "^4.4.0", - "lodash.reject": "^4.4.0", - "lodash.some": "^4.4.0" - }, - "dependencies": { - "entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", - "dev": true - } + "lodash": "^4.15.0", + "parse5": "^3.0.1" } }, "child-process-ext": { @@ -7060,9 +7131,9 @@ "dev": true }, "comment-parser": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-0.7.2.tgz", - "integrity": "sha512-4Rjb1FnxtOcv9qsfuaNuVsmmVn4ooVoBHzYfyKteiXwIU84PClyGA5jASoFMwPV93+FPh9spwueXauxFJZkGAg==", + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-0.7.4.tgz", + "integrity": "sha512-Nnl77/mt6sj1BiYSVMeMWzvD0183F2MFOJyFRmZHimUVDYS9J40AvXpiFA7RpU5pQH+HkvYc0dnsHpwW2xmbyQ==", "dev": true }, "common-tags": { @@ -7084,15 +7155,15 @@ "dev": true }, "compress-commons": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-3.0.0.tgz", - "integrity": "sha512-FyDqr8TKX5/X0qo+aVfaZ+PVmNJHJeckFBlq8jZGSJOgnynhfifoyl24qaqdUdDIBe0EVTHByN6NAkqYvE/2Xg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-2.1.1.tgz", + "integrity": "sha512-eVw6n7CnEMFzc3duyFVrQEuY1BlHR3rYsSztyG32ibGMW722i3C6IizEGMFmfMU+A+fALvBIwxN3czffTcdA+Q==", "dev": true, "requires": { "buffer-crc32": "^0.2.13", "crc32-stream": "^3.0.1", "normalize-path": "^3.0.0", - "readable-stream": "^2.3.7" + "readable-stream": "^2.3.6" } }, "concat-map": { @@ -7460,17 +7531,6 @@ "sha.js": "^2.4.8" } }, - "create-react-class": { - "version": "15.6.3", - "resolved": "https://registry.npmjs.org/create-react-class/-/create-react-class-15.6.3.tgz", - "integrity": "sha512-M+/3Q6E6DLO6Yx3OwrWjwHBnvfXXYA7W+dFjt/ZDBemHO1DDZhsalX/NUtnTYclN6GfnBDRh4qRHjcDHmlJBJg==", - "dev": true, - "requires": { - "fbjs": "^0.8.9", - "loose-envify": "^1.3.1", - "object-assign": "^4.1.1" - } - }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", @@ -7787,9 +7847,9 @@ "dev": true }, "cssstyle": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.2.0.tgz", - "integrity": "sha512-sEb3XFPx3jNnCAMtqrXPDeSgQr+jojtCeNf8cvMNMh1cG970+lljssvQDzPq6lmmJu2Vhqood/gtEomBiHOGnA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", "dev": true, "requires": { "cssom": "~0.3.6" @@ -7810,9 +7870,9 @@ "dev": true }, "csv-parse": { - "version": "4.8.9", - "resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-4.8.9.tgz", - "integrity": "sha512-uDxIDIDLb89gxqixSgGqDj3EA5A8D0pgUeyp9Qut8u+eCIC8IXkTtaxJEnnWDb6N2HqBY64suSlcOGg5ZBtsAQ==", + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-4.9.0.tgz", + "integrity": "sha512-SaFMvRWzobY9z0Nxg+q5pXvU2JY7p++icb1Bb/ZwGSLv058cLabhGg3YNpLPI2KALtZnoe/oNBCfWX9xgTkcaA==", "dev": true }, "cuid": { @@ -7843,9 +7903,9 @@ "dev": true }, "cypress": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-4.4.0.tgz", - "integrity": "sha512-ZpsV3pVemANGi4Cxu0UIqFv23uHdDJZYlKY+8P/eixujCpI1TQ5RSPBp2grfV3ZvlGYrOXPJY44j9iEh1xoQug==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-4.5.0.tgz", + "integrity": "sha512-2A4g5FW5d2fHzq8HKUGAMVTnW6P8nlWYQALiCoGN4bqBLvgwhYM/oG9oKc2CS6LnvgHFiKivKzpm9sfk3uU3zQ==", "dev": true, "requires": { "@cypress/listr-verbose-renderer": "0.4.1", @@ -7935,6 +7995,15 @@ "has-flag": "^4.0.0" } }, + "tmp": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.1.0.tgz", + "integrity": "sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw==", + "dev": true, + "requires": { + "rimraf": "^2.6.3" + } + }, "url": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", @@ -7990,15 +8059,15 @@ "dev": true }, "dayjs": { - "version": "1.8.24", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.8.24.tgz", - "integrity": "sha512-bImQZbBv86zcOWOq6fLg7r4aqMx8fScdmykA7cSh+gH1Yh8AM0Dbw0gHYrsOrza6oBBnkK+/OaR+UAa9UsMrDw==", + "version": "1.8.26", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.8.26.tgz", + "integrity": "sha512-KqtAuIfdNfZR5sJY1Dixr2Is4ZvcCqhb0dZpCOt5dGEFiMzoIbjkTSzUb4QKTCsP+WNpGwUjAFIZrnZvUxxkhw==", "dev": true }, "deasync": { - "version": "0.1.19", - "resolved": "https://registry.npmjs.org/deasync/-/deasync-0.1.19.tgz", - "integrity": "sha512-oh3MRktfnPlLysCPpBpKZZzb4cUC/p0aA3SyRGp15lN30juJBTo/CiD0d4fR+f1kBtUQoJj1NE9RPNWQ7BQ9Mg==", + "version": "0.1.20", + "resolved": "https://registry.npmjs.org/deasync/-/deasync-0.1.20.tgz", + "integrity": "sha512-E1GI7jMI57hL30OX6Ht/hfQU8DO4AuB9m72WFm4c38GNbUD4Q03//XZaOIHZiY+H1xUaomcot5yk2q/qIZQkGQ==", "dev": true, "requires": { "bindings": "^1.5.0", @@ -8618,15 +8687,15 @@ "dev": true }, "detective-typescript": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/detective-typescript/-/detective-typescript-5.7.0.tgz", - "integrity": "sha512-4SQeACXWAjIOsd2kJykPL8gWC9nVA+z8w7KtAdtd/7BCpDfrpI2ZA7pdhsmHv/zxf3ofeqpYi72vCkZ65bAjtA==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/detective-typescript/-/detective-typescript-5.8.0.tgz", + "integrity": "sha512-SrsUCfCaDTF64QVMHMidRal+kmkbIc5zP8cxxZPsomWx9vuEUjBlSJNhf7/ypE5cLdJJDI4qzKDmyzqQ+iz/xg==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "^2.4.0", - "ast-module-types": "^2.5.0", + "@typescript-eslint/typescript-estree": "^2.29.0", + "ast-module-types": "^2.6.0", "node-source-walk": "^4.2.0", - "typescript": "^3.6.4" + "typescript": "^3.8.3" } }, "diagnostics": { @@ -8690,6 +8759,12 @@ } } }, + "discontinuous-range": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", + "integrity": "sha1-44Mx8IRLukm5qctxx3FYWqsbxlo=", + "dev": true + }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -8723,14 +8798,6 @@ "requires": { "domelementtype": "^1.3.0", "entities": "^1.1.1" - }, - "dependencies": { - "entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", - "dev": true - } } }, "domain-browser": { @@ -8948,10 +9015,13 @@ "dev": true }, "ejs": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.0.2.tgz", - "integrity": "sha512-IncmUpn1yN84hy2shb0POJ80FWrfGNY0cxO9f4v+/sG7qcBvAtVWUA1IdzY/8EYUmOVhoKJVdJjNd3AZcnxOjA==", - "dev": true + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.2.tgz", + "integrity": "sha512-zFuywxrAWtX5Mk2KAuoJNkXXbfezpNA0v7i+YC971QORguPekpjpAgeOv99YWSdKXwj7JxI2QAWDeDkE8fWtXw==", + "dev": true, + "requires": { + "jake": "^10.6.1" + } }, "elasticsearch": { "version": "16.7.1", @@ -8992,9 +9062,9 @@ } }, "electron-to-chromium": { - "version": "1.3.413", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.413.tgz", - "integrity": "sha512-Jm1Rrd3siqYHO3jftZwDljL2LYQafj3Kki5r+udqE58d0i91SkjItVJ5RwlJn9yko8i7MOcoidVKjQlgSdd1hg==", + "version": "1.3.430", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.430.tgz", + "integrity": "sha512-HMDYkANGhx6vfbqpOf/hc6hWEmiOipOHGDeRDeUb3HLD3XIWpvKQxFgWf0tgHcr3aNv6I/8VPecplqmQsXoZSw==", "dev": true }, "elegant-spinner": { @@ -9108,9 +9178,9 @@ } }, "entities": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.0.tgz", - "integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", "dev": true }, "env-variable": { @@ -9120,11 +9190,82 @@ "dev": true }, "envinfo": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.5.0.tgz", - "integrity": "sha512-jDgnJaF/Btomk+m3PZDTTCb5XIIIX3zYItnCRfF73zVgvinLoRomuhi75Y4su0PtQxWz4v66XnLLckyvyJTOIQ==", + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.5.1.tgz", + "integrity": "sha512-hQBkDf2iO4Nv0CNHpCuSBeaSrveU6nThVxFGTrq/eDlV716UQk09zChaJae4mZRsos1x4YLY2TaH3LHUae3ZmQ==", "dev": true }, + "enzyme": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-3.11.0.tgz", + "integrity": "sha512-Dw8/Gs4vRjxY6/6i9wU0V+utmQO9kvh9XLnz3LIudviOnVYDEe2ec+0k+NQoMamn1VrjKgCUOWj5jG/5M5M0Qw==", + "dev": true, + "requires": { + "array.prototype.flat": "^1.2.3", + "cheerio": "^1.0.0-rc.3", + "enzyme-shallow-equal": "^1.0.1", + "function.prototype.name": "^1.1.2", + "has": "^1.0.3", + "html-element-map": "^1.2.0", + "is-boolean-object": "^1.0.1", + "is-callable": "^1.1.5", + "is-number-object": "^1.0.4", + "is-regex": "^1.0.5", + "is-string": "^1.0.5", + "is-subset": "^0.1.1", + "lodash.escape": "^4.0.1", + "lodash.isequal": "^4.5.0", + "object-inspect": "^1.7.0", + "object-is": "^1.0.2", + "object.assign": "^4.1.0", + "object.entries": "^1.1.1", + "object.values": "^1.1.1", + "raf": "^3.4.1", + "rst-selector-parser": "^2.2.3", + "string.prototype.trim": "^1.2.1" + } + }, + "enzyme-adapter-react-16": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.15.2.tgz", + "integrity": "sha512-SkvDrb8xU3lSxID8Qic9rB8pvevDbLybxPK6D/vW7PrT0s2Cl/zJYuXvsd1EBTz0q4o3iqG3FJhpYz3nUNpM2Q==", + "dev": true, + "requires": { + "enzyme-adapter-utils": "^1.13.0", + "enzyme-shallow-equal": "^1.0.1", + "has": "^1.0.3", + "object.assign": "^4.1.0", + "object.values": "^1.1.1", + "prop-types": "^15.7.2", + "react-is": "^16.12.0", + "react-test-renderer": "^16.0.0-0", + "semver": "^5.7.0" + } + }, + "enzyme-adapter-utils": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/enzyme-adapter-utils/-/enzyme-adapter-utils-1.13.0.tgz", + "integrity": "sha512-YuEtfQp76Lj5TG1NvtP2eGJnFKogk/zT70fyYHXK2j3v6CtuHqc8YmgH/vaiBfL8K1SgVVbQXtTcgQZFwzTVyQ==", + "dev": true, + "requires": { + "airbnb-prop-types": "^2.15.0", + "function.prototype.name": "^1.1.2", + "object.assign": "^4.1.0", + "object.fromentries": "^2.0.2", + "prop-types": "^15.7.2", + "semver": "^5.7.1" + } + }, + "enzyme-shallow-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/enzyme-shallow-equal/-/enzyme-shallow-equal-1.0.1.tgz", + "integrity": "sha512-hGA3i1so8OrYOZSM9whlkNmVHOicJpsjgTzC+wn2JMJXhq1oO4kA4bJ5MsfzSIcC71aLDKzJ6gZpIxrqt3QTAQ==", + "dev": true, + "requires": { + "has": "^1.0.3", + "object-is": "^1.0.2" + } + }, "errno": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", @@ -9415,9 +9556,9 @@ } }, "eslint-config-prettier": { - "version": "6.10.1", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.10.1.tgz", - "integrity": "sha512-svTy6zh1ecQojvpbJSgH3aei/Rt7C6i090l5f2WQ4aB05lYHeZIR1qL4wZyyILTbtmnbHP5Yn8MrsOJMGa8RkQ==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.11.0.tgz", + "integrity": "sha512-oB8cpLWSAjOVFEJhhyMZh6NOEOtBVziaqdDQ86+qhDHFbZXoRTM7pNSvFRfW/W/L/LrQ38C99J5CGuRBBzBsdA==", "dev": true, "requires": { "get-stdin": "^6.0.0" @@ -9496,21 +9637,21 @@ } }, "eslint-plugin-jest": { - "version": "23.8.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-23.8.2.tgz", - "integrity": "sha512-xwbnvOsotSV27MtAe7s8uGWOori0nUsrXh2f1EnpmXua8sDfY6VZhHAhHg2sqK7HBNycRQExF074XSZ7DvfoFg==", + "version": "23.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-23.9.0.tgz", + "integrity": "sha512-8mt5xJQIFh33W5nE7vCikkDTE4saTo08V91KjU6yI5sLQ9e8Jkp1OXkWJoIHLheFqY5OXIZdAjZmNYHSJ3IpzQ==", "dev": true, "requires": { "@typescript-eslint/experimental-utils": "^2.5.0" } }, "eslint-plugin-jsdoc": { - "version": "24.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-24.0.0.tgz", - "integrity": "sha512-AGAc9PYpramsJGVmqtxnXBYlq+AMh+hIZdbJ52OLvyJS3f+PaT/PzuckRFOLnth2uhCDv4IjgsB3r5jUFWqUnw==", + "version": "24.0.6", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-24.0.6.tgz", + "integrity": "sha512-WDzUgShMK7Zg9N6s19LxUqy71At/PxCuMEXaKyBzybhABq6iU4DaZtWZ+4fkCMBvMzMwMAPa2oRD/+fQGORMhg==", "dev": true, "requires": { - "comment-parser": "^0.7.2", + "comment-parser": "^0.7.4", "debug": "^4.1.1", "jsdoctypeparser": "^6.1.0", "lodash": "^4.17.15", @@ -9641,9 +9782,9 @@ } }, "eslint-plugin-sort-keys-fix": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-sort-keys-fix/-/eslint-plugin-sort-keys-fix-1.1.0.tgz", - "integrity": "sha512-6q5lM4eLjEui/GUUvrb7yTWWxslY0j7W4Ra6/F1t460fXLXtn18s0fDPqSYLsnXa6gXg+PYgh4eqdQbkgrqTpg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-sort-keys-fix/-/eslint-plugin-sort-keys-fix-1.1.1.tgz", + "integrity": "sha512-x02SLBg+8OEaoT9vvMbsgeInw17wjHLsa9cOieIVQY+xMNRiXBbyMWw+NiBoxYyJIR4QKDOPDofCjQdoSvltQg==", "dev": true, "requires": { "requireindex": "~1.2.0" @@ -9907,16 +10048,16 @@ } }, "expect": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-25.4.0.tgz", - "integrity": "sha512-7BDIX99BTi12/sNGJXA9KMRcby4iAmu1xccBOhyKCyEhjcVKS3hPmHdA/4nSI9QGIOkUropKqr3vv7WMDM5lvQ==", + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-25.5.0.tgz", + "integrity": "sha512-w7KAXo0+6qqZZhovCaBVPSIqQp7/UTcx4M9uKt2m6pd2VB1voyC8JizLRqeEqud3AAVP02g+hbErDu5gu64tlA==", "dev": true, "requires": { - "@jest/types": "^25.4.0", + "@jest/types": "^25.5.0", "ansi-styles": "^4.0.0", "jest-get-type": "^25.2.6", - "jest-matcher-utils": "^25.4.0", - "jest-message-util": "^25.4.0", + "jest-matcher-utils": "^25.5.0", + "jest-message-util": "^25.5.0", "jest-regex-util": "^25.2.6" }, "dependencies": { @@ -10327,29 +10468,6 @@ "bser": "2.1.1" } }, - "fbjs": { - "version": "0.8.17", - "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz", - "integrity": "sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=", - "dev": true, - "requires": { - "core-js": "^1.0.0", - "isomorphic-fetch": "^2.1.1", - "loose-envify": "^1.0.0", - "object-assign": "^4.1.0", - "promise": "^7.1.1", - "setimmediate": "^1.0.5", - "ua-parser-js": "^0.7.18" - }, - "dependencies": { - "core-js": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", - "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=", - "dev": true - } - } - }, "fd-slicer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", @@ -10433,6 +10551,15 @@ "integrity": "sha1-6VF4TXkJUSfTcTApqwY/QIGMoq4=", "dev": true }, + "filelist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.1.tgz", + "integrity": "sha512-8zSK6Nu0DQIC08mUC46sWGXi+q3GGpKydAG36k+JDba6VRpkevvOWUW5a/PhShij4+vHT9M+ghgG7eM+a9JDUQ==", + "dev": true, + "requires": { + "minimatch": "^3.0.4" + } + }, "filename-reserved-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", @@ -10800,18 +10927,18 @@ "dev": true }, "fs2": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/fs2/-/fs2-0.3.7.tgz", - "integrity": "sha512-fwfd9MBI/fnXtR/ClVTyeuPXJ+oI5WNyXvBQPmc4btgqLYTKOuBRTRUVjmVpDUri0C88HLwMlc5ESg48fEAGjw==", + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/fs2/-/fs2-0.3.8.tgz", + "integrity": "sha512-HxOTRiFS3PqwAOmlp1mTwLA+xhQBdaP82b5aBamc/rHKFVyn4qL8YpngaAleD52PNMzBm6TsGOoU/Hq+bAfBhA==", "dev": true, "requires": { "d": "^1.0.1", "deferred": "^0.7.11", - "es5-ext": "^0.10.51", + "es5-ext": "^0.10.53", "event-emitter": "^0.3.5", "ignore": "^5.1.4", "memoizee": "^0.4.14", - "type": "^1.2.0" + "type": "^2.0.0" }, "dependencies": { "ignore": { @@ -10819,596 +10946,53 @@ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz", "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==", "dev": true + }, + "type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz", + "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==", + "dev": true } } }, "fsevents": { - "version": "1.2.12", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.12.tgz", - "integrity": "sha512-Ggd/Ktt7E7I8pxZRbGIs7vwqAPscSESMrCSkx2FtWeqmheJgCo2R74fTsZFCifr0VTPwqRpPv17+6b8Zp7th0Q==", + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", "dev": true, "optional": true, "requires": { "bindings": "^1.5.0", - "nan": "^2.12.1", - "node-pre-gyp": "*" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.1.4", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "3.2.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "deep-extend": { - "version": "0.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.7", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.6.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.24", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore-walk": { - "version": "3.0.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "bundled": true, - "dev": true, - "optional": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "dev": true, - "optional": true, - "version": "^1.2.5" - }, - "minipass": { - "version": "2.9.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.3.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.9.0" - } - }, - "mkdirp": { - "version": "0.5.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimist": "^1.2.5" - }, - "dependencies": { - "minimist": { - "version": "^1.2.5" - } - } - }, - "ms": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.3.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "^3.2.6", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.14.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4.4.2" - } - }, - "nopt": { - "version": "4.0.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "npm-normalize-package-bin": "^1.0.1" - } - }, - "npm-normalize-package-bin": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.4.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1", - "npm-normalize-package-bin": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.5", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "^1.2.5" - } - } - }, - "readable-stream": { - "version": "2.3.7", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "2.7.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.7.1", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.13", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.8.6", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "yallist": { - "version": "3.1.1", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "function-tree": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/function-tree/-/function-tree-3.3.1.tgz", - "integrity": "sha512-4sRZHwlsCkTOYJnubunF+3tIjnTNzM1q61IirLwicWD4IH9sanQOPiISXO1U8qYVbgpqvBsnaTY4DRD09LBQGQ==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "eventemitter3": "^2.0.2", - "universal-websocket-client": "^1.0.1" + "nan": "^2.12.1" + } + }, + "fstream": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", + "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "function-tree": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/function-tree/-/function-tree-3.3.1.tgz", + "integrity": "sha512-4sRZHwlsCkTOYJnubunF+3tIjnTNzM1q61IirLwicWD4IH9sanQOPiISXO1U8qYVbgpqvBsnaTY4DRD09LBQGQ==", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "eventemitter3": "^2.0.2", + "universal-websocket-client": "^1.0.1" }, "dependencies": { "ansi-styles": { @@ -11438,12 +11022,29 @@ } } }, + "function.prototype.name": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.2.tgz", + "integrity": "sha512-C8A+LlHBJjB2AdcRPorc5JvJ5VUoWlXdEHLOJdCI7kjHEtGTpHQUiqMvCIKUwIsGwZX2jZJy761AXsn356bJQg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "functions-have-names": "^1.2.0" + } + }, "functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, + "functions-have-names": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.1.tgz", + "integrity": "sha512-j48B/ZI7VKs3sgeI2cZp7WXWmZXu7Iq5pl5/vptV5N2mq+DGFuS/ulaDjtaoLpYzuD6u8UgrUKHfgo7fDTSiBA==", + "dev": true + }, "gauge": { "version": "2.7.4", "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", @@ -11769,9 +11370,9 @@ } }, "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", "dev": true }, "graceful-readlink": { @@ -11981,13 +11582,33 @@ "dev": true }, "hash-base": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", - "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", "dev": true, "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", + "dev": true + } } }, "hash.js": { @@ -12069,6 +11690,15 @@ "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==", "dev": true }, + "html-element-map": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/html-element-map/-/html-element-map-1.2.0.tgz", + "integrity": "sha512-0uXq8HsuG1v2TmQ8QkIhzbrqeskE4kn52Q18QJ9iAA/SnHoEKXWiUxHQtclRsCFWEUD2So34X+0+pZZu862nnw==", + "dev": true, + "requires": { + "array-filter": "^1.0.0" + } + }, "html-encoding-sniffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", @@ -12119,9 +11749,9 @@ "dev": true }, "posthtml": { - "version": "0.12.2", - "resolved": "https://registry.npmjs.org/posthtml/-/posthtml-0.12.2.tgz", - "integrity": "sha512-vDMikGrmr2Ce4ralyBwfoTymA9Ycv2QSeaV+U9CdF/kHstsGSBVsTZ3Jt/BdACFuqCNyaICMdJI/rvGEreL7pA==", + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/posthtml/-/posthtml-0.12.3.tgz", + "integrity": "sha512-Fbpi95+JJyR0tqU7pUy1zTSQFjAsluuwB9pJ1h0jtnGk7n/O2TBtP5nDl9rV0JVACjQ1Lm5wSp4ppChr8u3MhA==", "dev": true, "requires": { "posthtml-parser": "^0.4.2", @@ -12135,9 +11765,9 @@ "dev": true }, "terser": { - "version": "4.6.11", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.6.11.tgz", - "integrity": "sha512-76Ynm7OXUG5xhOpblhytE7X58oeNSmC8xnNhjWVo8CksHit0U0kO4hfNbPrrYwowLWFgM2n9L176VNx2QaHmtA==", + "version": "4.6.13", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.6.13.tgz", + "integrity": "sha512-wMvqukYgVpQlymbnNbabVZbtM6PN63AzqexpwJL8tbh/mRT9LE5o+ruVduAGL7D6Fpjl+Q+06U5I9Ul82odAhw==", "dev": true, "requires": { "commander": "^2.20.0", @@ -12161,12 +11791,6 @@ "readable-stream": "^3.1.1" }, "dependencies": { - "entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", - "dev": true - }, "readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", @@ -12440,9 +12064,9 @@ }, "dependencies": { "make-dir": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.2.tgz", - "integrity": "sha512-rYKABKutXa6vXTXhoV18cBE7PaewPXHe/Bdq4v+ZLMhxbWApkFFplT0LcbMW+6BbjnQXzZ/sAvSE/JdguApG5w==", + "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, "requires": { "semver": "^6.0.0" @@ -12841,9 +12465,9 @@ } }, "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", "dev": true }, "ip-regex": { @@ -12933,6 +12557,12 @@ "binary-extensions": "^1.0.0" } }, + "is-boolean-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.0.1.tgz", + "integrity": "sha512-TqZuVwa/sppcrhUCAYkGBk7w0yxfQQnxq28fjkO53tnK9FQXmdwz2JS5+GjsWQ6RByES1K40nI+yDic5c9/aAQ==", + "dev": true + }, "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", @@ -13157,6 +12787,12 @@ } } }, + "is-number-object": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", + "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", + "dev": true + }, "is-obj": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", @@ -13227,9 +12863,9 @@ "dev": true }, "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", "dev": true }, "is-reachable": { @@ -13408,6 +13044,12 @@ "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", "dev": true }, + "is-subset": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz", + "integrity": "sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY=", + "dev": true + }, "is-svg": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-3.0.0.tgz", @@ -13463,10 +13105,13 @@ "dev": true }, "is-wsl": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.1.1.tgz", - "integrity": "sha512-umZHcSrwlDHo2TGMXv0DZ8dIUGunZ2Iv68YZnrmCiBPkZ4aaOhtv7pXJKeki9k3qJ3RJr0cDyitcl5wEH3AYog==", - "dev": true + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "requires": { + "is-docker": "^2.0.0" + } }, "is-yarn-global": { "version": "0.3.0", @@ -13567,9 +13212,9 @@ "dev": true }, "make-dir": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.2.tgz", - "integrity": "sha512-rYKABKutXa6vXTXhoV18cBE7PaewPXHe/Bdq4v+ZLMhxbWApkFFplT0LcbMW+6BbjnQXzZ/sAvSE/JdguApG5w==", + "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, "requires": { "semver": "^6.0.0" @@ -13646,15 +13291,35 @@ "is-object": "^1.0.1" } }, + "jake": { + "version": "10.6.1", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.6.1.tgz", + "integrity": "sha512-pHUK3+V0BjOb1XSi95rbBksrMdIqLVC9bJqDnshVyleYsET3H0XAq+3VB2E3notcYvv4wRdRHn13p7vobG+wfQ==", + "dev": true, + "requires": { + "async": "0.9.x", + "chalk": "^2.4.2", + "filelist": "^1.0.1", + "minimatch": "^3.0.4" + }, + "dependencies": { + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "dev": true + } + } + }, "jest": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-25.4.0.tgz", - "integrity": "sha512-XWipOheGB4wai5JfCYXd6vwsWNwM/dirjRoZgAa7H2wd8ODWbli2AiKjqG8AYhyx+8+5FBEdpO92VhGlBydzbw==", + "version": "25.5.4", + "resolved": "https://registry.npmjs.org/jest/-/jest-25.5.4.tgz", + "integrity": "sha512-hHFJROBTqZahnO+X+PMtT6G2/ztqAZJveGqz//FnWWHurizkD05PQGzRZOhF3XP6z7SJmL+5tCfW8qV06JypwQ==", "dev": true, "requires": { - "@jest/core": "^25.4.0", + "@jest/core": "^25.5.4", "import-local": "^3.0.2", - "jest-cli": "^25.4.0" + "jest-cli": "^25.5.4" }, "dependencies": { "ansi-styles": { @@ -13699,21 +13364,22 @@ "dev": true }, "jest-cli": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-25.4.0.tgz", - "integrity": "sha512-usyrj1lzCJZMRN1r3QEdnn8e6E6yCx/QN7+B1sLoA68V7f3WlsxSSQfy0+BAwRiF4Hz2eHauf11GZG3PIfWTXQ==", + "version": "25.5.4", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-25.5.4.tgz", + "integrity": "sha512-rG8uJkIiOUpnREh1768/N3n27Cm+xPFkSNFO91tgg+8o2rXeVLStz+vkXkGr4UtzH6t1SNbjwoiswd7p4AhHTw==", "dev": true, "requires": { - "@jest/core": "^25.4.0", - "@jest/test-result": "^25.4.0", - "@jest/types": "^25.4.0", + "@jest/core": "^25.5.4", + "@jest/test-result": "^25.5.0", + "@jest/types": "^25.5.0", "chalk": "^3.0.0", "exit": "^0.1.2", + "graceful-fs": "^4.2.4", "import-local": "^3.0.2", "is-ci": "^2.0.0", - "jest-config": "^25.4.0", - "jest-util": "^25.4.0", - "jest-validate": "^25.4.0", + "jest-config": "^25.5.4", + "jest-util": "^25.5.0", + "jest-validate": "^25.5.0", "prompts": "^2.0.1", "realpath-native": "^2.0.0", "yargs": "^15.3.1" @@ -13731,12 +13397,12 @@ } }, "jest-changed-files": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-25.4.0.tgz", - "integrity": "sha512-VR/rfJsEs4BVMkwOTuStRyS630fidFVekdw/lBaBQjx9KK3VZFOZ2c0fsom2fRp8pMCrCTP6LGna00o/DXGlqA==", + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-25.5.0.tgz", + "integrity": "sha512-EOw9QEqapsDT7mKF162m8HFzRPbmP8qJQny6ldVOdOVBz3ACgPm/1nAn5fPQ/NDaYhX/AHkrGwwkCncpAVSXcw==", "dev": true, "requires": { - "@jest/types": "^25.4.0", + "@jest/types": "^25.5.0", "execa": "^3.2.0", "throat": "^5.0.0" }, @@ -13839,28 +13505,29 @@ } }, "jest-config": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-25.4.0.tgz", - "integrity": "sha512-egT9aKYxMyMSQV1aqTgam0SkI5/I2P9qrKexN5r2uuM2+68ypnc+zPGmfUxK7p1UhE7dYH9SLBS7yb+TtmT1AA==", + "version": "25.5.4", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-25.5.4.tgz", + "integrity": "sha512-SZwR91SwcdK6bz7Gco8qL7YY2sx8tFJYzvg216DLihTWf+LKY/DoJXpM9nTzYakSyfblbqeU48p/p7Jzy05Atg==", "dev": true, "requires": { "@babel/core": "^7.1.0", - "@jest/test-sequencer": "^25.4.0", - "@jest/types": "^25.4.0", - "babel-jest": "^25.4.0", + "@jest/test-sequencer": "^25.5.4", + "@jest/types": "^25.5.0", + "babel-jest": "^25.5.1", "chalk": "^3.0.0", "deepmerge": "^4.2.2", "glob": "^7.1.1", - "jest-environment-jsdom": "^25.4.0", - "jest-environment-node": "^25.4.0", + "graceful-fs": "^4.2.4", + "jest-environment-jsdom": "^25.5.0", + "jest-environment-node": "^25.5.0", "jest-get-type": "^25.2.6", - "jest-jasmine2": "^25.4.0", + "jest-jasmine2": "^25.5.4", "jest-regex-util": "^25.2.6", - "jest-resolve": "^25.4.0", - "jest-util": "^25.4.0", - "jest-validate": "^25.4.0", + "jest-resolve": "^25.5.1", + "jest-util": "^25.5.0", + "jest-validate": "^25.5.0", "micromatch": "^4.0.2", - "pretty-format": "^25.4.0", + "pretty-format": "^25.5.0", "realpath-native": "^2.0.0" }, "dependencies": { @@ -13960,15 +13627,15 @@ } }, "jest-diff": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-25.4.0.tgz", - "integrity": "sha512-kklLbJVXW0y8UKOWOdYhI6TH5MG6QAxrWiBMgQaPIuhj3dNFGirKCd+/xfplBXICQ7fI+3QcqHm9p9lWu1N6ug==", + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-25.5.0.tgz", + "integrity": "sha512-z1kygetuPiREYdNIumRpAHY6RXiGmp70YHptjdaxTWGmA085W3iCnXNx0DhflK3vwrKmrRWyY1wUpkPMVxMK7A==", "dev": true, "requires": { "chalk": "^3.0.0", "diff-sequences": "^25.2.6", "jest-get-type": "^25.2.6", - "pretty-format": "^25.4.0" + "pretty-format": "^25.5.0" }, "dependencies": { "ansi-styles": { @@ -14033,16 +13700,16 @@ } }, "jest-each": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-25.4.0.tgz", - "integrity": "sha512-lwRIJ8/vQU/6vq3nnSSUw1Y3nz5tkYSFIywGCZpUBd6WcRgpn8NmJoQICojbpZmsJOJNHm0BKdyuJ6Xdx+eDQQ==", + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-25.5.0.tgz", + "integrity": "sha512-QBogUxna3D8vtiItvn54xXde7+vuzqRrEeaw8r1s+1TG9eZLVJE5ZkKoSUlqFwRjnlaA4hyKGiu9OlkFIuKnjA==", "dev": true, "requires": { - "@jest/types": "^25.4.0", + "@jest/types": "^25.5.0", "chalk": "^3.0.0", "jest-get-type": "^25.2.6", - "jest-util": "^25.4.0", - "pretty-format": "^25.4.0" + "jest-util": "^25.5.0", + "pretty-format": "^25.5.0" }, "dependencies": { "ansi-styles": { @@ -14098,16 +13765,16 @@ } }, "jest-environment-jsdom": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-25.4.0.tgz", - "integrity": "sha512-KTitVGMDrn2+pt7aZ8/yUTuS333w3pWt1Mf88vMntw7ZSBNDkRS6/4XLbFpWXYfWfp1FjcjQTOKzbK20oIehWQ==", + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-25.5.0.tgz", + "integrity": "sha512-7Jr02ydaq4jaWMZLY+Skn8wL5nVIYpWvmeatOHL3tOcV3Zw8sjnPpx+ZdeBfc457p8jCR9J6YCc+Lga0oIy62A==", "dev": true, "requires": { - "@jest/environment": "^25.4.0", - "@jest/fake-timers": "^25.4.0", - "@jest/types": "^25.4.0", - "jest-mock": "^25.4.0", - "jest-util": "^25.4.0", + "@jest/environment": "^25.5.0", + "@jest/fake-timers": "^25.5.0", + "@jest/types": "^25.5.0", + "jest-mock": "^25.5.0", + "jest-util": "^25.5.0", "jsdom": "^15.2.1" }, "dependencies": { @@ -14145,6 +13812,12 @@ "xml-name-validator": "^3.0.0" } }, + "parse5": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", + "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==", + "dev": true + }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -14163,24 +13836,24 @@ } }, "ws": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.3.tgz", - "integrity": "sha512-HTDl9G9hbkNDk98naoR/cHDws7+EyYMOdL1BmjsZXRUjf7d+MficC4B7HLUPlSiho0vg+CWKrGIt/VJBd1xunQ==", + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.5.tgz", + "integrity": "sha512-C34cIU4+DB2vMyAbmEKossWq2ZQDr6QEyuuCzWrM9zfw1sGc0mYiJ0UnG9zzNykt49C2Fi34hvr2vssFQRS6EA==", "dev": true } } }, "jest-environment-node": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-25.4.0.tgz", - "integrity": "sha512-wryZ18vsxEAKFH7Z74zi/y/SyI1j6UkVZ6QsllBuT/bWlahNfQjLNwFsgh/5u7O957dYFoXj4yfma4n4X6kU9A==", + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-25.5.0.tgz", + "integrity": "sha512-iuxK6rQR2En9EID+2k+IBs5fCFd919gVVK5BeND82fYeLWPqvRcFNPKu9+gxTwfB5XwBGBvZ0HFQa+cHtIoslA==", "dev": true, "requires": { - "@jest/environment": "^25.4.0", - "@jest/fake-timers": "^25.4.0", - "@jest/types": "^25.4.0", - "jest-mock": "^25.4.0", - "jest-util": "^25.4.0", + "@jest/environment": "^25.5.0", + "@jest/fake-timers": "^25.5.0", + "@jest/types": "^25.5.0", + "jest-mock": "^25.5.0", + "jest-util": "^25.5.0", "semver": "^6.3.0" }, "dependencies": { @@ -14199,19 +13872,20 @@ "dev": true }, "jest-haste-map": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-25.4.0.tgz", - "integrity": "sha512-5EoCe1gXfGC7jmXbKzqxESrgRcaO3SzWXGCnvp9BcT0CFMyrB1Q6LIsjl9RmvmJGQgW297TCfrdgiy574Rl9HQ==", + "version": "25.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-25.5.1.tgz", + "integrity": "sha512-dddgh9UZjV7SCDQUrQ+5t9yy8iEgKc1AKqZR9YDww8xsVOtzPQSMVLDChc21+g29oTRexb9/B0bIlZL+sWmvAQ==", "dev": true, "requires": { - "@jest/types": "^25.4.0", + "@jest/types": "^25.5.0", + "@types/graceful-fs": "^4.1.2", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "fsevents": "^2.1.2", - "graceful-fs": "^4.2.3", - "jest-serializer": "^25.2.6", - "jest-util": "^25.4.0", - "jest-worker": "^25.4.0", + "graceful-fs": "^4.2.4", + "jest-serializer": "^25.5.0", + "jest-util": "^25.5.0", + "jest-worker": "^25.5.0", "micromatch": "^4.0.2", "sane": "^4.0.3", "walker": "^1.0.7", @@ -14247,9 +13921,9 @@ } }, "fsevents": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz", - "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", "dev": true, "optional": true }, @@ -14281,27 +13955,27 @@ } }, "jest-jasmine2": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-25.4.0.tgz", - "integrity": "sha512-QccxnozujVKYNEhMQ1vREiz859fPN/XklOzfQjm2j9IGytAkUbSwjFRBtQbHaNZ88cItMpw02JnHGsIdfdpwxQ==", + "version": "25.5.4", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-25.5.4.tgz", + "integrity": "sha512-9acbWEfbmS8UpdcfqnDO+uBUgKa/9hcRh983IHdM+pKmJPL77G0sWAAK0V0kr5LK3a8cSBfkFSoncXwQlRZfkQ==", "dev": true, "requires": { "@babel/traverse": "^7.1.0", - "@jest/environment": "^25.4.0", - "@jest/source-map": "^25.2.6", - "@jest/test-result": "^25.4.0", - "@jest/types": "^25.4.0", + "@jest/environment": "^25.5.0", + "@jest/source-map": "^25.5.0", + "@jest/test-result": "^25.5.0", + "@jest/types": "^25.5.0", "chalk": "^3.0.0", "co": "^4.6.0", - "expect": "^25.4.0", + "expect": "^25.5.0", "is-generator-fn": "^2.0.0", - "jest-each": "^25.4.0", - "jest-matcher-utils": "^25.4.0", - "jest-message-util": "^25.4.0", - "jest-runtime": "^25.4.0", - "jest-snapshot": "^25.4.0", - "jest-util": "^25.4.0", - "pretty-format": "^25.4.0", + "jest-each": "^25.5.0", + "jest-matcher-utils": "^25.5.0", + "jest-message-util": "^25.5.0", + "jest-runtime": "^25.5.4", + "jest-snapshot": "^25.5.1", + "jest-util": "^25.5.0", + "pretty-format": "^25.5.0", "throat": "^5.0.0" }, "dependencies": { @@ -14358,25 +14032,25 @@ } }, "jest-leak-detector": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-25.4.0.tgz", - "integrity": "sha512-7Y6Bqfv2xWsB+7w44dvZuLs5SQ//fzhETgOGG7Gq3TTGFdYvAgXGwV8z159RFZ6fXiCPm/szQ90CyfVos9JIFQ==", + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-25.5.0.tgz", + "integrity": "sha512-rV7JdLsanS8OkdDpZtgBf61L5xZ4NnYLBq72r6ldxahJWWczZjXawRsoHyXzibM5ed7C2QRjpp6ypgwGdKyoVA==", "dev": true, "requires": { "jest-get-type": "^25.2.6", - "pretty-format": "^25.4.0" + "pretty-format": "^25.5.0" } }, "jest-matcher-utils": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-25.4.0.tgz", - "integrity": "sha512-yPMdtj7YDgXhnGbc66bowk8AkQ0YwClbbwk3Kzhn5GVDrciiCr27U4NJRbrqXbTdtxjImONITg2LiRIw650k5A==", + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-25.5.0.tgz", + "integrity": "sha512-VWI269+9JS5cpndnpCwm7dy7JtGQT30UHfrnM3mXl22gHGt/b7NkjBqXfbhZ8V4B7ANUsjK18PlSBmG0YH7gjw==", "dev": true, "requires": { "chalk": "^3.0.0", - "jest-diff": "^25.4.0", + "jest-diff": "^25.5.0", "jest-get-type": "^25.2.6", - "pretty-format": "^25.4.0" + "pretty-format": "^25.5.0" }, "dependencies": { "ansi-styles": { @@ -14432,15 +14106,16 @@ } }, "jest-message-util": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-25.4.0.tgz", - "integrity": "sha512-LYY9hRcVGgMeMwmdfh9tTjeux1OjZHMusq/E5f3tJN+dAoVVkJtq5ZUEPIcB7bpxDUt2zjUsrwg0EGgPQ+OhXQ==", + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-25.5.0.tgz", + "integrity": "sha512-ezddz3YCT/LT0SKAmylVyWWIGYoKHOFOFXx3/nA4m794lfVUskMcwhip6vTgdVrOtYdjeQeis2ypzes9mZb4EA==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@jest/types": "^25.4.0", + "@jest/types": "^25.5.0", "@types/stack-utils": "^1.0.1", "chalk": "^3.0.0", + "graceful-fs": "^4.2.4", "micromatch": "^4.0.2", "slash": "^3.0.0", "stack-utils": "^1.0.1" @@ -14548,12 +14223,12 @@ } }, "jest-mock": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-25.4.0.tgz", - "integrity": "sha512-MdazSfcYAUjJjuVTTnusLPzE0pE4VXpOUzWdj8sbM+q6abUjm3bATVPXFqTXrxSieR8ocpvQ9v/QaQCftioQFg==", + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-25.5.0.tgz", + "integrity": "sha512-eXWuTV8mKzp/ovHc5+3USJMYsTBhyQ+5A1Mak35dey/RG8GlM4YWVylZuGgVXinaW6tpvk/RSecmF37FKUlpXA==", "dev": true, "requires": { - "@jest/types": "^25.4.0" + "@jest/types": "^25.5.0" } }, "jest-pnp-resolver": { @@ -14569,18 +14244,19 @@ "dev": true }, "jest-resolve": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-25.4.0.tgz", - "integrity": "sha512-wOsKqVDFWUiv8BtLMCC6uAJ/pHZkfFgoBTgPtmYlsprAjkxrr2U++ZnB3l5ykBMd2O24lXvf30SMAjJIW6k2aA==", + "version": "25.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-25.5.1.tgz", + "integrity": "sha512-Hc09hYch5aWdtejsUZhA+vSzcotf7fajSlPA6EZPE1RmPBAD39XtJhvHWFStid58iit4IPDLI/Da4cwdDmAHiQ==", "dev": true, "requires": { - "@jest/types": "^25.4.0", + "@jest/types": "^25.5.0", "browser-resolve": "^1.11.3", "chalk": "^3.0.0", + "graceful-fs": "^4.2.4", "jest-pnp-resolver": "^1.2.1", "read-pkg-up": "^7.0.1", "realpath-native": "^2.0.0", - "resolve": "^1.15.1", + "resolve": "^1.17.0", "slash": "^3.0.0" }, "dependencies": { @@ -14735,39 +14411,39 @@ } }, "jest-resolve-dependencies": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-25.4.0.tgz", - "integrity": "sha512-A0eoZXx6kLiuG1Ui7wITQPl04HwjLErKIJTt8GR3c7UoDAtzW84JtCrgrJ6Tkw6c6MwHEyAaLk7dEPml5pf48A==", + "version": "25.5.4", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-25.5.4.tgz", + "integrity": "sha512-yFmbPd+DAQjJQg88HveObcGBA32nqNZ02fjYmtL16t1xw9bAttSn5UGRRhzMHIQbsep7znWvAvnD4kDqOFM0Uw==", "dev": true, "requires": { - "@jest/types": "^25.4.0", + "@jest/types": "^25.5.0", "jest-regex-util": "^25.2.6", - "jest-snapshot": "^25.4.0" + "jest-snapshot": "^25.5.1" } }, "jest-runner": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-25.4.0.tgz", - "integrity": "sha512-wWQSbVgj2e/1chFdMRKZdvlmA6p1IPujhpLT7TKNtCSl1B0PGBGvJjCaiBal/twaU2yfk8VKezHWexM8IliBfA==", + "version": "25.5.4", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-25.5.4.tgz", + "integrity": "sha512-V/2R7fKZo6blP8E9BL9vJ8aTU4TH2beuqGNxHbxi6t14XzTb+x90B3FRgdvuHm41GY8ch4xxvf0ATH4hdpjTqg==", "dev": true, "requires": { - "@jest/console": "^25.4.0", - "@jest/environment": "^25.4.0", - "@jest/test-result": "^25.4.0", - "@jest/types": "^25.4.0", + "@jest/console": "^25.5.0", + "@jest/environment": "^25.5.0", + "@jest/test-result": "^25.5.0", + "@jest/types": "^25.5.0", "chalk": "^3.0.0", "exit": "^0.1.2", - "graceful-fs": "^4.2.3", - "jest-config": "^25.4.0", + "graceful-fs": "^4.2.4", + "jest-config": "^25.5.4", "jest-docblock": "^25.3.0", - "jest-haste-map": "^25.4.0", - "jest-jasmine2": "^25.4.0", - "jest-leak-detector": "^25.4.0", - "jest-message-util": "^25.4.0", - "jest-resolve": "^25.4.0", - "jest-runtime": "^25.4.0", - "jest-util": "^25.4.0", - "jest-worker": "^25.4.0", + "jest-haste-map": "^25.5.1", + "jest-jasmine2": "^25.5.4", + "jest-leak-detector": "^25.5.0", + "jest-message-util": "^25.5.0", + "jest-resolve": "^25.5.1", + "jest-runtime": "^25.5.4", + "jest-util": "^25.5.0", + "jest-worker": "^25.5.0", "source-map-support": "^0.5.6", "throat": "^5.0.0" }, @@ -14825,32 +14501,33 @@ } }, "jest-runtime": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-25.4.0.tgz", - "integrity": "sha512-lgNJlCDULtXu9FumnwCyWlOub8iytijwsPNa30BKrSNtgoT6NUMXOPrZvsH06U6v0wgD/Igwz13nKA2wEKU2VA==", - "dev": true, - "requires": { - "@jest/console": "^25.4.0", - "@jest/environment": "^25.4.0", - "@jest/source-map": "^25.2.6", - "@jest/test-result": "^25.4.0", - "@jest/transform": "^25.4.0", - "@jest/types": "^25.4.0", + "version": "25.5.4", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-25.5.4.tgz", + "integrity": "sha512-RWTt8LeWh3GvjYtASH2eezkc8AehVoWKK20udV6n3/gC87wlTbE1kIA+opCvNWyyPeBs6ptYsc6nyHUb1GlUVQ==", + "dev": true, + "requires": { + "@jest/console": "^25.5.0", + "@jest/environment": "^25.5.0", + "@jest/globals": "^25.5.2", + "@jest/source-map": "^25.5.0", + "@jest/test-result": "^25.5.0", + "@jest/transform": "^25.5.1", + "@jest/types": "^25.5.0", "@types/yargs": "^15.0.0", "chalk": "^3.0.0", "collect-v8-coverage": "^1.0.0", "exit": "^0.1.2", "glob": "^7.1.3", - "graceful-fs": "^4.2.3", - "jest-config": "^25.4.0", - "jest-haste-map": "^25.4.0", - "jest-message-util": "^25.4.0", - "jest-mock": "^25.4.0", + "graceful-fs": "^4.2.4", + "jest-config": "^25.5.4", + "jest-haste-map": "^25.5.1", + "jest-message-util": "^25.5.0", + "jest-mock": "^25.5.0", "jest-regex-util": "^25.2.6", - "jest-resolve": "^25.4.0", - "jest-snapshot": "^25.4.0", - "jest-util": "^25.4.0", - "jest-validate": "^25.4.0", + "jest-resolve": "^25.5.1", + "jest-snapshot": "^25.5.1", + "jest-util": "^25.5.0", + "jest-validate": "^25.5.0", "realpath-native": "^2.0.0", "slash": "^3.0.0", "strip-bom": "^4.0.0", @@ -14922,30 +14599,34 @@ } }, "jest-serializer": { - "version": "25.2.6", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-25.2.6.tgz", - "integrity": "sha512-RMVCfZsezQS2Ww4kB5HJTMaMJ0asmC0BHlnobQC6yEtxiFKIxohFA4QSXSabKwSggaNkqxn6Z2VwdFCjhUWuiQ==", - "dev": true + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-25.5.0.tgz", + "integrity": "sha512-LxD8fY1lByomEPflwur9o4e2a5twSQ7TaVNLlFUuToIdoJuBt8tzHfCsZ42Ok6LkKXWzFWf3AGmheuLAA7LcCA==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.4" + } }, "jest-snapshot": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-25.4.0.tgz", - "integrity": "sha512-J4CJ0X2SaGheYRZdLz9CRHn9jUknVmlks4UBeu270hPAvdsauFXOhx9SQP2JtRzhnR3cvro/9N9KP83/uvFfRg==", + "version": "25.5.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-25.5.1.tgz", + "integrity": "sha512-C02JE1TUe64p2v1auUJ2ze5vcuv32tkv9PyhEb318e8XOKF7MOyXdJ7kdjbvrp3ChPLU2usI7Rjxs97Dj5P0uQ==", "dev": true, "requires": { "@babel/types": "^7.0.0", - "@jest/types": "^25.4.0", + "@jest/types": "^25.5.0", "@types/prettier": "^1.19.0", "chalk": "^3.0.0", - "expect": "^25.4.0", - "jest-diff": "^25.4.0", + "expect": "^25.5.0", + "graceful-fs": "^4.2.4", + "jest-diff": "^25.5.0", "jest-get-type": "^25.2.6", - "jest-matcher-utils": "^25.4.0", - "jest-message-util": "^25.4.0", - "jest-resolve": "^25.4.0", + "jest-matcher-utils": "^25.5.0", + "jest-message-util": "^25.5.0", + "jest-resolve": "^25.5.1", "make-dir": "^3.0.0", "natural-compare": "^1.4.0", - "pretty-format": "^25.4.0", + "pretty-format": "^25.5.0", "semver": "^6.3.0" }, "dependencies": { @@ -14991,9 +14672,9 @@ "dev": true }, "make-dir": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.2.tgz", - "integrity": "sha512-rYKABKutXa6vXTXhoV18cBE7PaewPXHe/Bdq4v+ZLMhxbWApkFFplT0LcbMW+6BbjnQXzZ/sAvSE/JdguApG5w==", + "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, "requires": { "semver": "^6.0.0" @@ -15017,13 +14698,14 @@ } }, "jest-util": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-25.4.0.tgz", - "integrity": "sha512-WSZD59sBtAUjLv1hMeKbNZXmMcrLRWcYqpO8Dz8b4CeCTZpfNQw2q9uwrYAD+BbJoLJlu4ezVPwtAmM/9/SlZA==", + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-25.5.0.tgz", + "integrity": "sha512-KVlX+WWg1zUTB9ktvhsg2PXZVdkI1NBevOJSkTKYAyXyH4QSvh+Lay/e/v+bmaFfrkfx43xD8QTfgobzlEXdIA==", "dev": true, "requires": { - "@jest/types": "^25.4.0", + "@jest/types": "^25.5.0", "chalk": "^3.0.0", + "graceful-fs": "^4.2.4", "is-ci": "^2.0.0", "make-dir": "^3.0.0" }, @@ -15070,9 +14752,9 @@ "dev": true }, "make-dir": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.2.tgz", - "integrity": "sha512-rYKABKutXa6vXTXhoV18cBE7PaewPXHe/Bdq4v+ZLMhxbWApkFFplT0LcbMW+6BbjnQXzZ/sAvSE/JdguApG5w==", + "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, "requires": { "semver": "^6.0.0" @@ -15096,17 +14778,17 @@ } }, "jest-validate": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-25.4.0.tgz", - "integrity": "sha512-hvjmes/EFVJSoeP1yOl8qR8mAtMR3ToBkZeXrD/ZS9VxRyWDqQ/E1C5ucMTeSmEOGLipvdlyipiGbHJ+R1MQ0g==", + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-25.5.0.tgz", + "integrity": "sha512-okUFKqhZIpo3jDdtUXUZ2LxGUZJIlfdYBvZb1aczzxrlyMlqdnnws9MOxezoLGhSaFc2XYaHNReNQfj5zPIWyQ==", "dev": true, "requires": { - "@jest/types": "^25.4.0", + "@jest/types": "^25.5.0", "camelcase": "^5.3.1", "chalk": "^3.0.0", "jest-get-type": "^25.2.6", "leven": "^3.1.0", - "pretty-format": "^25.4.0" + "pretty-format": "^25.5.0" }, "dependencies": { "ansi-styles": { @@ -15162,16 +14844,16 @@ } }, "jest-watcher": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-25.4.0.tgz", - "integrity": "sha512-36IUfOSRELsKLB7k25j/wutx0aVuHFN6wO94gPNjQtQqFPa2rkOymmx9rM5EzbF3XBZZ2oqD9xbRVoYa2w86gw==", + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-25.5.0.tgz", + "integrity": "sha512-XrSfJnVASEl+5+bb51V0Q7WQx65dTSk7NL4yDdVjPnRNpM0hG+ncFmDYJo9O8jaSRcAitVbuVawyXCRoxGrT5Q==", "dev": true, "requires": { - "@jest/test-result": "^25.4.0", - "@jest/types": "^25.4.0", + "@jest/test-result": "^25.5.0", + "@jest/types": "^25.5.0", "ansi-escapes": "^4.2.1", "chalk": "^3.0.0", - "jest-util": "^25.4.0", + "jest-util": "^25.5.0", "string-length": "^3.1.0" }, "dependencies": { @@ -15243,9 +14925,9 @@ } }, "jest-worker": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-25.4.0.tgz", - "integrity": "sha512-ghAs/1FtfYpMmYQ0AHqxV62XPvKdUDIBBApMZfly+E9JEmYh2K45G0R5dWxx986RN12pRCxsViwQVtGl+N4whw==", + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-25.5.0.tgz", + "integrity": "sha512-/dsSmUkIy5EBGfv/IjjqmFxrNAUpBERfGs1oHROyD7yxjG/w+t0GOJDX8O1k32ySmd7+a5IhnJU2qQFcJ4n1vw==", "dev": true, "requires": { "merge-stream": "^2.0.0", @@ -15529,9 +15211,9 @@ } }, "ws": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.3.tgz", - "integrity": "sha512-HTDl9G9hbkNDk98naoR/cHDws7+EyYMOdL1BmjsZXRUjf7d+MficC4B7HLUPlSiho0vg+CWKrGIt/VJBd1xunQ==", + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.5.tgz", + "integrity": "sha512-C34cIU4+DB2vMyAbmEKossWq2ZQDr6QEyuuCzWrM9zfw1sGc0mYiJ0UnG9zzNykt49C2Fi34hvr2vssFQRS6EA==", "dev": true } } @@ -15658,9 +15340,9 @@ } }, "jsonata": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/jsonata/-/jsonata-1.8.2.tgz", - "integrity": "sha512-ma5F/Bs47dZfJfDZ0Dt37eIbzVBVKZIDqsZSqdCCAPNHxKn+s3+CfMA6ahVVlf8Y1hyIjXkVLFU7yv4XxRfihA==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/jsonata/-/jsonata-1.8.3.tgz", + "integrity": "sha512-r6ztI6ohbpRo77AxBm6vMs3aHZi2L2PaakW7TCPwSkeGcuAZ/SxXGLWH2Npwqq5+YBM/fg/g0EXg/pI9HvXQ8Q==", "dev": true }, "jsonfile": { @@ -15779,6 +15461,17 @@ "safe-buffer": "^5.0.1" } }, + "jwk-to-pem": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/jwk-to-pem/-/jwk-to-pem-2.0.3.tgz", + "integrity": "sha512-T1MA0L3DVB2mOIZytZyNTdcAAOJscLLCi25dgzQtkHjTcuwpRW3BFnjj0eEpMORfJyZtFZ5wy++Ys6wsMolPsA==", + "dev": true, + "requires": { + "asn1.js": "^5.3.0", + "elliptic": "^6.5.2", + "safe-buffer": "^5.0.1" + } + }, "jws": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", @@ -16198,12 +15891,12 @@ } }, "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", "dev": true, "requires": { - "invert-kv": "^1.0.0" + "invert-kv": "^2.0.0" } }, "leven": { @@ -16486,6 +16179,12 @@ "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=", "dev": true }, + "lodash.escape": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz", + "integrity": "sha1-yQRGkMIeBClL6qUXcS/e0fqI3pg=", + "dev": true + }, "lodash.filter": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz", @@ -16498,6 +16197,12 @@ "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", "dev": true }, + "lodash.flattendeep": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", + "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", + "dev": true + }, "lodash.foreach": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz", @@ -16826,22 +16531,22 @@ "dev": true }, "luxon": { - "version": "1.23.0", - "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.23.0.tgz", - "integrity": "sha512-+6a/bXsCWrrR8vfbL41iM92es12zwV2Rum/KPkT+ubOZnnU3Sqbqok/FmD1xsWlWN2Y9Hu0fU/vNgU24ns7bpA==", + "version": "1.24.1", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.24.1.tgz", + "integrity": "sha512-CgnIMKAWT0ghcuWFfCWBnWGOddM0zu6c4wZAWmD0NN7MZTnro0+833DF6tJep+xlxRPg4KtsYEHYLfTMBQKwYg==", "dev": true }, "madge": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/madge/-/madge-3.8.0.tgz", - "integrity": "sha512-bcX2QxiTwWvZrNM+XkmZY1SPl18C2HGaQGhroj3YzqSRxQ1ns7WXCYDyGCfZwp/uLibnNd6IOWrRLOkCS+lpAg==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/madge/-/madge-3.9.0.tgz", + "integrity": "sha512-ABR2ZTFga+TPLzlu2u46lcv8WwOzoI6VMTMqe3DyaY0igzyGpXiOIH1vAtziSKC4UHuyTpwkfhjWN5qOYR/5OA==", "dev": true, "requires": { - "chalk": "^3.0.0", - "commander": "^4.0.1", + "chalk": "^4.0.0", + "commander": "^5.1.0", "commondir": "^1.0.1", "debug": "^4.0.1", - "dependency-tree": "^7.0.2", + "dependency-tree": "^7.2.1", "detective-amd": "^3.0.0", "detective-cjs": "^3.1.1", "detective-es6": "^2.1.0", @@ -16850,12 +16555,12 @@ "detective-sass": "^3.0.1", "detective-scss": "^2.0.1", "detective-stylus": "^1.0.0", - "detective-typescript": "^5.7.0", + "detective-typescript": "^5.8.0", "graphviz": "0.0.9", - "ora": "^4.0.2", - "pify": "^4.0.0", + "ora": "^4.0.4", + "pify": "^5.0.0", "pluralize": "^8.0.0", - "pretty-ms": "^5.0.0", + "pretty-ms": "^7.0.0", "rc": "^1.2.7", "walkdir": "^0.4.1" }, @@ -16871,9 +16576,9 @@ } }, "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz", + "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -16895,6 +16600,12 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "dev": true + }, "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", @@ -16916,6 +16627,12 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "pify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz", + "integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==", + "dev": true + }, "supports-color": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", @@ -17002,6 +16719,14 @@ "linkify-it": "^2.0.0", "mdurl": "^1.0.1", "uc.micro": "^1.0.5" + }, + "dependencies": { + "entities": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.0.tgz", + "integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==", + "dev": true + } } }, "markdown-it-anchor": { @@ -17332,18 +17057,18 @@ "dev": true }, "mime-db": { - "version": "1.43.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", - "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==", + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", "dev": true }, "mime-types": { - "version": "2.1.26", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", - "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", "dev": true, "requires": { - "mime-db": "1.43.0" + "mime-db": "1.44.0" } }, "mimic-fn": { @@ -17522,6 +17247,12 @@ "moment": ">= 2.9.0" } }, + "moo": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz", + "integrity": "sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w==", + "dev": true + }, "move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", @@ -17573,9 +17304,9 @@ "dev": true }, "nan": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", - "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", + "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==", "dev": true }, "nanoid": { @@ -17644,6 +17375,27 @@ } } }, + "nearley": { + "version": "2.19.3", + "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.19.3.tgz", + "integrity": "sha512-FpAy1PmTsUpOtgxr23g4jRNvJHYzZEW2PixXeSzksLR/ykPfwKhAodc2+9wQhY+JneWLcvkDw6q7FJIsIdF/aQ==", + "dev": true, + "requires": { + "commander": "^2.19.0", + "moo": "^0.5.0", + "railroad-diagrams": "^1.0.0", + "randexp": "0.4.6", + "semver": "^5.4.1" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + } + } + }, "negotiator": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", @@ -17861,15 +17613,15 @@ } }, "node-releases": { - "version": "1.1.53", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.53.tgz", - "integrity": "sha512-wp8zyQVwef2hpZ/dJH7SfSrIPD6YoJz6BDQDpGEkcA0s3LpAQoxBIYmfIq6QAhC1DhwsyCgTaTTcONwX8qzCuQ==", + "version": "1.1.55", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.55.tgz", + "integrity": "sha512-H3R3YR/8TjT5WPin/wOoHOUPHgvj8leuU/Keta/rwelEQN9pA/S2Dx8/se4pZ2LBxSd0nAGzsNzhqwa77v7F1w==", "dev": true }, "node-sass": { - "version": "4.13.1", - "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.13.1.tgz", - "integrity": "sha512-TTWFx+ZhyDx1Biiez2nB0L3YrCZ/8oHagaDalbuBSlqXgUPsdkUSzJsVxeDO9LtPB49+Fh3WQl3slABo6AotNw==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.14.1.tgz", + "integrity": "sha512-sjCuOlvGyCJS40R8BscF5vhVlQjNN069NtQ1gSxyK1u9iqvn6tf7O1R4GNowVZfiZUCRt5MmMs1xd+4V/7Yr0g==", "dev": true, "requires": { "async-foreach": "^0.1.3", @@ -17886,7 +17638,7 @@ "node-gyp": "^3.8.0", "npmlog": "^4.0.0", "request": "^2.88.0", - "sass-graph": "^2.2.4", + "sass-graph": "2.2.5", "stdout-stream": "^1.4.0", "true-case-path": "^1.0.2" }, @@ -18426,9 +18178,9 @@ } }, "ora": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/ora/-/ora-4.0.3.tgz", - "integrity": "sha512-fnDebVFyz309A73cqCipVL1fBZewq4vwgSHfxh43vVy31mbyoQ8sCH3Oeaog/owYOs/lLlGVPCISQonTneg6Pg==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/ora/-/ora-4.0.4.tgz", + "integrity": "sha512-77iGeVU1cIdRhgFzCK8aw1fbtT1B/iZAvWjS+l/o1x0RShMgxHUZaD2yDpWsNCPwXg9z1ZA78Kbdvr8kBmG/Ww==", "dev": true, "requires": { "chalk": "^3.0.0", @@ -18564,12 +18316,14 @@ "dev": true }, "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", "dev": true, "requires": { - "lcid": "^1.0.0" + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" } }, "os-tmpdir": { @@ -18834,6 +18588,30 @@ "supports-color": "^2.0.0" } }, + "cheerio": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz", + "integrity": "sha1-qbqoYKP5tZWmuBsahocxIe06Jp4=", + "dev": true, + "requires": { + "css-select": "~1.2.0", + "dom-serializer": "~0.1.0", + "entities": "~1.1.1", + "htmlparser2": "^3.9.1", + "lodash.assignin": "^4.0.9", + "lodash.bind": "^4.1.4", + "lodash.defaults": "^4.0.1", + "lodash.filter": "^4.4.0", + "lodash.flatten": "^4.2.0", + "lodash.foreach": "^4.3.0", + "lodash.map": "^4.4.0", + "lodash.merge": "^4.4.0", + "lodash.pick": "^4.2.1", + "lodash.reduce": "^4.4.0", + "lodash.reject": "^4.4.0", + "lodash.some": "^4.4.0" + } + }, "commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -19218,12 +18996,6 @@ "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", "dev": true }, - "invert-kv": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", - "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", - "dev": true - }, "is-fullwidth-code-point": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", @@ -19233,26 +19005,6 @@ "number-is-nan": "^1.0.0" } }, - "lcid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", - "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", - "dev": true, - "requires": { - "invert-kv": "^2.0.0" - } - }, - "os-locale": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", - "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", - "dev": true, - "requires": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" - } - }, "require-main-filename": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", @@ -19381,6 +19133,19 @@ "evp_bytestokey": "^1.0.0", "pbkdf2": "^3.0.3", "safe-buffer": "^5.1.1" + }, + "dependencies": { + "asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + } } }, "parse-entities": { @@ -19413,10 +19178,13 @@ "dev": true }, "parse5": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", - "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==", - "dev": true + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz", + "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==", + "dev": true, + "requires": { + "@types/node": "*" + } }, "parseurl": { "version": "1.3.3", @@ -19563,15 +19331,15 @@ } }, "pdf-lib": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/pdf-lib/-/pdf-lib-1.4.1.tgz", - "integrity": "sha512-Fj72wP2ZNIr797953v+8iQSH0argRdFkd8nbW+q0ngsuocgwCC9FT7sSXLsaSsUGM5eNKQlKJNHvWQlo7+ROJA==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/pdf-lib/-/pdf-lib-1.5.0.tgz", + "integrity": "sha512-ZpMB7AY7JxvhAAaz/YS0J67Con+ks63h9GWSTHbul46mg1j35pfz6LN/xNGiwoMM19PjaxTbtuhNQAePIyKyRA==", "dev": true, "requires": { "@pdf-lib/standard-fonts": "^0.0.4", "@pdf-lib/upng": "^1.0.1", - "pako": "^1.0.10", - "tslib": "^1.10.0" + "pako": "^1.0.11", + "tslib": "^1.11.1" }, "dependencies": { "pako": { @@ -19798,9 +19566,9 @@ "dev": true }, "postcss": { - "version": "7.0.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", - "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", + "version": "7.0.29", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.29.tgz", + "integrity": "sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -20518,9 +20286,9 @@ } }, "postcss-value-parser": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.0.3.tgz", - "integrity": "sha512-N7h4pG+Nnu5BEIzyeaaIYWs0LI5XC40OrRh5L60z0QjFsqGWcHcbkBvpe1WYpcIS9yQ8sOi/vIPt1ejQCrMVrg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", + "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==", "dev": true }, "postcss-values-parser": { @@ -20616,9 +20384,9 @@ "dev": true }, "prettier": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.0.4.tgz", - "integrity": "sha512-SVJIQ51spzFDvh4fIbCLvciiDMCrRhlN3mbZvv/+ycjvmF5E73bKdGfU8QDLNmjYJf+lsGnDBC4UUnvTe5OO0w==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.0.5.tgz", + "integrity": "sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg==", "dev": true }, "prettier-linter-helpers": { @@ -20637,12 +20405,12 @@ "dev": true }, "pretty-format": { - "version": "25.4.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.4.0.tgz", - "integrity": "sha512-PI/2dpGjXK5HyXexLPZU/jw5T9Q6S1YVXxxVxco+LIqzUFHXIbKZKdUVt7GcX7QUCr31+3fzhi4gN4/wUYPVxQ==", + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.5.0.tgz", + "integrity": "sha512-kbo/kq2LQ/A/is0PQwsEHM7Ca6//bGPPvU6UnsdDRSKTWxT/ru/xb88v4BJf6a69H+uTytOEsTusT9ksd/1iWQ==", "dev": true, "requires": { - "@jest/types": "^25.4.0", + "@jest/types": "^25.5.0", "ansi-regex": "^5.0.0", "ansi-styles": "^4.0.0", "react-is": "^16.12.0" @@ -20682,9 +20450,9 @@ } }, "pretty-ms": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-5.1.0.tgz", - "integrity": "sha512-4gaK1skD2gwscCfkswYQRmddUb2GJZtzDGRjHWadVHtK/DIKFufa12MvES6/xu1tVbUYeia5bmLcwJtZJQUqnw==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-7.0.0.tgz", + "integrity": "sha512-J3aPWiC5e9ZeZFuSeBraGxSkGMOvulSWsxDByOcbD1Pr75YL3LSNIKIb52WXbCLE1sS5s4inBBbryjF4Y05Ceg==", "dev": true, "requires": { "parse-ms": "^2.1.0" @@ -20781,6 +20549,17 @@ "react-is": "^16.8.1" } }, + "prop-types-exact": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/prop-types-exact/-/prop-types-exact-1.2.0.tgz", + "integrity": "sha512-K+Tk3Kd9V0odiXFP9fwDHUYRyvK3Nun3GVyPapSIs5OBkITAm15W0CPFD/YKTkMUAbc0b9CUwRQp2ybiBIq+eA==", + "dev": true, + "requires": { + "has": "^1.0.3", + "object.assign": "^4.1.0", + "reflect.ownkeys": "^0.2.0" + } + }, "proto-list": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", @@ -21036,9 +20815,9 @@ } }, "mime": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", - "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.5.tgz", + "integrity": "sha512-3hQhEUF027BuxZjQA3s7rIv/7VCQPa27hN9u9g87sEkWaKwQPuXOkVKtOeiyUrnWqTDiOs8Ed2rwg733mB0R5w==", "dev": true }, "ms": { @@ -21084,9 +20863,9 @@ } }, "mime": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", - "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.5.tgz", + "integrity": "sha512-3hQhEUF027BuxZjQA3s7rIv/7VCQPa27hN9u9g87sEkWaKwQPuXOkVKtOeiyUrnWqTDiOs8Ed2rwg733mB0R5w==", "dev": true }, "ms": { @@ -21253,9 +21032,9 @@ "dev": true }, "qs": { - "version": "6.9.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.3.tgz", - "integrity": "sha512-EbZYNarm6138UKKq46tdx08Yo/q9ZhFoAXAI1meAFd2GtbRDhbZY2WQSICskT0c5q99aFzLG1D4nvTk9tqfXIw==", + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz", + "integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==", "dev": true }, "query-string": { @@ -21364,12 +21143,37 @@ } } }, + "raf": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", + "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", + "dev": true, + "requires": { + "performance-now": "^2.1.0" + } + }, + "railroad-diagrams": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", + "integrity": "sha1-635iZ1SN3t+4mcG5Dlc3RVnN234=", + "dev": true + }, "ramda": { "version": "0.26.1", "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.26.1.tgz", "integrity": "sha512-hLWjpy7EnsDBb0p+Z3B7rPi3GDeRG5ZtiI33kJhTt+ORCd38AbAIjB/9zRIUoeTbE/AVX5ZkU7m6bznsvrf8eQ==", "dev": true }, + "randexp": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", + "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", + "dev": true, + "requires": { + "discontinuous-range": "1.0.0", + "ret": "~0.1.10" + } + }, "random-bytes": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", @@ -21504,12 +21308,6 @@ "scheduler": "^0.19.1" } }, - "react-dom-factories": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/react-dom-factories/-/react-dom-factories-1.0.2.tgz", - "integrity": "sha1-63cFxNs2+1AbOqOP91lhaqD/luA=", - "dev": true - }, "react-idle-timer": { "version": "4.2.12", "resolved": "https://registry.npmjs.org/react-idle-timer/-/react-idle-timer-4.2.12.tgz", @@ -21532,17 +21330,14 @@ "dev": true }, "react-quill": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/react-quill/-/react-quill-1.3.5.tgz", - "integrity": "sha512-/W/rNCW+6QpGz8yQ9tFK5Ka/h/No1RqrcOOvCIOR092OiKzRFlU2xbPEwiP3Wgy/Dx13pi1YhjReDMX/5uotJg==", + "version": "2.0.0-beta.2", + "resolved": "https://registry.npmjs.org/react-quill/-/react-quill-2.0.0-beta.2.tgz", + "integrity": "sha512-jzoq57Mt216sCOr59OC6aMgmckdAh3BgKgEqYI/FcS26JwCMlXMgGu7Dc7TApzObax9dwOWbr6lT8cEWxigyVA==", "dev": true, "requires": { - "@types/quill": "1.3.10", - "create-react-class": "^15.6.0", + "@types/quill": "^1.3.10", "lodash": "^4.17.4", - "prop-types": "^15.5.10", - "quill": "^1.3.7", - "react-dom-factories": "^1.0.0" + "quill": "^1.3.7" } }, "react-responsive": { @@ -21586,9 +21381,9 @@ } }, "react-transition-group": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.3.0.tgz", - "integrity": "sha512-1qRV1ZuVSdxPlPf4O8t7inxUGpdyO5zG9IoNfJxSO0ImU2A1YWkEQvFPuIPZmMLkg5hYs7vv5mMOyfgSkvAwvw==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.1.tgz", + "integrity": "sha512-Djqr7OQ2aPUiYurhPalTrVy9ddmFCCzwhqQmtN+J3+3DzLO209Fdr70QrN8Z3DsglWql6iY1lDWAfpFiBtuKGw==", "dev": true, "requires": { "@babel/runtime": "^7.5.5", @@ -21644,6 +21439,12 @@ "readable-stream": "^2.0.2" } }, + "readline": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/readline/-/readline-1.3.0.tgz", + "integrity": "sha1-xYDXfvLPyHUrEySYBg3JeTp6wBw=", + "dev": true + }, "realpath-native": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-2.0.0.tgz", @@ -21683,6 +21484,12 @@ } } }, + "reflect.ownkeys": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz", + "integrity": "sha1-dJrO7H8/34tj+SegSAnpDFwLNGA=", + "dev": true + }, "regenerate": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", @@ -21813,9 +21620,9 @@ } }, "remark-parse": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.1.tgz", - "integrity": "sha512-Ye/5W57tdQZWsfkuVyRq9SUWRgECHnDsMuyUMzdSKpTbNPkZeGtoYfsrkeSi4+Xyl0mhcPPddHITXPcCPHrl3w==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.2.tgz", + "integrity": "sha512-eMI6kMRjsAGpMXXBAywJwiwAse+KNpmt+BK55Oofy4KvBZEqUDj6mWbGLJZrujoPIPPxDXzn3T9baRlpsm2jnQ==", "dev": true, "requires": { "ccount": "^1.0.0", @@ -21886,9 +21693,9 @@ } }, "replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", + "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", "dev": true }, "replaceall": { @@ -22030,9 +21837,9 @@ } }, "resolve": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.16.1.tgz", - "integrity": "sha512-rmAglCSqWWMrrBv/XM6sW0NuRFiKViw/W4d9EbC4pt+49H8JwHy+mcGmALTEg504AUDcLTvb1T2q3E9AnmY+ig==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", "dev": true, "requires": { "path-parse": "^1.0.6" @@ -22163,6 +21970,16 @@ "integrity": "sha1-ROAIWOvrwBM9WOQLLNih+7BCA/U=", "dev": true }, + "rst-selector-parser": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz", + "integrity": "sha1-gbIw6i/MYGbInjRy3nlChdmwPZE=", + "dev": true, + "requires": { + "lodash.flattendeep": "^4.4.0", + "nearley": "^2.7.10" + } + }, "rsvp": { "version": "4.8.5", "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz", @@ -22170,13 +21987,10 @@ "dev": true }, "run-async": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.0.tgz", - "integrity": "sha512-xJTbh/d7Lm7SBhc1tNvTpeCHaEzoyxPrqNlvSdMfBTYwaY++UJFyXUOxAtsRUXjlqOfj8luNaR9vjCh4KeV+pg==", - "dev": true, - "requires": { - "is-promise": "^2.1.0" - } + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true }, "run-parallel": { "version": "1.1.9", @@ -22246,74 +22060,6 @@ "requires": { "archiver": "^3.1.1", "s3-files": "^2.0.0" - }, - "dependencies": { - "archiver": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/archiver/-/archiver-3.1.1.tgz", - "integrity": "sha512-5Hxxcig7gw5Jod/8Gq0OneVgLYET+oNHcxgWItq4TbhOzRLKNAFUb9edAftiMKXvXfCB0vbGrJdZDNq0dWMsxg==", - "dev": true, - "requires": { - "archiver-utils": "^2.1.0", - "async": "^2.6.3", - "buffer-crc32": "^0.2.1", - "glob": "^7.1.4", - "readable-stream": "^3.4.0", - "tar-stream": "^2.1.0", - "zip-stream": "^2.1.2" - } - }, - "compress-commons": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-2.1.1.tgz", - "integrity": "sha512-eVw6n7CnEMFzc3duyFVrQEuY1BlHR3rYsSztyG32ibGMW722i3C6IizEGMFmfMU+A+fALvBIwxN3czffTcdA+Q==", - "dev": true, - "requires": { - "buffer-crc32": "^0.2.13", - "crc32-stream": "^3.0.1", - "normalize-path": "^3.0.0", - "readable-stream": "^2.3.6" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - } - } - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "zip-stream": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-2.1.3.tgz", - "integrity": "sha512-EkXc2JGcKhO5N5aZ7TmuNo45budRaFGHOmz24wtJR7znbNqDPmdZtUauKX6et8KAVseAMBOyWJqEpXcHTBsh7Q==", - "dev": true, - "requires": { - "archiver-utils": "^2.1.0", - "compress-commons": "^2.1.1", - "readable-stream": "^3.4.0" - } - } } }, "s3rver": { @@ -22425,204 +22171,149 @@ } }, "sass": { - "version": "1.26.3", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.26.3.tgz", - "integrity": "sha512-5NMHI1+YFYw4sN3yfKjpLuV9B5l7MqQ6FlkTcC4FT+oHbBRUZoSjHrrt/mE0nFXJyY2kQtU9ou9HxvFVjLFuuw==", + "version": "1.26.5", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.26.5.tgz", + "integrity": "sha512-FG2swzaZUiX53YzZSjSakzvGtlds0lcbF+URuU9mxOv7WBh7NhXEVDa4kPKN4hN6fC2TkOTOKqiqp6d53N9X5Q==", "dev": true, "requires": { "chokidar": ">=2.0.0 <4.0.0" } }, "sass-graph": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz", - "integrity": "sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=", + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.5.tgz", + "integrity": "sha512-VFWDAHOe6mRuT4mZRd4eKE+d8Uedrk6Xnh7Sh9b4NGufQLQjOrvf/MQoOdx+0s92L89FeyUUNfU597j/3uNpag==", "dev": true, "requires": { - "glob": "^7.0.0", - "lodash": "^4.0.0", - "scss-tokenizer": "^0.2.3", - "yargs": "^7.0.0" - }, - "dependencies": { - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } - }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "glob": "^7.0.0", + "lodash": "^4.0.0", + "scss-tokenizer": "^0.2.3", + "yargs": "^13.3.2" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", "dev": true, "requires": { - "number-is-nan": "^1.0.0" + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" } }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - } + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dev": true, "requires": { - "pinkie-promise": "^2.0.0" + "locate-path": "^3.0.0" } }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" } }, - "pify": { + "p-limit": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" + "p-try": "^2.0.0" } }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "dev": true, "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" + "p-limit": "^2.0.0" } }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "p-try": { + "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 }, "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", "dev": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" } }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "requires": { - "is-utf8": "^0.2.0" + "ansi-regex": "^4.1.0" } }, - "which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true - }, "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", "dev": true, "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" } }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true - }, "yargs": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", - "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", "dev": true, "requires": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", + "require-main-filename": "^2.0.0", "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^5.0.0" + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" } }, "yargs-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", - "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", "dev": true, "requires": { - "camelcase": "^3.0.0" + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } } } @@ -23349,19 +23040,19 @@ } }, "serverless-jetpack": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/serverless-jetpack/-/serverless-jetpack-0.10.3.tgz", - "integrity": "sha512-W/3ggCS6Qim7lerU+6DEp/P8C+KBpDHs6q1R+RVuQeuxBYUIzxYo5zNminpfMm5Dnx4Sa7yrG95FQRqb3yTjIg==", + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/serverless-jetpack/-/serverless-jetpack-0.10.6.tgz", + "integrity": "sha512-91+vrX36nKTalSEEhq4bpLYEQNsiVgP0SOvKE5g1QLMnLfBeVJVvUXsBzRLyVCnxMF3S2vqszpkq/eql9JomrQ==", "dev": true, "requires": { "archiver": "^3.1.1", "globby": "^9.2.0", "inspectdep": "^0.2.0", - "jest-worker": "^25.2.6", + "jest-worker": "^25.5.0", "make-dir": "^3.0.2", "nanomatch": "^1.2.13", "p-limit": "^2.3.0", - "trace-deps": "^0.3.0" + "trace-deps": "^0.3.3" }, "dependencies": { "@nodelib/fs.stat": { @@ -23370,21 +23061,6 @@ "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", "dev": true }, - "archiver": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/archiver/-/archiver-3.1.1.tgz", - "integrity": "sha512-5Hxxcig7gw5Jod/8Gq0OneVgLYET+oNHcxgWItq4TbhOzRLKNAFUb9edAftiMKXvXfCB0vbGrJdZDNq0dWMsxg==", - "dev": true, - "requires": { - "archiver-utils": "^2.1.0", - "async": "^2.6.3", - "buffer-crc32": "^0.2.1", - "glob": "^7.1.4", - "readable-stream": "^3.4.0", - "tar-stream": "^2.1.0", - "zip-stream": "^2.1.2" - } - }, "array-union": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", @@ -23394,35 +23070,6 @@ "array-uniq": "^1.0.1" } }, - "compress-commons": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-2.1.1.tgz", - "integrity": "sha512-eVw6n7CnEMFzc3duyFVrQEuY1BlHR3rYsSztyG32ibGMW722i3C6IizEGMFmfMU+A+fALvBIwxN3czffTcdA+Q==", - "dev": true, - "requires": { - "buffer-crc32": "^0.2.13", - "crc32-stream": "^3.0.1", - "normalize-path": "^3.0.0", - "readable-stream": "^2.3.6" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - } - } - }, "dir-glob": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", @@ -23463,9 +23110,9 @@ } }, "make-dir": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.2.tgz", - "integrity": "sha512-rYKABKutXa6vXTXhoV18cBE7PaewPXHe/Bdq4v+ZLMhxbWApkFFplT0LcbMW+6BbjnQXzZ/sAvSE/JdguApG5w==", + "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, "requires": { "semver": "^6.0.0" @@ -23503,33 +23150,11 @@ } } }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true - }, - "zip-stream": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-2.1.3.tgz", - "integrity": "sha512-EkXc2JGcKhO5N5aZ7TmuNo45budRaFGHOmz24wtJR7znbNqDPmdZtUauKX6et8KAVseAMBOyWJqEpXcHTBsh7Q==", - "dev": true, - "requires": { - "archiver-utils": "^2.1.0", - "compress-commons": "^2.1.1", - "readable-stream": "^3.4.0" - } } } }, @@ -23543,6 +23168,15 @@ "traverse": "^0.6.6" } }, + "serverless-log-forwarding": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/serverless-log-forwarding/-/serverless-log-forwarding-1.4.0.tgz", + "integrity": "sha512-+LBfP1JmDM+MIWVlFJ6JMU6c/TIL7Ukh75aWe32/a7k65032DrjCb/ZVkN+C7ncEP2o8d3FVf1iSerywaU/jeQ==", + "dev": true, + "requires": { + "underscore": "^1.8.3" + } + }, "serverless-offline": { "version": "5.12.1", "resolved": "https://registry.npmjs.org/serverless-offline/-/serverless-offline-5.12.1.tgz", @@ -24189,9 +23823,9 @@ } }, "source-map-support": { - "version": "0.5.17", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.17.tgz", - "integrity": "sha512-bwdKOBZ5L0gFRh4KOxNap/J/MpvX9Yxsq9lFDx65s3o7F/NiHy7JRaGIS8MwW6tZPAq9UXE207Il0cfcb5yu/Q==", + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", "dev": true, "requires": { "buffer-from": "^1.0.0", @@ -24223,9 +23857,9 @@ } }, "spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", "dev": true }, "spdx-expression-parse": { @@ -24669,6 +24303,17 @@ "es-abstract": "^1.17.0-next.1" } }, + "string.prototype.trim": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.1.tgz", + "integrity": "sha512-MjGFEeqixw47dAMFMtgUro/I0+wNqZB5GKXGt1fFr24u3TzDXCPu7J9Buppzoe3r/LqkSDLDDJzE15RGWDGAVw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1" + } + }, "string.prototype.trimend": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", @@ -24721,9 +24366,9 @@ } }, "stringify-entities": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-3.0.0.tgz", - "integrity": "sha512-h7NJJIssprqlyjHT2eQt2W1F+MCcNmwPGlKb0bWEdET/3N44QN3QbUF/ueKCgAssyKRZ3Br9rQ7FcXjHr0qLHw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-3.0.1.tgz", + "integrity": "sha512-Lsk3ISA2++eJYqBMPKcr/8eby1I6L0gP0NlxF8Zja6c05yr/yCYyb2c9PwXjd08Ib3If1vn1rbs1H5ZtVuOfvQ==", "dev": true, "requires": { "character-entities-html4": "^1.0.0", @@ -24843,9 +24488,9 @@ } }, "stylelint": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-13.3.2.tgz", - "integrity": "sha512-kpO3/Gz2ZY40EWUwFYYkgpzhf8ZDUyKpcui5+pS0XKJBj/EMYmZpOJoL8IFAz2yApYeg91NVy5yAjE39hDzWvQ==", + "version": "13.3.3", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-13.3.3.tgz", + "integrity": "sha512-j8Oio2T1YNiJc6iXDaPYd74Jg4zOa1bByNm/g9/Nvnq4tDPsIjMi46jhRZyPPktGPwjJ5FwcmCqIRlH6PVP8mA==", "dev": true, "requires": { "@stylelint/postcss-css-in-js": "^0.37.1", @@ -25078,22 +24723,22 @@ "dev": true }, "meow": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-6.1.0.tgz", - "integrity": "sha512-iIAoeI01v6pmSfObAAWFoITAA4GgiT45m4SmJgoxtZfvI0fyZwhV4d0lTwiUXvAKIPlma05Feb2Xngl52Mj5Cg==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-6.1.1.tgz", + "integrity": "sha512-3YffViIt2QWgTy6Pale5QpopX/IvU3LPL03jOTqp6pGj3VjesdO/U8CuHMKpnQr4shCNCM5fd5XFFvIIl6JBHg==", "dev": true, "requires": { "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.1.1", + "camelcase-keys": "^6.2.2", "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.0.0", - "minimist-options": "^4.0.1", + "hard-rejection": "^2.1.0", + "minimist-options": "^4.0.2", "normalize-package-data": "^2.5.0", - "read-pkg-up": "^7.0.0", + "read-pkg-up": "^7.0.1", "redent": "^3.0.0", "trim-newlines": "^3.0.0", - "type-fest": "^0.8.1", - "yargs-parser": "^18.1.1" + "type-fest": "^0.13.1", + "yargs-parser": "^18.1.3" } }, "micromatch": { @@ -25189,6 +24834,14 @@ "find-up": "^4.1.0", "read-pkg": "^5.2.0", "type-fest": "^0.8.1" + }, + "dependencies": { + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + } } }, "redent": { @@ -25259,6 +24912,12 @@ "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.0.tgz", "integrity": "sha512-C4+gOpvmxaSMKuEf9Qc134F1ZuOHVXKRbtEflf4NTtuuJDEIJ9p5PXsalL8SkeRw+qit1Mo+yuvMPAKwWg/1hA==", "dev": true + }, + "type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "dev": true } } }, @@ -25665,9 +25324,9 @@ } }, "es6-promisify": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-6.1.0.tgz", - "integrity": "sha512-jCsk2fpfEFusVv1MDkF4Uf0hAzIKNDMgR6LyOIw6a3jwkN1sCgWzuwgnsHY9YSQ8n8P31HoncvE0LC44cpWTrw==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-6.1.1.tgz", + "integrity": "sha512-HBL8I3mIki5C1Cc9QjKUenHtnG0A5/xA8Q/AllRcfiwl2CZFXGK7ddBiCoRwAix4i2KxcQfjtIVcrVbB3vbmwg==", "dev": true }, "figures": { @@ -25981,9 +25640,9 @@ "dev": true }, "terser": { - "version": "4.6.11", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.6.11.tgz", - "integrity": "sha512-76Ynm7OXUG5xhOpblhytE7X58oeNSmC8xnNhjWVo8CksHit0U0kO4hfNbPrrYwowLWFgM2n9L176VNx2QaHmtA==", + "version": "4.6.13", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.6.13.tgz", + "integrity": "sha512-wMvqukYgVpQlymbnNbabVZbtM6PN63AzqexpwJL8tbh/mRT9LE5o+ruVduAGL7D6Fpjl+Q+06U5I9Ul82odAhw==", "dev": true, "requires": { "commander": "^2.20.0", @@ -26082,12 +25741,23 @@ "dev": true }, "tmp": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.1.0.tgz", - "integrity": "sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw==", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", "dev": true, "requires": { - "rimraf": "^2.6.3" + "rimraf": "^3.0.0" + }, + "dependencies": { + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } } }, "tmpl": { @@ -26210,9 +25880,9 @@ } }, "trace-deps": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/trace-deps/-/trace-deps-0.3.0.tgz", - "integrity": "sha512-XZuFVyiBTynufC5TRfD5JBDJR4r3fwekMyJtoCT/xG/uwkhoQ6S2cG1ZDxfsyjjy96gc5F1p+8QFb0SvDW/fwg==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/trace-deps/-/trace-deps-0.3.3.tgz", + "integrity": "sha512-aNpC9Bd8UYuaVlo5sXSJboveHUVmeWk9/0ak/usg/eOUSt1Mj0xjLQFJ7QStBqezf0PHQi48mNTua64PS6ve7w==", "dev": true, "requires": { "acorn-node": "^2.0.0", @@ -26295,9 +25965,9 @@ "dev": true }, "tslib": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz", - "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==", + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.2.tgz", + "integrity": "sha512-tTSkux6IGPnUGUd1XAZHcpu85MOkIl5zX49pO+jfsie3eP0B6pyhOlLXm3cAC6T7s+euSDDUUV+Acop5WmtkVg==", "dev": true }, "tsscmp": { @@ -26394,12 +26064,6 @@ "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==", "dev": true }, - "ua-parser-js": { - "version": "0.7.21", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.21.tgz", - "integrity": "sha512-+O8/qh/Qj8CgC6eYBVBykMrNtp5Gebn4dlGD/kKXVkJNDwyrAwSIqwz8CDf+tsAIWVycKcku6gIXJ0qwx/ZXaQ==", - "dev": true - }, "uc.micro": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", @@ -26486,9 +26150,9 @@ } }, "unbzip2-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.1.tgz", - "integrity": "sha512-sgDYfSDPMsA4Hr2/w7vOlrJBlwzmyakk1+hW8ObLvxSp0LA36LcL2XItGvOT3OSblohSdevMuT8FQjLsqyy4sA==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.2.tgz", + "integrity": "sha512-pZMVAofMrrHX6Ik39hCk470kulCbmZ2SWfQLPmTWqfJV/oUm0gn1CblvHdUu4+54Je6Jq34x8kY6XjTy6dMkOg==", "dev": true, "requires": { "buffer": "^5.2.1", @@ -26579,6 +26243,12 @@ "xml-name-validator": "^3.0.0" } }, + "parse5": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", + "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==", + "dev": true + }, "ws": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", @@ -27081,9 +26751,9 @@ "dev": true }, "uuid": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", - "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz", + "integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==", "dev": true }, "v8-compile-cache": { @@ -27093,9 +26763,9 @@ "dev": true }, "v8-to-istanbul": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-4.1.3.tgz", - "integrity": "sha512-sAjOC+Kki6aJVbUOXJbcR0MnbfjvBzwKZazEJymA2IX49uoOdEdk+4fBq5cXgYgiyKtAyrrJNtBZdOeDIF+Fng==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-4.1.4.tgz", + "integrity": "sha512-Rw6vJHj1mbdK8edjR7+zuJrpDtKIgNdAvTSAcpYfgMIw+u2dPDntD3dgN4XQFLU2/fvFQdzj+EeSGfd/jnY5fQ==", "dev": true, "requires": { "@types/istanbul-lib-coverage": "^2.0.1", @@ -27122,9 +26792,9 @@ } }, "validator": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-11.1.0.tgz", - "integrity": "sha512-qiQ5ktdO7CD6C/5/mYV4jku/7qnqzjrxb3C/Q5wR3vGGinHTgJZN/TdFT3ZX4vXhX2R1PXx42fB1cn5W+uJ4lg==", + "version": "12.2.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-12.2.0.tgz", + "integrity": "sha512-jJfE/DW6tIK1Ek8nCfNFqt8Wb3nzMoAbocBF6/Icgg1ZFSBpObdnwVY2jQj6qUqzhx5jc71fpvBWyLGO7Xl+nQ==", "dev": true }, "vary": { @@ -27174,6 +26844,12 @@ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", "dev": true + }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true } } }, @@ -27273,16 +26949,16 @@ "dev": true }, "webpack": { - "version": "4.42.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.42.1.tgz", - "integrity": "sha512-SGfYMigqEfdGchGhFFJ9KyRpQKnipvEvjc1TwrXEPCM6H5Wywu10ka8o3KGrMzSMxMQKt8aCHUFh5DaQ9UmyRg==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.43.0.tgz", + "integrity": "sha512-GW1LjnPipFW2Y78OOab8NJlCflB7EFskMih2AHdvjbpKMeDJqEgSx24cXXXiPS65+WSwVyxtDsJH6jGX2czy+g==", "dev": true, "requires": { "@webassemblyjs/ast": "1.9.0", "@webassemblyjs/helper-module-context": "1.9.0", "@webassemblyjs/wasm-edit": "1.9.0", "@webassemblyjs/wasm-parser": "1.9.0", - "acorn": "^6.2.1", + "acorn": "^6.4.1", "ajv": "^6.10.2", "ajv-keywords": "^3.4.1", "chrome-trace-event": "^1.0.2", @@ -27299,7 +26975,7 @@ "schema-utils": "^1.0.0", "tapable": "^1.1.3", "terser-webpack-plugin": "^1.4.3", - "watchpack": "^1.6.0", + "watchpack": "^1.6.1", "webpack-sources": "^1.4.1" }, "dependencies": { @@ -27858,15 +27534,15 @@ "dev": true }, "z-schema": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-4.2.2.tgz", - "integrity": "sha512-7bGR7LohxSdlK1EOdvA/OHksvKGE4jTLSjd8dBj9YKT0S43N9pdMZ0Z7GZt9mHrBFhbNTRh3Ky6Eu2MHsPJe8g==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-4.2.3.tgz", + "integrity": "sha512-zkvK/9TC6p38IwcrbnT3ul9in1UX4cm1y/VZSs4GHKIiDCrlafc+YQBgQBUdDXLAoZHf2qvQ7gJJOo6yT1LH6A==", "dev": true, "requires": { "commander": "^2.7.1", "lodash.get": "^4.4.2", "lodash.isequal": "^4.5.0", - "validator": "^11.0.0" + "validator": "^12.0.0" }, "dependencies": { "commander": { @@ -27879,14 +27555,14 @@ } }, "zip-stream": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-3.0.1.tgz", - "integrity": "sha512-r+JdDipt93ttDjsOVPU5zaq5bAyY+3H19bDrThkvuVxC0xMQzU1PJcS6D+KrP3u96gH9XLomcHPb+2skoDjulQ==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-2.1.3.tgz", + "integrity": "sha512-EkXc2JGcKhO5N5aZ7TmuNo45budRaFGHOmz24wtJR7znbNqDPmdZtUauKX6et8KAVseAMBOyWJqEpXcHTBsh7Q==", "dev": true, "requires": { "archiver-utils": "^2.1.0", - "compress-commons": "^3.0.0", - "readable-stream": "^3.6.0" + "compress-commons": "^2.1.1", + "readable-stream": "^3.4.0" }, "dependencies": { "readable-stream": { diff --git a/package.json b/package.json index 606cc4ed130..cc324f7a105 100644 --- a/package.json +++ b/package.json @@ -6,8 +6,8 @@ "repository": "https://github.com/ustaxcourt/ef-cms", "devDependencies": { "@babel/cli": "^7.8.4", - "@babel/core": "^7.9.0", - "@babel/preset-env": "^7.9.5", + "@babel/core": "^7.9.6", + "@babel/preset-env": "^7.9.6", "@babel/preset-react": "^7.9.4", "@babel/register": "^7.9.0", "@cerebral/react": "4.2.1-1584683380023", @@ -16,26 +16,29 @@ "@fortawesome/free-solid-svg-icons": "^5.13.0", "@fortawesome/react-fontawesome": "^0.1.9", "@hapi/joi": "^17.1.0", - "archiver": "^4.0.1", + "@hapi/joi-date": "^2.0.1", + "archiver": "3.1.1", "autoprefixer": "^9.7.5", - "aws-sdk": "^2.657.0", + "aws-sdk": "^2.666.0", "aws-sdk-mock": "^5.0.0", "aws-xray-sdk": "^2.5.0", "axios": "^0.19.2", "babel-eslint": "^10.0.3", - "babel-jest": "^25.2.4", + "babel-jest": "^25.5.1", "babel-plugin-cerebral": "^1.0.1", "babel-plugin-transform-html-import-require-to-string": "^0.0.3", "cerebral": "5.2.1-1584683380023", "chrome-aws-lambda": "^2.1.1", "classnames": "^2.2.6", "core-js": "^3.6.5", - "csv-parse": "^4.8.8", - "cypress": "^4.4.0", + "csv-parse": "^4.9.0", + "cypress": "^4.5.0", "deep-freeze": "0.0.1", "diff-arrays-of-objects": "^1.1.5", "dynamodb-admin": "^4.0.0", "elasticsearch": "^16.6.0", + "enzyme": "^3.11.0", + "enzyme-adapter-react-16": "^1.15.2", "eslint": "^6.8.0", "eslint-config-prettier": "^6.10.1", "eslint-plugin-cypress": "^2.10.1", @@ -64,23 +67,25 @@ "imagemin-pngquant": "^8.0.0", "is-reachable": "^4.0.0", "isomorphic-fetch": "^2.2.1", - "jest": "^25.2.4", + "jest": "^25.5.2", + "js-yaml": "^3.13.1", "jsdoc": "^3.6.4", "jsdom": "^16.2.2", "json2md": "^1.7.0", "jsonwebtoken": "^8.5.1", + "jwk-to-pem": "^2.0.3", "lodash": "^4.17.15", "madge": "^3.7.0", - "moment": "^2.24.0", + "moment": "2.24.0", "moment-timezone": "^0.5.27", - "node-sass": "^4.13.1", + "node-sass": "^4.14.0", "npm-force-resolutions": "0.0.3", "npm-run-all": "^4.1.5", "pa11y-ci": "^2.3.0", "parcel-bundler": "^1.12.4", "parcel-plugin-bundle-visualiser": "^1.2.0", "parcel-plugin-static-files-copy": "^2.3.1", - "pdf-lib": "^1.4.0", + "pdf-lib": "^1.5.0", "pdfjs-dist": "^2.3.200", "pixelmatch": "^5.2.0", "pngjs": "^5.0.0", @@ -96,20 +101,22 @@ "react-calendar": "^3.0.1", "react-dom": "^16.13.1", "react-idle-timer": "^4.2.12", - "react-quill": "^1.3.5", + "react-quill": "^2.0.0-beta.2", "react-responsive": "^8.0.2", "react-select": "^3.1.0", "react-test-renderer": "^16.13.1", + "readline": "^1.3.0", "riot-route": "^3.1.4", "s3-files": "^2.0.1", "s3-zip": "^3.1.3", "s3rver": "^3.5.0", "sanitize-filename": "^1.6.3", - "sass": "^1.26.3", + "sass": "^1.26.5", "serverless": "1.61.1", "serverless-domain-manager": "github:codyseibert/serverless-domain-manager", - "serverless-jetpack": "^0.10.2", + "serverless-jetpack": "^0.10.4", "serverless-latest-layer-version": "^2.1.0", + "serverless-log-forwarding": "^1.4.0", "serverless-offline": "^5.12.1", "serverless-offline-dynamodb-streams": "^3.0.2", "serverless-plugin-aws-alerts": "^1.3.1", @@ -119,14 +126,14 @@ "serverless-plugin-tracing": "^2.0.0", "serverless-plugin-warmup": "^4.9.0", "serverless-prune-plugin": "^1.4.2", - "stylelint": "^13.3.2", + "stylelint": "^13.3.3", "stylelint-config-idiomatic-order": "^8.1.0", "stylelint-config-standard": "^20.0.0", "swagger-cli": "^4.0.2", - "tmp": "^0.1.0", + "tmp": "^0.2.1", "umzug": "^2.3.0", "uswds": "^2.6.0", - "uuid": "^7.0.2", + "uuid": "^8.0.0", "webpack": "^4.42.1", "websocket": "^1.0.31", "wicg-inert": "^3.0.2" @@ -183,6 +190,7 @@ "seed:db": "node ./web-api/create-dynamo-tables.js && node ./web-api/seed-dynamo.js", "seed:elasticsearch": "./web-api/seed-elasticsearch.sh", "seed:s3": "cp -R ./web-api/storage/fixtures/s3/* ./web-api/storage/s3", + "seed:s3:lint": "pushd ./web-api/storage/fixtures && grep documentId seed/*json | ./validate-seed.js && popd", "seed": "run-p seed:db seed:s3", "start:api:ci": "CI=true npm run start:api", "start:api:resume": "RESUME=true npm run start:api", @@ -195,9 +203,9 @@ "start:public:ci": "npm run clean:public && CI=true USTC_ENV=dev parcel --port 5678 -d dist-public --no-cache --no-source-maps web-client/src/index-public.pug", "start:public": "npm run clean:public && USTC_ENV=dev parcel --port 5678 -d dist-public --no-cache --no-source-maps web-client/src/index-public.pug", "start:s3rver": "s3rver -d web-api/storage/s3 -a 0.0.0.0 -p 9000 --configure-bucket $DOCUMENTS_BUCKET_NAME web-api/cors-policy.xml --configure-bucket $TEMP_DOCUMENTS_BUCKET_NAME web-api/cors-policy.xml", - "test:_client:parallel": "NO_SCANNER=true SKIP_VIRUS_SCAN=true AWS_ACCESS_KEY_ID=noop AWS_SECRET_ACCESS_KEY=noop FILE_UPLOAD_MODAL_TIMEOUT=1 jest --maxWorkers=95% --config web-client/jest-unit.config.js", + "test:_client:parallel": "NO_SCANNER=true SKIP_VIRUS_SCAN=true AWS_ACCESS_KEY_ID=noop AWS_SECRET_ACCESS_KEY=noop FILE_UPLOAD_MODAL_TIMEOUT=1 jest --maxWorkers=50% --config web-client/jest-unit.config.js", "test:_client": "NO_SCANNER=true SKIP_VIRUS_SCAN=true AWS_ACCESS_KEY_ID=noop AWS_SECRET_ACCESS_KEY=noop FILE_UPLOAD_MODAL_TIMEOUT=1 jest --runInBand --config web-client/jest.config.js", - "test:api": "npm run build:assets && jest --maxWorkers=4 --config web-api/jest.config.js \"web-api/.*\\.test\\.js\"", + "test:api": "npm run build:assets && jest --maxWorkers=50% --config web-api/jest.config.js \"web-api/.*\\.test\\.js\"", "test:client:_integration": "npm run test:_client -- ", "test:client:integration": "npm run test:client:_integration \"web-client/integration-tests/.*\\.test\\.js\"", "test:client:unit": "npm run test:_client:parallel -- \"web-client/src/.*\\.test\\.js\"", @@ -212,8 +220,9 @@ "test:pa11y:smoketests": ". ./set-tokens.sh && pa11y-ci --config web-client/pa11y-ci-smoketests.config.js", "test:pa11y": "npm run test:pa11y:1 && npm run test:pa11y:2 && npm run test:pa11y:3", "test:pdf": "npm run build:assets && node ./shared/pdf-tests/pdfReportTester.js", + "test:pdf-output": "npm run build:assets && PDF_OUTPUT=true jest shared/src/business/utilities/documentGenerators.test.js", "test:public:integration": "npm run test:_client -- \"web-client/integration-tests-public/.*\\.test\\.js\"", - "test:shared": "npm run build:assets && jest --maxWorkers=90% --config shared/jest.config.js \"shared/.*\\.test\\.js\"", + "test:shared": "npm run build:assets && jest --maxWorkers=50% --config shared/jest.config.js \"shared/.*\\.test\\.js\"", "test:watch": "jest --watch .*test\\.js$", "test": "echo 'Best run with start:api:ci and start:client:ci' && sleep 3 && CI=true npx run-s test:shared test:api test:client test:pa11y cypress lint", "watch": "nodemon -e yml --exec sls offline start" diff --git a/run-local.sh b/run-local.sh index 89f7e41df85..0e288aa24e2 100755 --- a/run-local.sh +++ b/run-local.sh @@ -1,19 +1,22 @@ #!/bin/bash -echo "killing dynamo if already running" -pkill -f DynamoDBLocal -echo "starting dynamo" -./web-api/start-dynamo.sh & -DYNAMO_PID=$! -./wait-until.sh http://localhost:8000/shell +# if [ ! -e "$CIRCLECI" ]; then + echo "killing dynamo if already running" + pkill -f DynamoDBLocal -echo "killing elasticsearch if already running" -pkill -f elasticsearch + echo "starting dynamo" + ./web-api/start-dynamo.sh & + DYNAMO_PID=$! + ./wait-until.sh http://localhost:8000/shell -echo "starting elasticsearch" -./web-api/start-elasticsearch.sh & -ESEARCH_PID=$! -./wait-until.sh http://localhost:9200/ 200 + echo "killing elasticsearch if already running" + pkill -f elasticsearch + + echo "starting elasticsearch" + ./web-api/start-elasticsearch.sh & + ESEARCH_PID=$! + ./wait-until.sh http://localhost:9200/ 200 +# fi npm run build:assets diff --git a/shared/src/business/entities/Batch.js b/shared/src/business/entities/Batch.js index 096255ebf75..d6bc18c4740 100644 --- a/shared/src/business/entities/Batch.js +++ b/shared/src/business/entities/Batch.js @@ -3,6 +3,8 @@ const { joiValidationDecorator, } = require('../../utilities/JoiValidationDecorator'); const { createISODateString } = require('../utilities/DateHandler'); +const { getTimestampSchema } = require('../../utilities/dateSchema'); +const joiStrictTimestamp = getTimestampSchema(); /** * constructor @@ -56,15 +58,10 @@ Batch.schema = joi.object().keys({ }) .required(), batchIndex: joi.number().integer().min(0).required(), - createdAt: joi.date().iso().required(), + createdAt: joiStrictTimestamp.required(), pages: joi.array().min(1).required(), }); -joiValidationDecorator( - Batch, - Batch.schema, - undefined, - Batch.VALIDATION_ERROR_MESSAGES, -); +joiValidationDecorator(Batch, Batch.schema, Batch.VALIDATION_ERROR_MESSAGES); module.exports = { Batch }; diff --git a/shared/src/business/entities/CaseAssociationRequestFactory.js b/shared/src/business/entities/CaseAssociationRequestFactory.js index 38b2ff0fbd3..ab6243b22cc 100644 --- a/shared/src/business/entities/CaseAssociationRequestFactory.js +++ b/shared/src/business/entities/CaseAssociationRequestFactory.js @@ -5,7 +5,9 @@ const { const { SupportingDocumentInformationFactory, } = require('./externalDocument/SupportingDocumentInformationFactory'); +const { getTimestampSchema } = require('../../utilities/dateSchema'); const { replaceBracketed } = require('../utilities/replaceBracketed'); +const joiStrictTimestamp = getTimestampSchema(); const { VALIDATION_ERROR_MESSAGES, @@ -129,7 +131,7 @@ function CaseAssociationRequestFactory(rawProps) { let schemaOptionalItems = { attachments: joi.boolean().required(), - certificateOfServiceDate: joi.date().iso().max('now').required(), + certificateOfServiceDate: joiStrictTimestamp.max('now').required(), exhibits: joi.boolean().required(), hasSupportingDocuments: joi.boolean().required(), objections: joi.string().required(), @@ -138,8 +140,6 @@ function CaseAssociationRequestFactory(rawProps) { supportingDocuments: joi.array().optional(), }; - let customValidate; - const makeRequired = itemName => { schema[itemName] = schemaOptionalItems[itemName]; }; @@ -175,7 +175,6 @@ function CaseAssociationRequestFactory(rawProps) { joiValidationDecorator( entityConstructor, schema, - customValidate, CaseAssociationRequestFactory.VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/CaseAssociationRequestFactory.test.js b/shared/src/business/entities/CaseAssociationRequestFactory.test.js index 87f00013a4f..b9d55997e36 100644 --- a/shared/src/business/entities/CaseAssociationRequestFactory.test.js +++ b/shared/src/business/entities/CaseAssociationRequestFactory.test.js @@ -1,4 +1,7 @@ -const moment = require('moment'); +const { + calculateISODate, + createISODateString, +} = require('../utilities/DateHandler'); const { CaseAssociationRequestFactory, } = require('./CaseAssociationRequestFactory'); @@ -70,12 +73,16 @@ describe('CaseAssociationRequestFactory', () => { expect(errors().certificateOfServiceDate).toEqual( VALIDATION_ERROR_MESSAGES.certificateOfServiceDate[1], ); - rawEntity.certificateOfServiceDate = moment().format(); + rawEntity.certificateOfServiceDate = createISODateString(); expect(errors().certificateOfServiceDate).toEqual(undefined); }); it('should not allow certificate of service date to be in the future', () => { - rawEntity.certificateOfServiceDate = moment().add(1, 'days').format(); + rawEntity.certificateOfServiceDate = calculateISODate({ + dateString: createISODateString(), + howMuch: 1, + unit: 'days', + }); expect(errors().certificateOfServiceDate).toEqual( VALIDATION_ERROR_MESSAGES.certificateOfServiceDate[0].message, ); @@ -158,7 +165,7 @@ describe('CaseAssociationRequestFactory', () => { expect( errors().supportingDocuments[0].certificateOfServiceDate, ).toEqual(VALIDATION_ERROR_MESSAGES.certificateOfServiceDate[1]); - rawEntity.supportingDocuments[0].certificateOfServiceDate = moment().format(); + rawEntity.supportingDocuments[0].certificateOfServiceDate = createISODateString(); expect(errors().supportingDocuments).toEqual(undefined); }); }); diff --git a/shared/src/business/entities/CaseDeadline.js b/shared/src/business/entities/CaseDeadline.js index 2dc5af7a50d..95937c5295a 100644 --- a/shared/src/business/entities/CaseDeadline.js +++ b/shared/src/business/entities/CaseDeadline.js @@ -3,6 +3,8 @@ const { joiValidationDecorator, } = require('../../utilities/JoiValidationDecorator'); const { createISODateString } = require('../utilities/DateHandler'); +const { getTimestampSchema } = require('../../utilities/dateSchema'); +const joiStrictTimestamp = getTimestampSchema(); /** * Case Deadline entity @@ -14,6 +16,8 @@ function CaseDeadline(rawProps, { applicationContext }) { if (!applicationContext) { throw new TypeError('applicationContext must be defined'); } + this.entityName = 'CaseDeadline'; + this.caseDeadlineId = rawProps.caseDeadlineId || applicationContext.getUniqueId(); this.caseId = rawProps.caseId; @@ -51,14 +55,10 @@ CaseDeadline.schema = joi.object().keys({ }) .required() .description('Unique Case ID only used by the system.'), - createdAt: joi - .date() - .iso() + createdAt: joiStrictTimestamp .required() .description('When the Case Deadline was added to the system.'), - deadlineDate: joi - .date() - .iso() + deadlineDate: joiStrictTimestamp .required() .description('When the Case Deadline expires.'), description: joi @@ -67,12 +67,12 @@ CaseDeadline.schema = joi.object().keys({ .min(1) .required() .description('User provided description of the Case Deadline.'), + entityName: joi.string().valid('CaseDeadline').required(), }); joiValidationDecorator( CaseDeadline, CaseDeadline.schema, - undefined, CaseDeadline.VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/DocketRecord.js b/shared/src/business/entities/DocketRecord.js index 14cd430ac55..a20d45bac61 100644 --- a/shared/src/business/entities/DocketRecord.js +++ b/shared/src/business/entities/DocketRecord.js @@ -3,7 +3,9 @@ const { joiValidationDecorator, } = require('../../utilities/JoiValidationDecorator'); const { getAllEventCodes } = require('../../utilities/getAllEventCodes'); +const { getTimestampSchema } = require('../../utilities/dateSchema'); +const joiStrictTimestamp = getTimestampSchema(); /** * DocketRecord constructor * @@ -14,6 +16,7 @@ function DocketRecord(rawDocketRecord, { applicationContext }) { if (!applicationContext) { throw new TypeError('applicationContext must be defined'); } + this.entityName = 'DocketRecord'; this.docketRecordId = rawDocketRecord.docketRecordId || applicationContext.getUniqueId(); @@ -65,6 +68,7 @@ joiValidationDecorator( .optional() .meta({ tags: ['Restricted'] }) .description('JSON representation of the in-progress edit of this item.'), + entityName: joi.string().valid('DocketRecord').required(), eventCode: joi .string() .valid(...getAllEventCodes()) @@ -78,10 +82,8 @@ joiValidationDecorator( .allow(null) .meta({ tags: ['Restricted'] }) .description('ID of the user that filed this Docket Record item.'), - filingDate: joi - .date() + filingDate: joiStrictTimestamp .max('now') - .iso() .required() .description('Date that this Docket Record item was filed.'), index: joi @@ -95,7 +97,6 @@ joiValidationDecorator( .optional() .description('Served parties code to override system-computed code.'), }), - undefined, DocketRecord.VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/Document.js b/shared/src/business/entities/Document.js index fcbc18759d5..bc00dd20c7c 100644 --- a/shared/src/business/entities/Document.js +++ b/shared/src/business/entities/Document.js @@ -2,19 +2,17 @@ const courtIssuedEventCodes = require('../../tools/courtIssuedEventCodes.json'); const documentMapExternal = require('../../tools/externalFilingEvents.json'); const documentMapInternal = require('../../tools/internalFilingEvents.json'); const joi = require('@hapi/joi'); -const { - DOCKET_NUMBER_MATCHER, - TRIAL_LOCATION_MATCHER, -} = require('./cases/CaseConstants'); const { joiValidationDecorator, } = require('../../utilities/JoiValidationDecorator'); const { createISODateString } = require('../utilities/DateHandler'); +const { DOCKET_NUMBER_MATCHER } = require('./cases/CaseConstants'); const { flatten } = require('lodash'); +const { getTimestampSchema } = require('../../utilities/dateSchema'); const { Order } = require('./orders/Order'); -const { TrialSession } = require('./trialSessions/TrialSession'); const { User } = require('./User'); const { WorkItem } = require('./WorkItem'); +const joiStrictTimestamp = getTimestampSchema(); Document.CATEGORIES = Object.keys(documentMapExternal); Document.CATEGORY_MAP = documentMapExternal; @@ -23,11 +21,76 @@ Document.COURT_ISSUED_EVENT_CODES = courtIssuedEventCodes; Document.INTERNAL_CATEGORIES = Object.keys(documentMapInternal); Document.INTERNAL_CATEGORY_MAP = documentMapInternal; Document.PETITION_DOCUMENT_TYPES = ['Petition']; -Document.ORDER_DOCUMENT_TYPES = Document.COURT_ISSUED_EVENT_CODES.filter( - document => document.documentType.includes('Order'), -); +Document.ORDER_DOCUMENT_TYPES = [ + 'O', + 'OAJ', + 'OAL', + 'OAP', + 'OAPF', + 'OAR', + 'OAS', + 'OASL', + 'OAW', + 'OAX', + 'OCA', + 'OD', + 'ODD', + 'ODL', + 'ODP', + 'ODR', + 'ODS', + 'ODSL', + 'ODW', + 'ODX', + 'OF', + 'OFAB', + 'OFFX', + 'OFWD', + 'OFX', + 'OIP', + 'OJR', + 'OODS', + 'OPFX', + 'OPX', + 'ORAP', + 'OROP', + 'OSC', + 'OSCP', + 'OST', + 'OSUB', + 'OAD', + 'ODJ', +]; Document.validationName = 'Document'; +Document.SCENARIOS = [ + 'Standard', + 'Nonstandard A', + 'Nonstandard B', + 'Nonstandard C', + 'Nonstandard D', + 'Nonstandard E', + 'Nonstandard F', + 'Nonstandard G', + 'Nonstandard H', + 'Type A', + 'Type B', + 'Type C', + 'Type D', + 'Type E', + 'Type F', + 'Type G', + 'Type H', +]; + +Document.RELATIONSHIPS = [ + 'primaryDocument', + 'primarySupportingDocument', + 'secondaryDocument', + 'secondarySupportingDocument', + 'supportingDocument', +]; + /** * constructor * @@ -39,6 +102,8 @@ function Document(rawDocument, { applicationContext, filtered = false }) { throw new TypeError('applicationContext must be defined'); } + this.entityName = 'Document'; + if ( !filtered || User.isInternalUser(applicationContext.getCurrentUser().role) @@ -50,13 +115,13 @@ function Document(rawDocument, { applicationContext, filtered = false }) { ? Document.isPendingOnCreation(rawDocument) : rawDocument.pending; this.previousDocument = rawDocument.previousDocument; - this.processingStatus = rawDocument.processingStatus || 'pending'; // TODO: restricted + this.processingStatus = rawDocument.processingStatus || 'pending'; this.qcAt = rawDocument.qcAt; - this.qcByUser = rawDocument.qcByUser; this.qcByUserId = rawDocument.qcByUserId; this.signedAt = rawDocument.signedAt; this.signedByUserId = rawDocument.signedByUserId; this.signedJudgeName = rawDocument.signedJudgeName; + this.userId = rawDocument.userId; this.workItems = (rawDocument.workItems || []).map( workItem => new WorkItem(workItem, { applicationContext }), ); @@ -65,15 +130,17 @@ function Document(rawDocument, { applicationContext, filtered = false }) { this.additionalInfo = rawDocument.additionalInfo; this.additionalInfo2 = rawDocument.additionalInfo2; this.addToCoversheet = rawDocument.addToCoversheet; - this.archived = rawDocument.archived; // TODO: look into this + this.archived = rawDocument.archived; this.attachments = rawDocument.attachments; - this.documentContents = rawDocument.documentContents; this.caseId = rawDocument.caseId; this.certificateOfService = rawDocument.certificateOfService; this.certificateOfServiceDate = rawDocument.certificateOfServiceDate; this.createdAt = rawDocument.createdAt || createISODateString(); + this.date = rawDocument.date; this.docketNumber = rawDocument.docketNumber; + this.docketNumbers = rawDocument.docketNumbers; this.documentId = rawDocument.documentId; + this.documentContentsId = rawDocument.documentContentsId; this.documentTitle = rawDocument.documentTitle; this.documentType = rawDocument.documentType; this.eventCode = rawDocument.eventCode; @@ -88,23 +155,35 @@ function Document(rawDocument, { applicationContext, filtered = false }) { this.mailingDate = rawDocument.mailingDate; this.objections = rawDocument.objections; this.ordinalValue = rawDocument.ordinalValue; - this.partyPrimary = rawDocument.partyPrimary; // TODO: add info about purpose + this.partyPrimary = rawDocument.partyPrimary; this.partyIrsPractitioner = rawDocument.partyIrsPractitioner; - this.partySecondary = rawDocument.partySecondary; // TODO: add info about purpose - this.privatePractitioners = rawDocument.privatePractitioners; // TODO: look into this + this.partySecondary = rawDocument.partySecondary; this.receivedAt = rawDocument.receivedAt || createISODateString(); - this.relationship = rawDocument.relationship; // TODO: look into this - this.scenario = rawDocument.scenario; // TODO: look into this - this.secondaryDate = rawDocument.secondaryDate; // TODO: look into this - this.secondaryDocument = rawDocument.secondaryDocument; // TODO: look into this + this.relationship = rawDocument.relationship; + this.scenario = rawDocument.scenario; + this.secondaryDate = rawDocument.secondaryDate; this.servedAt = rawDocument.servedAt; + this.numberOfPages = rawDocument.numberOfPages; this.servedParties = rawDocument.servedParties; this.serviceDate = rawDocument.serviceDate; this.serviceStamp = rawDocument.serviceStamp; - this.status = rawDocument.status; // TODO: look into this this.supportingDocument = rawDocument.supportingDocument; - this.trialLocation = rawDocument.trialLocation; // TODO: look into this - this.userId = rawDocument.userId; // TODO: restricted + this.trialLocation = rawDocument.trialLocation; + + // only share the userId with an external user if it is the logged in user + if (applicationContext.getCurrentUser().userId === rawDocument.userId) { + this.userId = rawDocument.userId; + } + + // only use the privatePractitioner name + if (Array.isArray(rawDocument.privatePractitioners)) { + this.privatePractitioners = rawDocument.privatePractitioners.map(item => { + return { + name: item.name, + partyPrivatePractitioner: item.partyPrivatePractitioner, + }; + }); + } this.generateFiledBy(rawDocument); } @@ -290,7 +369,12 @@ joiValidationDecorator( addToCoversheet: joi.boolean().optional(), additionalInfo: joi.string().optional(), additionalInfo2: joi.string().optional(), - archived: joi.boolean().optional(), + archived: joi + .boolean() + .optional() + .description( + 'A document that was archived instead of added to the Docket Record.', + ), caseId: joi .string() .optional() @@ -299,19 +383,37 @@ joiValidationDecorator( certificateOfServiceDate: joi.when('certificateOfService', { is: true, otherwise: joi.optional(), - then: joi.date().iso().required(), + then: joiStrictTimestamp.required(), }), - createdAt: joi - .date() - .iso() + createdAt: joiStrictTimestamp .required() .description('When the Document was added to the system.'), + date: joi + .date() + .iso() + .optional() + .allow(null) + .description( + 'An optional date used when generating a fully concatenated document title.', + ), docketNumber: joi .string() .regex(DOCKET_NUMBER_MATCHER) .optional() .description('Docket Number of the associated Case in XXXXX-YY format.'), - documentContents: joi.string().optional(), + docketNumbers: joi + .string() + .optional() + .description( + 'Optional Docket Number text used when generating a fully concatenated document title.', + ), + documentContentsId: joi + .string() + .uuid({ + version: ['uuidv4'], + }) + .optional() + .description('The S3 ID containing the text contents of the document.'), documentId: joi .string() .uuid({ @@ -329,12 +431,11 @@ joiValidationDecorator( .required() .description('The type of this document.'), draftState: joi.object().allow(null).optional(), + entityName: joi.string().valid('Document').required(), eventCode: joi.string().optional(), filedBy: joi.string().allow('').optional(), - filingDate: joi - .date() + filingDate: joiStrictTimestamp .max('now') - .iso() .required() .description('Date that this Document was filed.'), freeText: joi.string().optional(), @@ -353,53 +454,71 @@ joiValidationDecorator( .description( 'A lodged document is awaiting action by the judge to enact or refuse.', ), + numberOfPages: joi.number().optional().allow(null), objections: joi.string().optional(), ordinalValue: joi.string().optional(), partyIrsPractitioner: joi.boolean().optional(), - partyPrimary: joi.boolean().optional(), - partySecondary: joi.boolean().optional(), + partyPrimary: joi + .boolean() + .optional() + .description('Use the primary contact to compose the filedBy text.'), + partySecondary: joi + .boolean() + .optional() + .description('Use the secondary contact to compose the filedBy text.'), pending: joi.boolean().optional(), previousDocument: joi.object().optional(), - privatePractitioners: joi.array().optional(), + privatePractitioners: joi + .array() + .items({ name: joi.string().required() }) + .optional() + .description( + 'Practitioner names to be used to compose the filedBy text.', + ), processingStatus: joi.string().optional(), - qcAt: joi.date().iso().optional(), - qcByUser: joi.object().optional(), + qcAt: joiStrictTimestamp.optional(), qcByUserId: joi.string().optional().allow(null), - receivedAt: joi.date().iso().optional(), - relationship: joi.string().optional(), - scenario: joi.string().optional(), - secondaryDate: joi - .date() - .iso() + receivedAt: joiStrictTimestamp.optional(), + relationship: joi + .string() + .valid(...Document.RELATIONSHIPS) + .optional(), + scenario: joi + .string() + .valid(...Document.SCENARIOS) + .optional(), + secondaryDate: joiStrictTimestamp .optional() .description( 'A secondary date associated with the document, typically related to time-restricted availability.', ), - // TODO: What's the difference between servedAt and serviceDate? - secondaryDocument: joi.object().optional(), - servedAt: joi.date().iso().optional(), - servedParties: joi.array().optional(), - serviceDate: joi.date().iso().max('now').optional().allow(null), + servedAt: joiStrictTimestamp + .optional() + .description('When the document is served on the parties.'), + servedParties: joi + .array() + .items({ name: joi.string().required() }) + .optional(), + serviceDate: joiStrictTimestamp + .max('now') + .optional() + .allow(null) + .description('Certificate of service date.'), serviceStamp: joi.string().optional(), - signedAt: joi.date().iso().optional().allow(null), + signedAt: joiStrictTimestamp.optional().allow(null), signedByUserId: joi.string().optional().allow(null), signedJudgeName: joi.string().optional().allow(null), - status: joi.string().valid('served').optional(), supportingDocument: joi.string().optional().allow(null), trialLocation: joi - .alternatives() - .try( - joi.string().valid(...TrialSession.TRIAL_CITY_STRINGS), - joi.string().pattern(TRIAL_LOCATION_MATCHER), // Allow unique values for testing - joi.string().allow(null), - ) - .optional(), + .string() + .optional() + .allow(null) + .description( + 'An optional trial location used when generating a fully concatenated document title.', + ), userId: joi.string().required(), workItems: joi.array().optional(), }), - function () { - return WorkItem.validateCollection(this.workItems); - }, ); /** @@ -419,7 +538,6 @@ Document.prototype.archive = function () { }; Document.prototype.setAsServed = function (servedParties = null) { - this.status = 'served'; this.servedAt = createISODateString(); this.draftState = null; diff --git a/shared/src/business/entities/Document.test.js b/shared/src/business/entities/Document.test.js index 5a0ab46630c..23da7aa68ca 100644 --- a/shared/src/business/entities/Document.test.js +++ b/shared/src/business/entities/Document.test.js @@ -96,6 +96,7 @@ describe('Document entity', () => { const myDoc = new Document(A_VALID_DOCUMENT, { applicationContext }); myDoc.documentId = 'a6b81f4d-1e47-423a-8caf-6d2fdc3d3859'; expect(myDoc.isValid()).toBeTruthy(); + expect(myDoc.entityName).toEqual('Document'); }); it('Creates an invalid document with no document type', () => { @@ -134,9 +135,9 @@ describe('Document entity', () => { { assigneeId: 'bob', assigneeName: 'bob', - caseCaptionNames: 'testing', caseId: 'c6b81f4d-1e47-423a-8caf-6d2fdc3d3859', caseStatus: 'new', + caseTitle: 'Johnny Joe Jacobson', docketNumber: '101-18', document: {}, isQC: true, @@ -177,7 +178,7 @@ describe('Document entity', () => { error = err; } - expect(document.documentContents).toBeDefined(); + expect(document.documentContents).not.toBeDefined(); expect(error).not.toBeDefined(); }); @@ -853,9 +854,9 @@ describe('Document entity', () => { { assigneeId: 'bill', assigneeName: 'bill', - caseCaptionNames: 'testing', caseId: 'c6b81f4d-1e47-423a-8caf-6d2fdc3d3859', caseStatus: 'new', + caseTitle: 'Johnny Joe Jacobson', docketNumber: '101-18', document: {}, isQC: false, @@ -873,9 +874,9 @@ describe('Document entity', () => { { assigneeId: 'bob', assigneeName: 'bob', - caseCaptionNames: 'testing', caseId: 'c6b81f4d-1e47-423a-8caf-6d2fdc3d3859', caseStatus: 'new', + caseTitle: 'Johnny Joe Jacobson', docketNumber: '101-18', document: {}, isQC: true, @@ -908,9 +909,9 @@ describe('Document entity', () => { { assigneeId: 'bill', assigneeName: 'bill', - caseCaptionNames: 'testing', caseId: 'c6b81f4d-1e47-423a-8caf-6d2fdc3d3859', caseStatus: 'new', + caseTitle: 'Johnny Joe Jacobson', docketNumber: '101-18', document: {}, isQC: false, @@ -997,7 +998,6 @@ describe('Document entity', () => { ); document.setAsServed(); - expect(document.status).toEqual('served'); expect(document.servedAt).toBeDefined(); expect(document.draftState).toEqual(null); }); @@ -1019,7 +1019,6 @@ describe('Document entity', () => { }, ]); - expect(document.status).toEqual('served'); expect(document.servedAt).toBeDefined(); expect(document.draftState).toEqual(null); expect(document.servedParties).toMatchObject([{ name: 'Served Party' }]); diff --git a/shared/src/business/entities/ForwardMessage.js b/shared/src/business/entities/ForwardMessage.js index 5b9f48c6947..3149e24ecaf 100644 --- a/shared/src/business/entities/ForwardMessage.js +++ b/shared/src/business/entities/ForwardMessage.js @@ -32,7 +32,6 @@ joiValidationDecorator( forwardMessage: joi.string().required(), section: joi.string().required(), }), - undefined, ForwardMessage.VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/InitialWorkItemMessage.js b/shared/src/business/entities/InitialWorkItemMessage.js index 53bc537dc70..d3b34fa853b 100644 --- a/shared/src/business/entities/InitialWorkItemMessage.js +++ b/shared/src/business/entities/InitialWorkItemMessage.js @@ -32,7 +32,6 @@ joiValidationDecorator( message: joi.string().required(), section: joi.string().required(), }), - undefined, InitialWorkItemMessage.VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/IrsPractitioner.js b/shared/src/business/entities/IrsPractitioner.js index d2c407dbda2..428255ac7cb 100644 --- a/shared/src/business/entities/IrsPractitioner.js +++ b/shared/src/business/entities/IrsPractitioner.js @@ -17,6 +17,7 @@ const { SERVICE_INDICATOR_TYPES } = require('./cases/CaseConstants'); */ function IrsPractitioner(rawUser) { userDecorator(this, rawUser); + this.entityName = 'IrsPractitioner'; this.serviceIndicator = rawUser.serviceIndicator || SERVICE_INDICATOR_TYPES.SI_ELECTRONIC; } @@ -25,12 +26,12 @@ joiValidationDecorator( IrsPractitioner, joi.object().keys({ ...userValidation, + entityName: joi.string().valid('IrsPractitioner').required(), serviceIndicator: joi .string() .valid(...Object.values(SERVICE_INDICATOR_TYPES)) .required(), }), - undefined, VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/IrsPractitioner.test.js b/shared/src/business/entities/IrsPractitioner.test.js index 2896c29f6a1..4edcd4eb919 100644 --- a/shared/src/business/entities/IrsPractitioner.test.js +++ b/shared/src/business/entities/IrsPractitioner.test.js @@ -21,6 +21,7 @@ describe('IrsPractitioner', () => { userId: 'petitioner', }); expect(user.isValid()).toBeTruthy(); + expect(user.entityName).toEqual('IrsPractitioner'); }); it('Creates an invalid', () => { diff --git a/shared/src/business/entities/Message.js b/shared/src/business/entities/Message.js index 78b4c1a3016..bae170fdbb3 100644 --- a/shared/src/business/entities/Message.js +++ b/shared/src/business/entities/Message.js @@ -3,7 +3,8 @@ const { joiValidationDecorator, } = require('../../utilities/JoiValidationDecorator'); const { createISODateString } = require('../utilities/DateHandler'); - +const { getTimestampSchema } = require('../../utilities/dateSchema'); +const joiStrictTimestamp = getTimestampSchema(); /** * constructor * @@ -14,6 +15,8 @@ function Message(rawMessage, { applicationContext }) { if (!applicationContext) { throw new TypeError('applicationContext must be defined'); } + this.entityName = 'Message'; + this.createdAt = rawMessage.createdAt || createISODateString(); this.from = rawMessage.from; this.fromUserId = rawMessage.fromUserId; @@ -28,7 +31,8 @@ Message.validationName = 'Message'; joiValidationDecorator( Message, joi.object().keys({ - createdAt: joi.date().iso().optional(), + createdAt: joiStrictTimestamp.optional(), + entityName: joi.string().valid('Message').required(), from: joi.string().required(), fromUserId: joi .string() diff --git a/shared/src/business/entities/NewPractitioner.js b/shared/src/business/entities/NewPractitioner.js index e8e6f68deca..d863aba0c85 100644 --- a/shared/src/business/entities/NewPractitioner.js +++ b/shared/src/business/entities/NewPractitioner.js @@ -35,7 +35,6 @@ joiValidationDecorator( role: joi.string().optional().allow(null), userId: joi.string().optional().allow(null), }), - undefined, VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/Practitioner.js b/shared/src/business/entities/Practitioner.js index d118d52a500..adbe7545d52 100644 --- a/shared/src/business/entities/Practitioner.js +++ b/shared/src/business/entities/Practitioner.js @@ -8,7 +8,8 @@ const { userValidation, VALIDATION_ERROR_MESSAGES: USER_VALIDATION_ERROR_MESSAGES, } = require('./User'); - +const { getTimestampSchema } = require('../../utilities/dateSchema'); +const joiStrictTimestamp = getTimestampSchema(); const EMPLOYER_OPTIONS = ['IRS', 'DOJ', 'Private']; const PRACTITIONER_TYPE_OPTIONS = ['Attorney', 'Non-Attorney']; const ADMISSIONS_STATUS_OPTIONS = [ @@ -38,6 +39,7 @@ const roleMap = { Practitioner.prototype.init = function (rawUser) { userDecorator(this, rawUser); + this.entityName = 'Practitioner'; this.name = Practitioner.getFullName(rawUser); this.firstName = rawUser.firstName; this.lastName = rawUser.lastName; @@ -90,9 +92,7 @@ const validationRules = { .optional() .allow(null) .description('An alternate phone number for the practitioner.'), - admissionsDate: joi - .date() - .iso() + admissionsDate: joiStrictTimestamp .max('now') .required() .description( @@ -126,6 +126,7 @@ const validationRules = { .valid(...EMPLOYER_OPTIONS) .required() .description('The employer designation for the practitioner.'), + entityName: joi.string().valid('Practitioner').required(), firmName: joi .string() .optional() @@ -167,7 +168,6 @@ joiValidationDecorator( joi.object().keys({ ...validationRules, }), - undefined, VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/PrivatePractitioner.js b/shared/src/business/entities/PrivatePractitioner.js index e7833acd683..c7e4a6088bd 100644 --- a/shared/src/business/entities/PrivatePractitioner.js +++ b/shared/src/business/entities/PrivatePractitioner.js @@ -13,6 +13,7 @@ const { userDecorator, userValidation } = require('./User'); */ function PrivatePractitioner(rawUser) { userDecorator(this, rawUser); + this.entityName = 'PrivatePractitioner'; this.representingPrimary = rawUser.representingPrimary; this.representingSecondary = rawUser.representingSecondary; this.serviceIndicator = @@ -23,6 +24,7 @@ joiValidationDecorator( PrivatePractitioner, joi.object().keys({ ...userValidation, + entityName: joi.string().valid('PrivatePractitioner').required(), representingPrimary: joi.boolean().optional(), representingSecondary: joi.boolean().optional(), serviceIndicator: joi @@ -30,7 +32,6 @@ joiValidationDecorator( .valid(...Object.values(SERVICE_INDICATOR_TYPES)) .required(), }), - undefined, {}, ); diff --git a/shared/src/business/entities/PrivatePractitioner.test.js b/shared/src/business/entities/PrivatePractitioner.test.js index 9a60df97fbe..603a3aa6d49 100644 --- a/shared/src/business/entities/PrivatePractitioner.test.js +++ b/shared/src/business/entities/PrivatePractitioner.test.js @@ -21,6 +21,7 @@ describe('PrivatePractitioner', () => { userId: 'petitioner', }); expect(user.isValid()).toBeTruthy(); + expect(user.entityName).toEqual('PrivatePractitioner'); }); it('Creates an invalid', () => { diff --git a/shared/src/business/entities/PublicUser.js b/shared/src/business/entities/PublicUser.js index 4c4f2803446..9abc0eda6d3 100644 --- a/shared/src/business/entities/PublicUser.js +++ b/shared/src/business/entities/PublicUser.js @@ -50,7 +50,6 @@ function PublicUser(rawUser) { joiValidationDecorator( PublicUser, joi.object().keys(userValidation), - undefined, VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/Scan.js b/shared/src/business/entities/Scan.js index 198e4e5e0ae..dc9a2b25edb 100644 --- a/shared/src/business/entities/Scan.js +++ b/shared/src/business/entities/Scan.js @@ -3,8 +3,9 @@ const { joiValidationDecorator, } = require('../../utilities/JoiValidationDecorator'); const { createISODateString } = require('../utilities/DateHandler'); +const { getTimestampSchema } = require('../../utilities/dateSchema'); const { remove } = require('lodash'); - +const joiStrictTimestamp = getTimestampSchema(); /** * constructor * @@ -80,7 +81,7 @@ Scan.VALIDATION_ERROR_MESSAGES = { Scan.schema = joi.object().keys({ batches: joi.array().min(1).required(), - createdAt: joi.date().iso().required(), + createdAt: joiStrictTimestamp.required(), scanId: joi .string() .uuid({ @@ -89,11 +90,6 @@ Scan.schema = joi.object().keys({ .required(), }); -joiValidationDecorator( - Scan, - Scan.schema, - undefined, - Scan.VALIDATION_ERROR_MESSAGES, -); +joiValidationDecorator(Scan, Scan.schema, Scan.VALIDATION_ERROR_MESSAGES); module.exports = { Scan }; diff --git a/shared/src/business/entities/User.js b/shared/src/business/entities/User.js index f5e7e5b2733..f43116a3f58 100644 --- a/shared/src/business/entities/User.js +++ b/shared/src/business/entities/User.js @@ -26,6 +26,7 @@ User.ROLES = { }; const userDecorator = (obj, rawObj) => { + obj.entityName = 'User'; obj.barNumber = rawObj.barNumber; obj.email = rawObj.email; obj.name = rawObj.name; @@ -90,6 +91,7 @@ const userValidation = { }) .optional(), email: joi.string().optional(), + entityName: joi.string().valid('User').required(), judgeFullName: joi.when('role', { is: User.ROLES.judge, otherwise: joi.optional().allow(null), @@ -142,7 +144,6 @@ User.validationName = 'User'; joiValidationDecorator( User, joi.object().keys(userValidation), - undefined, VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/User.test.js b/shared/src/business/entities/User.test.js index a852b084c50..5022e68499a 100644 --- a/shared/src/business/entities/User.test.js +++ b/shared/src/business/entities/User.test.js @@ -68,6 +68,7 @@ describe('User entity', () => { userId: 'Tester', }); expect(user.isValid()).toBeTruthy(); + expect(user.entityName).toEqual('User'); }); it('Creates a valid privatePractitioner user', () => { diff --git a/shared/src/business/entities/WorkItem.js b/shared/src/business/entities/WorkItem.js index 6363cac3006..baf91cc036d 100644 --- a/shared/src/business/entities/WorkItem.js +++ b/shared/src/business/entities/WorkItem.js @@ -4,9 +4,10 @@ const { } = require('../../utilities/JoiValidationDecorator'); const { CHIEF_JUDGE } = require('./cases/CaseConstants'); const { createISODateString } = require('../utilities/DateHandler'); +const { getTimestampSchema } = require('../../utilities/dateSchema'); const { Message } = require('./Message'); const { omit, orderBy } = require('lodash'); - +const joiStrictTimestamp = getTimestampSchema(); /** * constructor * @@ -17,13 +18,15 @@ function WorkItem(rawWorkItem, { applicationContext }) { if (!applicationContext) { throw new TypeError('applicationContext must be defined'); } + this.entityName = 'WorkItem'; + this.associatedJudge = rawWorkItem.associatedJudge || CHIEF_JUDGE; this.assigneeId = rawWorkItem.assigneeId; this.assigneeName = rawWorkItem.assigneeName; - this.caseCaptionNames = rawWorkItem.caseCaptionNames; this.caseId = rawWorkItem.caseId; this.caseIsInProgress = rawWorkItem.caseIsInProgress; this.caseStatus = rawWorkItem.caseStatus; + this.caseTitle = rawWorkItem.caseTitle; this.completedAt = rawWorkItem.completedAt; this.completedBy = rawWorkItem.completedBy; this.completedByUserId = rawWorkItem.completedByUserId; @@ -58,7 +61,6 @@ joiValidationDecorator( assigneeId: joi.string().allow(null).optional(), assigneeName: joi.string().allow(null).optional(), // should be a Message entity at some point associatedJudge: joi.string().required(), - caseCaptionNames: joi.string().optional(), caseId: joi .string() .uuid({ @@ -67,7 +69,8 @@ joiValidationDecorator( .required(), caseIsInProgress: joi.boolean().optional(), caseStatus: joi.string().optional(), - completedAt: joi.date().iso().optional(), + caseTitle: joi.string().optional(), + completedAt: joiStrictTimestamp.optional(), completedBy: joi.string().optional().allow(null), completedByUserId: joi .string() @@ -77,10 +80,11 @@ joiValidationDecorator( .optional() .allow(null), completedMessage: joi.string().optional().allow(null), - createdAt: joi.date().iso().optional(), + createdAt: joiStrictTimestamp.optional(), docketNumber: joi.string().required(), docketNumberSuffix: joi.string().allow(null).optional(), document: joi.object().required(), + entityName: joi.string().valid('WorkItem').required(), hideFromPendingMessages: joi.boolean().optional(), highPriority: joi.boolean().optional(), inProgress: joi.boolean().optional(), @@ -97,8 +101,8 @@ joiValidationDecorator( version: ['uuidv4'], }) .optional(), - trialDate: joi.date().iso().optional().allow(null), - updatedAt: joi.date().iso().required(), + trialDate: joiStrictTimestamp.optional().allow(null), + updatedAt: joiStrictTimestamp.required(), workItemId: joi .string() .uuid({ @@ -106,9 +110,6 @@ joiValidationDecorator( }) .required(), }), - function () { - return Message.validateCollection(this.messages); - }, ); /** diff --git a/shared/src/business/entities/WorkItem.test.js b/shared/src/business/entities/WorkItem.test.js index 90ec0bb718c..fa54ce9f89a 100644 --- a/shared/src/business/entities/WorkItem.test.js +++ b/shared/src/business/entities/WorkItem.test.js @@ -14,9 +14,9 @@ describe('WorkItem', () => { { assigneeId: 'bob', assigneeName: 'bob', - caseCaptionNames: 'testing', caseId: 'c6b81f4d-1e47-423a-8caf-6d2fdc3d3859', caseStatus: Case.STATUS_TYPES.new, + caseTitle: 'Johnny Joe Jacobson', docketNumber: '101-18', docketNumberSuffix: 'S', document: {}, @@ -35,9 +35,9 @@ describe('WorkItem', () => { { assigneeId: 'bob', assigneeName: 'bob', - caseCaptionNames: 'testing', caseId: 'c6b81f4d-1e47-423a-8caf-6d2fdc3d3859', caseStatus: Case.STATUS_TYPES.new, + caseTitle: 'Johnny Joe Jacobson', docketNumber: '101-18', docketNumberSuffix: 'S', document: {}, @@ -57,9 +57,9 @@ describe('WorkItem', () => { { assigneeId: 'bob', assigneeName: 'bob', - caseCaptionNames: 'testing', caseId: 'c6b81f4d-1e47-423a-8caf-6d2fdc3d3859', caseStatus: Case.STATUS_TYPES.new, + caseTitle: 'Johnny Joe Jacobson', docketNumber: '101-18', docketNumberSuffix: 'S', document: {}, @@ -80,9 +80,9 @@ describe('WorkItem', () => { { assigneeId: 'bob', assigneeName: 'bob', - caseCaptionNames: 'testing', caseId: 'c6b81f4d-1e47-423a-8caf-6d2fdc3d3859', caseStatus: Case.STATUS_TYPES.new, + caseTitle: 'Johnny Joe Jacobson', docketNumber: '101-18', docketNumberSuffix: 'S', document: {}, @@ -100,9 +100,9 @@ describe('WorkItem', () => { { assigneeId: 'bob', assigneeName: 'bob', - caseCaptionNames: 'testing', caseId: 'c6b81f4d-1e47-423a-8caf-6d2fdc3d3859', caseStatus: Case.STATUS_TYPES.new, + caseTitle: 'Johnny Joe Jacobson', docketNumber: '101-18', docketNumberSuffix: 'S', document: {}, @@ -129,9 +129,9 @@ describe('WorkItem', () => { { assigneeId: 'bob', assigneeName: 'bob', - caseCaptionNames: 'testing', caseId: 'c6b81f4d-1e47-423a-8caf-6d2fdc3d3859', caseStatus: Case.STATUS_TYPES.new, + caseTitle: 'Johnny Joe Jacobson', docketNumber: '101-18', docketNumberSuffix: 'S', document: {}, @@ -159,9 +159,9 @@ describe('WorkItem', () => { { assigneeId: 'bob', assigneeName: 'bob', - caseCaptionNames: 'testing', caseId: 'c6b81f4d-1e47-423a-8caf-6d2fdc3d3859', caseStatus: Case.STATUS_TYPES.new, + caseTitle: 'Johnny Joe Jacobson', docketNumber: '101-18', docketNumberSuffix: 'S', document: {}, diff --git a/shared/src/business/entities/WorkQueue.js b/shared/src/business/entities/WorkQueue.js index 17527853e95..6864d0f03e9 100644 --- a/shared/src/business/entities/WorkQueue.js +++ b/shared/src/business/entities/WorkQueue.js @@ -2,7 +2,6 @@ const { sortBy } = require('lodash'); exports.ADC_SECTION = 'adc'; exports.ADMISSIONS_SECTION = 'admissions'; -exports.CALENDAR_SECTION = 'calendar'; exports.CHAMBERS_SECTION = 'chambers'; exports.CLERK_OF_COURT_SECTION = 'clerkofcourt'; exports.DOCKET_SECTION = 'docket'; @@ -44,7 +43,6 @@ exports.WELLS_CHAMBERS_SECTION = 'wellsChambers'; exports.SECTIONS = sortBy([ exports.ADC_SECTION, exports.ADMISSIONS_SECTION, - exports.CALENDAR_SECTION, exports.CHAMBERS_SECTION, exports.CLERK_OF_COURT_SECTION, exports.DOCKET_SECTION, diff --git a/shared/src/business/entities/caseAssociation/AddIrsPractitioner.js b/shared/src/business/entities/caseAssociation/AddIrsPractitioner.js index 61c8f708898..9ac8a9b9d55 100644 --- a/shared/src/business/entities/caseAssociation/AddIrsPractitioner.js +++ b/shared/src/business/entities/caseAssociation/AddIrsPractitioner.js @@ -25,7 +25,6 @@ AddIrsPractitioner.schema = joi.object().keys({ joiValidationDecorator( AddIrsPractitioner, AddIrsPractitioner.schema, - undefined, AddIrsPractitioner.VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/caseAssociation/AddPrivatePractitionerFactory.js b/shared/src/business/entities/caseAssociation/AddPrivatePractitionerFactory.js index d59c7489156..c1377f571ff 100644 --- a/shared/src/business/entities/caseAssociation/AddPrivatePractitionerFactory.js +++ b/shared/src/business/entities/caseAssociation/AddPrivatePractitionerFactory.js @@ -41,8 +41,6 @@ AddPrivatePractitionerFactory.get = metadata => { representingSecondary: joi.boolean(), }; - let customValidate; - const makeRequired = itemName => { makeRequiredHelper({ itemName, @@ -61,7 +59,6 @@ AddPrivatePractitionerFactory.get = metadata => { joiValidationDecorator( entityConstructor, schema, - customValidate, AddPrivatePractitionerFactory.VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/caseAssociation/EditPrivatePractitionerFactory.js b/shared/src/business/entities/caseAssociation/EditPrivatePractitionerFactory.js index b50a10a4d47..e263607ace4 100644 --- a/shared/src/business/entities/caseAssociation/EditPrivatePractitionerFactory.js +++ b/shared/src/business/entities/caseAssociation/EditPrivatePractitionerFactory.js @@ -39,8 +39,6 @@ EditPrivatePractitionerFactory.get = metadata => { representingSecondary: joi.boolean(), }; - let customValidate; - const makeRequired = itemName => { makeRequiredHelper({ itemName, @@ -59,7 +57,6 @@ EditPrivatePractitionerFactory.get = metadata => { joiValidationDecorator( entityConstructor, schema, - customValidate, EditPrivatePractitionerFactory.VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/cases/Case.js b/shared/src/business/entities/cases/Case.js index 7722a043469..ec030d19a39 100644 --- a/shared/src/business/entities/cases/Case.js +++ b/shared/src/business/entities/cases/Case.js @@ -20,13 +20,14 @@ const { ContactFactory } = require('../contacts/ContactFactory'); const { DocketRecord } = require('../DocketRecord'); const { Document } = require('../Document'); const { find, includes, isEmpty } = require('lodash'); +const { getTimestampSchema } = require('../../../utilities/dateSchema'); const { IrsPractitioner } = require('../IrsPractitioner'); const { MAX_FILE_SIZE_MB } = require('../../../persistence/s3/getUploadPolicy'); const { Order } = require('../orders/Order'); const { PrivatePractitioner } = require('../PrivatePractitioner'); const { TrialSession } = require('../trialSessions/TrialSession'); const { User } = require('../User'); - +const joiStrictTimestamp = getTimestampSchema(); const orderDocumentTypes = Order.ORDER_TYPES.map( orderType => orderType.documentType, ); @@ -247,10 +248,9 @@ function Case(rawCase, { applicationContext, filtered = false }) { this.highPriorityReason = rawCase.highPriorityReason; this.qcCompleteForTrial = rawCase.qcCompleteForTrial || {}; this.status = rawCase.status || Case.STATUS_TYPES.new; + this.userId = rawCase.userId; } - this.userId = rawCase.userId; - this.caseCaption = rawCase.caseCaption; this.caseId = rawCase.caseId || applicationContext.getUniqueId(); this.caseType = rawCase.caseType; @@ -284,6 +284,10 @@ function Case(rawCase, { applicationContext, filtered = false }) { this.trialSessionId = rawCase.trialSessionId; this.trialTime = rawCase.trialTime; + if (applicationContext.getCurrentUser().userId === rawCase.userId) { + this.userId = rawCase.userId; + } + this.initialDocketNumberSuffix = rawCase.initialDocketNumberSuffix || this.docketNumberSuffix || '_'; @@ -360,6 +364,7 @@ function Case(rawCase, { applicationContext, filtered = false }) { Case.validationRules = { associatedJudge: joi .string() + .max(50) .optional() .meta({ tags: ['Restricted'] }) .description('Judge assigned to this case. Defaults to Chief Judge.'), @@ -372,7 +377,7 @@ Case.validationRules = { automaticBlockedDate: joi.when('automaticBlocked', { is: true, otherwise: joi.optional().allow(null), - then: joi.date().iso().required(), + then: joiStrictTimestamp.required(), }), automaticBlockedReason: joi.when('automaticBlocked', { is: true, @@ -392,7 +397,7 @@ Case.validationRules = { .when('blocked', { is: true, otherwise: joi.optional().allow(null), - then: joi.date().iso().required(), + then: joiStrictTimestamp.required(), }) .meta({ tags: ['Restricted'] }), blockedReason: joi @@ -401,6 +406,7 @@ Case.validationRules = { otherwise: joi.optional().allow(null), then: joi .string() + .max(250) .required() .description( 'Open text field for describing reason for blocking this case from trial.', @@ -409,6 +415,7 @@ Case.validationRules = { .meta({ tags: ['Restricted'] }), caseCaption: joi .string() + .max(500) .required() .description( 'The name of the party bringing the case, e.g. "Carol Williams, Petitioner," "Mark Taylor, Incompetent, Debra Thomas, Next Friend, Petitioner," or "Estate of Test Taxpayer, Deceased, Petitioner." This is the first half of the case title.', @@ -422,6 +429,7 @@ Case.validationRules = { .description('Unique case ID only used by the system.'), caseNote: joi .string() + .max(500) .optional() .meta({ tags: ['Restricted'] }), caseType: joi @@ -431,13 +439,11 @@ Case.validationRules = { closedDate: joi.when('status', { is: Case.STATUS_TYPES.closed, otherwise: joi.optional().allow(null), - then: joi.date().iso().required(), + then: joiStrictTimestamp.required(), }), contactPrimary: joi.object().required(), contactSecondary: joi.object().optional().allow(null), - createdAt: joi - .date() - .iso() + createdAt: joiStrictTimestamp .required() .description( 'When the paper or electronic case was added to the system. This value cannot be edited.', @@ -481,22 +487,22 @@ Case.validationRules = { .when('highPriority', { is: true, otherwise: joi.optional().allow(null), - then: joi.string().required(), + then: joi.string().max(250).required(), }) .meta({ tags: ['Restricted'] }), initialCaption: joi .string() + .max(500) .allow(null) .optional() .description('Case caption before modification.'), initialDocketNumberSuffix: joi .string() + .max(2) // TODO: add enum .allow(null) .optional() .description('Case docket number suffix before modification.'), - irsNoticeDate: joi - .date() - .iso() + irsNoticeDate: joiStrictTimestamp .max('now') .optional() .allow(null) @@ -507,9 +513,7 @@ Case.validationRules = { .description( 'List of IRS practitioners (also known as respondents) associated with the case.', ), - irsSendDate: joi - .date() - .iso() + irsSendDate: joiStrictTimestamp .optional() .description('When the case was sent to the IRS by the court.'), isPaper: joi.boolean().optional(), @@ -533,9 +537,7 @@ Case.validationRules = { .boolean() .optional() .description('Reminder for clerks to review the notice of attachments.'), - noticeOfTrialDate: joi - .date() - .iso() + noticeOfTrialDate: joiStrictTimestamp .optional() .description('Reminder for clerks to review the notice of trial date.'), orderDesignatingPlaceOfTrial: joi @@ -586,15 +588,15 @@ Case.validationRules = { petitionPaymentDate: joi .when('petitionPaymentStatus', { is: Case.PAYMENT_STATUS.PAID, - otherwise: joi.date().iso().optional().allow(null), - then: joi.date().iso().required(), + otherwise: joiStrictTimestamp.optional().allow(null), + then: joiStrictTimestamp.required(), }) .description('When the petitioner paid the case fee.'), petitionPaymentMethod: joi .when('petitionPaymentStatus', { is: Case.PAYMENT_STATUS.PAID, otherwise: joi.string().allow(null).optional(), - then: joi.string().required(), + then: joi.string().max(50).required(), }) .description('How the petitioner paid the case fee.'), petitionPaymentStatus: joi @@ -605,8 +607,8 @@ Case.validationRules = { petitionPaymentWaivedDate: joi .when('petitionPaymentStatus', { is: Case.PAYMENT_STATUS.WAIVED, - otherwise: joi.date().iso().allow(null).optional(), - then: joi.date().iso().required(), + otherwise: joiStrictTimestamp.allow(null).optional(), + then: joiStrictTimestamp.required(), }) .description('When the case fee was waived.'), preferredTrialCity: joi @@ -633,16 +635,12 @@ Case.validationRules = { .description( 'QC Checklist object that must be completed before the case can go to trial.', ), - receivedAt: joi - .date() - .iso() + receivedAt: joiStrictTimestamp .required() .description( 'When the case was received by the court. If electronic, this value will be the same as createdAt. If paper, this value can be edited.', ), - sealedDate: joi - .date() - .iso() + sealedDate: joiStrictTimestamp .optional() .allow(null) .description('When the case was sealed from the public.'), @@ -658,9 +656,7 @@ Case.validationRules = { .optional() .meta({ tags: ['Restricted'] }) .description('Status of the case.'), - trialDate: joi - .date() - .iso() + trialDate: joiStrictTimestamp .optional() .allow(null) .description('When this case goes to trial.'), @@ -685,11 +681,12 @@ Case.validationRules = { ), trialTime: joi .string() - .pattern(/^[0-9]+:([0-5][0-9])$/) + .pattern(/^[0-9]{1,2}:([0-5][0-9])$/) .optional() .description('Time of day when this case goes to trial.'), userId: joi .string() + .max(50) .optional() .meta({ tags: ['Restricted'] }) .description('The unique ID of the User who added the case to the system.'), @@ -703,15 +700,6 @@ Case.validationRules = { joiValidationDecorator( Case, joi.object().keys(Case.validationRules), - function () { - return ( - Case.isValidDocketNumber(this.docketNumber) && - Document.validateCollection(this.documents) && - DocketRecord.validateCollection(this.docketRecord) && - IrsPractitioner.validateCollection(this.irsPractitioners) && - PrivatePractitioner.validateCollection(this.privatePractitioners) - ); - }, Case.VALIDATION_ERROR_MESSAGES, ); @@ -798,9 +786,9 @@ Case.prototype.doesHavePendingItems = function () { * get the case caption without the ", Petitioner/s/(s)" postfix * * @param {string} caseCaption the original case caption - * @returns {string} caseCaptionNames the case caption with the postfix removed + * @returns {string} caseTitle the case caption with the postfix removed */ -Case.getCaseCaptionNames = function (caseCaption) { +Case.getCaseTitle = function (caseCaption) { return caseCaption.replace(/\s*,\s*Petitioner(s|\(s\))?\s*$/, '').trim(); }; @@ -1018,14 +1006,6 @@ Case.prototype.getDocumentById = function ({ documentId }) { return this.documents.find(document => document.documentId === documentId); }; -/** - * - * @returns {boolean} whether to show case name for primary - */ -Case.prototype.getShowCaseNameForPrimary = function () { - return !(this.contactSecondary && this.contactSecondary.name); -}; - /** * * @param {string} preferredTrialCity the preferred trial city diff --git a/shared/src/business/entities/cases/Case.test.js b/shared/src/business/entities/cases/Case.test.js index 31030d7b873..9df5abb237b 100644 --- a/shared/src/business/entities/cases/Case.test.js +++ b/shared/src/business/entities/cases/Case.test.js @@ -157,6 +157,7 @@ describe('Case entity', () => { applicationContext, }); expect(myCase.isValid()).toBeTruthy(); + expect(myCase.entityName).toEqual('Case'); }); it('Creates a valid case from an already existing case json', () => { @@ -166,6 +167,19 @@ describe('Case entity', () => { expect(myCase.isValid()).toBeTruthy(); }); + it('Creates an invalid case with an invalid nested contact object', () => { + const myCase = new Case( + { + ...MOCK_CASE, + contactPrimary: {}, + }, + { + applicationContext, + }, + ); + expect(myCase.isValid()).toBeFalsy(); + }); + it('Creates an invalid case with a document', () => { const myCase = new Case( { @@ -734,26 +748,24 @@ describe('Case entity', () => { }); }); - describe('getCaseCaptionNames', () => { + describe('getCaseTitle', () => { it('party type Petitioner', () => { - const caseCaptionNames = Case.getCaseCaptionNames( - 'Test Petitioner, Petitioner', - ); - expect(caseCaptionNames).toEqual('Test Petitioner'); + const caseTitle = Case.getCaseTitle('Test Petitioner, Petitioner'); + expect(caseTitle).toEqual('Test Petitioner'); }); it('party type Petitioner & Spouse', () => { - const caseCaptionNames = Case.getCaseCaptionNames( + const caseTitle = Case.getCaseTitle( 'Test Petitioner & Test Petitioner 2, Petitioners', ); - expect(caseCaptionNames).toEqual('Test Petitioner & Test Petitioner 2'); + expect(caseTitle).toEqual('Test Petitioner & Test Petitioner 2'); }); it('party type Estate with an Executor/Personal Representative/Fiduciary/etc.', () => { - const caseCaptionNames = Case.getCaseCaptionNames( + const caseTitle = Case.getCaseTitle( 'Estate of Test Petitioner 2, Deceased, Test Petitioner, Executor, Petitioner(s)', ); - expect(caseCaptionNames).toEqual( + expect(caseTitle).toEqual( 'Estate of Test Petitioner 2, Deceased, Test Petitioner, Executor', ); }); @@ -882,37 +894,6 @@ describe('Case entity', () => { expect(error).toBeTruthy(); }); }); - describe('validateWithError', () => { - it('passes back an error passed in if invalid', () => { - let error = null; - const caseRecord = new Case( - {}, - { - applicationContext, - }, - ); - try { - caseRecord.validateWithError(new Error("I'm a real error")); - } catch (e) { - error = e; - } - expect(error).toBeDefined(); - expect(error.message).toContain("I'm a real error"); - }); - - it('does not pass back an error passed in if valid', () => { - let error; - const caseRecord = new Case(MOCK_CASE, { - applicationContext, - }); - try { - caseRecord.validateWithError(new Error("I'm a real error")); - } catch (e) { - error = e; - } - expect(error).not.toBeDefined(); - }); - }); describe('attachIrsPractitioner', () => { it('adds the user to the irsPractitioners', () => { @@ -1191,9 +1172,9 @@ describe('Case entity', () => { { assigneeId: 'bob', assigneeName: 'bob', - caseCaptionNames: 'testing', caseId: 'c6b81f4d-1e47-423a-8caf-6d2fdc3d3859', caseStatus: Case.STATUS_TYPES.new, + caseTitle: 'Johnny Joe Jacobson', docketNumber: '101-18', document: {}, isQC: true, @@ -1208,9 +1189,9 @@ describe('Case entity', () => { { assigneeId: 'bob', assigneeName: 'bob', - caseCaptionNames: 'testing', caseId: 'c6b81f4d-1e47-423a-8caf-6d2fdc3d3859', caseStatus: Case.STATUS_TYPES.new, + caseTitle: 'Johnny Joe Jacobson', docketNumber: '101-18', document: {}, isQC: true, @@ -1275,7 +1256,7 @@ describe('Case entity', () => { it("should NOT change the status to 'Ready for Trial' when an answer document has been filed on the cutoff", () => { // eslint-disable-next-line spellcheck/spell-checker /* - Note: As of this writing on 2020-03-20, there may be a bug in the `moment` library as it pertains to + Note: As of this writing on 2020-03-20, there may be a bug in the `moment` library as it pertains to leap-years and/or leap-days and maybe daylight saving time, too. Meaning that if *this* test runs at a time when it is calculating date/time differences across the existence of a leap year and DST, it may fail. */ diff --git a/shared/src/business/entities/cases/CaseExternal.js b/shared/src/business/entities/cases/CaseExternal.js index a04aac00a42..05dca925991 100644 --- a/shared/src/business/entities/cases/CaseExternal.js +++ b/shared/src/business/entities/cases/CaseExternal.js @@ -95,9 +95,6 @@ CaseExternal.commonRequirements = { joiValidationDecorator( CaseExternal, joi.object().keys(CaseExternal.commonRequirements), - function () { - return !this.getFormattedValidationErrors(); - }, CaseExternal.VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/cases/CaseExternal.test.js b/shared/src/business/entities/cases/CaseExternal.test.js index afecececb9e..004b09a3452 100644 --- a/shared/src/business/entities/cases/CaseExternal.test.js +++ b/shared/src/business/entities/cases/CaseExternal.test.js @@ -60,7 +60,7 @@ describe('CaseExternal entity', () => { }); describe('Petition file size', () => { - it('should inform you if petition file size is greater than 500MB', () => { + it('should inform you if petition file size is greater than the PDF max file size', () => { const caseExternal = new CaseExternal({ caseType: 'Other', filingType: 'Myself', @@ -123,7 +123,7 @@ describe('CaseExternal entity', () => { }); describe('STIN file size', () => { - it('should inform you if stin file size is greater than 500MB', () => { + it('should inform you if stin file size is greater than the file max size', () => { const caseExternal = new CaseExternal({ caseType: 'Other', filingType: 'Myself', @@ -186,7 +186,7 @@ describe('CaseExternal entity', () => { }); describe('ownership disclosure file size', () => { - it('should inform you if ownership disclosure file size is greater than 500MB', () => { + it('should inform you if ownership disclosure file size is greater than the PDF max file size', () => { const caseExternal = new CaseExternal({ caseType: 'Other', filingType: 'Myself', diff --git a/shared/src/business/entities/cases/CaseExternalIncomplete.js b/shared/src/business/entities/cases/CaseExternalIncomplete.js index 130cbe58226..39c4bee5849 100644 --- a/shared/src/business/entities/cases/CaseExternalIncomplete.js +++ b/shared/src/business/entities/cases/CaseExternalIncomplete.js @@ -54,9 +54,6 @@ joiValidationDecorator( preferredTrialCity: CaseExternal.commonRequirements.preferredTrialCity, procedureType: CaseExternal.commonRequirements.procedureType, }), - function () { - return !this.getFormattedValidationErrors(); - }, CaseExternalIncomplete.VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/cases/CaseExternalInformationFactory.js b/shared/src/business/entities/cases/CaseExternalInformationFactory.js index f5f620db9b6..3db5152791b 100644 --- a/shared/src/business/entities/cases/CaseExternalInformationFactory.js +++ b/shared/src/business/entities/cases/CaseExternalInformationFactory.js @@ -7,7 +7,7 @@ const { CaseExternal } = require('./CaseExternal'); /** * CaseExternalInformationFactory Entity - * Represents a Case that a Petitioner is attempting to add to the system via the File a Petition wizard. + * Represents a Case that a Petitioner is attempting to add to the system via the File a Petition (now Create a Case) wizard. * Required fields are based on the user's current step in the wizard. * * @param {object} rawCase the raw case data @@ -82,9 +82,6 @@ const schema = { joiValidationDecorator( CaseExternalInformationFactory, joi.object().keys(schema), - function () { - return !this.getFormattedValidationErrors(); - }, CaseExternalInformationFactory.VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/cases/CaseExternalInformationFactory.test.js b/shared/src/business/entities/cases/CaseExternalInformationFactory.test.js index fbb1eb96add..d5b5e230207 100644 --- a/shared/src/business/entities/cases/CaseExternalInformationFactory.test.js +++ b/shared/src/business/entities/cases/CaseExternalInformationFactory.test.js @@ -39,7 +39,7 @@ describe('CaseExternalInformationFactory entity', () => { }); describe('STIN file size', () => { - it('should inform you if stin file size is greater than 500MB', () => { + it('should inform you if stin file size is greater than the PDF max file size', () => { const caseExternal = new CaseExternalInformationFactory({ stinFile: new File([], 'test.pdf'), stinFileSize: MAX_FILE_SIZE_BYTES + 5, @@ -161,7 +161,7 @@ describe('CaseExternalInformationFactory entity', () => { }); describe('petition file size', () => { - it('should inform you if petition file size is greater than 500MB', () => { + it('should inform you if petition file size is greater than the PDF max file size', () => { const caseExternal = new CaseExternalInformationFactory({ petitionFile: new File([], 'test.pdf'), petitionFileSize: MAX_FILE_SIZE_BYTES + 5, @@ -336,7 +336,7 @@ describe('CaseExternalInformationFactory entity', () => { }); describe('ownership disclosure file size', () => { - it('should inform you if ownership disclosure file size is greater than 500MB', () => { + it('should inform you if ownership disclosure file size is greater than the PDF max file size', () => { const caseExternal = new CaseExternalInformationFactory({ ownershipDisclosureFile: new File([], 'test.pdf'), ownershipDisclosureFileSize: MAX_FILE_SIZE_BYTES + 5, diff --git a/shared/src/business/entities/cases/CaseInternal.js b/shared/src/business/entities/cases/CaseInternal.js index 35cf1ca0d1e..28036b760db 100644 --- a/shared/src/business/entities/cases/CaseInternal.js +++ b/shared/src/business/entities/cases/CaseInternal.js @@ -7,7 +7,9 @@ const { } = require('../../../persistence/s3/getUploadPolicy'); const { Case } = require('./Case'); const { ContactFactory } = require('../contacts/ContactFactory'); +const { getTimestampSchema } = require('../../../utilities/dateSchema'); +const joiStrictTimestamp = getTimestampSchema(); CaseInternal.DEFAULT_PROCEDURE_TYPE = Case.PROCEDURE_TYPES[0]; /** @@ -33,6 +35,12 @@ function CaseInternal(rawCase) { this.orderDesignatingPlaceOfTrial = undefined; } this.orderForOds = rawCase.orderForOds; + this.orderForAmendedPetition = rawCase.orderForAmendedPetition; + this.orderForAmendedPetitionAndFilingFee = + rawCase.orderForAmendedPetitionAndFilingFee; + this.orderForFilingFee = rawCase.orderForFilingFee; + this.orderForRatification = rawCase.orderForRatification; + this.orderToShowCause = rawCase.orderToShowCause; this.ownershipDisclosureFile = rawCase.ownershipDisclosureFile; this.ownershipDisclosureFileSize = rawCase.ownershipDisclosureFileSize; this.partyType = rawCase.partyType; @@ -104,6 +112,13 @@ const paperRequirements = joi mailingDate: joi.string().max(25).required(), orderDesignatingPlaceOfTrial: Case.validationRules.orderDesignatingPlaceOfTrial, + orderForAmendedPetition: Case.validationRules.orderForAmendedPetition, + orderForAmendedPetitionAndFilingFee: + Case.validationRules.orderForAmendedPetitionAndFilingFee, + orderForFilingFee: Case.validationRules.orderForFilingFee, + orderForOds: Case.validationRules.orderForOds, + orderForRatification: Case.validationRules.orderForRatification, + orderToShowCause: Case.validationRules.orderToShowCause, ownershipDisclosureFile: joi.when('partyType', { is: joi .exist() @@ -134,8 +149,8 @@ const paperRequirements = joi }), petitionPaymentDate: joi.when('petitionPaymentStatus', { is: Case.PAYMENT_STATUS.PAID, - otherwise: joi.date().iso().optional().allow(null), - then: joi.date().iso().max('now').required(), + otherwise: joiStrictTimestamp.optional().allow(null), + then: joiStrictTimestamp.max('now').required(), }), petitionPaymentMethod: Case.validationRules.petitionPaymentMethod, petitionPaymentStatus: Case.validationRules.petitionPaymentStatus, @@ -148,7 +163,7 @@ const paperRequirements = joi then: joi.string().required(), }), procedureType: joi.string().required(), - receivedAt: joi.date().iso().max('now').required(), + receivedAt: joiStrictTimestamp.max('now').required(), requestForPlaceOfTrialFile: joi .alternatives() .conditional('preferredTrialCity', { @@ -161,7 +176,7 @@ const paperRequirements = joi otherwise: joi.optional().allow(null), then: joi.number().required().min(1).max(MAX_FILE_SIZE_BYTES).integer(), }), - stinFile: joi.object().required(), + stinFile: joi.object().optional(), stinFileSize: joi.when('stinFile', { is: joi.exist().not(null), otherwise: joi.optional().allow(null), @@ -177,9 +192,6 @@ const paperRequirements = joi joiValidationDecorator( CaseInternal, paperRequirements, - function () { - return !this.getFormattedValidationErrors(); - }, CaseInternal.VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/cases/CaseInternal.test.js b/shared/src/business/entities/cases/CaseInternal.test.js index 852704d82db..b354ef8340b 100644 --- a/shared/src/business/entities/cases/CaseInternal.test.js +++ b/shared/src/business/entities/cases/CaseInternal.test.js @@ -18,7 +18,6 @@ describe('CaseInternal entity', () => { petitionPaymentStatus: VALIDATION_ERROR_MESSAGES.petitionPaymentStatus, procedureType: VALIDATION_ERROR_MESSAGES.procedureType, receivedAt: VALIDATION_ERROR_MESSAGES.receivedAt[1], - stinFile: VALIDATION_ERROR_MESSAGES.stinFile, }); }); @@ -47,8 +46,6 @@ describe('CaseInternal entity', () => { receivedAt: new Date().toISOString(), requestForPlaceOfTrialFile: { anObject: true }, requestForPlaceOfTrialFileSize: 1, - stinFile: { anObject: true }, - stinFileSize: 1, }); expect(caseInternal.getFormattedValidationErrors()).toEqual(null); expect(caseInternal.isValid()).toEqual(true); @@ -80,8 +77,6 @@ describe('CaseInternal entity', () => { petitionPaymentStatus: Case.PAYMENT_STATUS.UNPAID, procedureType: 'Small', receivedAt: new Date().toISOString(), - stinFile: { anObject: true }, - stinFileSize: 1, }); expect(caseInternal.getFormattedValidationErrors()).toEqual(null); expect(caseInternal.isValid()).toEqual(true); @@ -112,8 +107,6 @@ describe('CaseInternal entity', () => { petitionPaymentStatus: Case.PAYMENT_STATUS.UNPAID, procedureType: 'Small', receivedAt: new Date().toISOString(), - stinFile: { anObject: true }, - stinFileSize: 1, }); expect(caseInternal.getFormattedValidationErrors()).toEqual(null); expect(caseInternal.isValid()).toEqual(true); diff --git a/shared/src/business/entities/cases/CaseSearch.js b/shared/src/business/entities/cases/CaseSearch.js index 5718287a2fa..3a0fbc382f8 100644 --- a/shared/src/business/entities/cases/CaseSearch.js +++ b/shared/src/business/entities/cases/CaseSearch.js @@ -53,7 +53,6 @@ CaseSearch.schema = joi.object().keys({ joiValidationDecorator( CaseSearch, CaseSearch.schema, - undefined, CaseSearch.VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/cases/PublicCase.js b/shared/src/business/entities/cases/PublicCase.js index ad191cffc76..e13aa253410 100644 --- a/shared/src/business/entities/cases/PublicCase.js +++ b/shared/src/business/entities/cases/PublicCase.js @@ -3,12 +3,15 @@ const { joiValidationDecorator, } = require('../../../utilities/JoiValidationDecorator'); const { Document } = require('../Document'); +const { getTimestampSchema } = require('../../../utilities/dateSchema'); const { map } = require('lodash'); const { Order } = require('../orders/Order'); const { PublicContact } = require('./PublicContact'); const { PublicDocketRecordEntry } = require('./PublicDocketRecordEntry'); const { PublicDocument } = require('./PublicDocument'); +const joiStrictTimestamp = getTimestampSchema(); + /** * Public Case Entity * Represents the view of the public case. @@ -52,11 +55,11 @@ const publicCaseSchema = { version: ['uuidv4'], }) .optional(), - createdAt: joi.date().iso().optional(), + createdAt: joiStrictTimestamp.optional(), docketNumber: joi.string().optional(), docketNumberSuffix: joi.string().allow(null).optional(), isSealed: joi.boolean(), - receivedAt: joi.date().iso().optional(), + receivedAt: joiStrictTimestamp.optional(), }; const sealedCaseSchemaRestricted = { caseCaption: joi.any().forbidden(), @@ -77,7 +80,6 @@ joiValidationDecorator( joi.object(publicCaseSchema).when(joi.object({ isSealed: true }).unknown(), { then: joi.object(sealedCaseSchemaRestricted), }), - undefined, {}, ); diff --git a/shared/src/business/entities/cases/PublicContact.js b/shared/src/business/entities/cases/PublicContact.js index 25cd77fbc72..2fcfb617711 100644 --- a/shared/src/business/entities/cases/PublicContact.js +++ b/shared/src/business/entities/cases/PublicContact.js @@ -20,7 +20,6 @@ joiValidationDecorator( name: joi.string().optional(), state: joi.string().optional(), }), - undefined, {}, ); diff --git a/shared/src/business/entities/cases/PublicDocketRecordEntry.js b/shared/src/business/entities/cases/PublicDocketRecordEntry.js index 06d572d6068..6ced543226c 100644 --- a/shared/src/business/entities/cases/PublicDocketRecordEntry.js +++ b/shared/src/business/entities/cases/PublicDocketRecordEntry.js @@ -2,6 +2,9 @@ const joi = require('@hapi/joi'); const { joiValidationDecorator, } = require('../../../utilities/JoiValidationDecorator'); +const { getTimestampSchema } = require('../../../utilities/dateSchema'); + +const joiStrictTimestamp = getTimestampSchema(); /** * PublicDocketRecordEntry @@ -22,11 +25,10 @@ joiValidationDecorator( joi.object().keys({ description: joi.string().optional(), documentId: joi.string().optional(), - filedBy: joi.date().iso().optional(), - filingDate: joi.date().max('now').iso().optional(), // Required on DocketRecord so probably should be required here. + filedBy: joiStrictTimestamp.optional(), + filingDate: joiStrictTimestamp.max('now').optional(), // Required on DocketRecord so probably should be required here. index: joi.number().integer().optional(), }), - undefined, {}, ); diff --git a/shared/src/business/entities/cases/PublicDocument.js b/shared/src/business/entities/cases/PublicDocument.js index 881f7e0beaa..7beda62b99b 100644 --- a/shared/src/business/entities/cases/PublicDocument.js +++ b/shared/src/business/entities/cases/PublicDocument.js @@ -2,6 +2,9 @@ const joi = require('@hapi/joi'); const { joiValidationDecorator, } = require('../../../utilities/JoiValidationDecorator'); +const { getTimestampSchema } = require('../../../utilities/dateSchema'); + +const joiStrictTimestamp = getTimestampSchema(); /** * PublicDocument @@ -38,7 +41,7 @@ joiValidationDecorator( version: ['uuidv4'], }) .optional(), - createdAt: joi.date().iso().optional(), + createdAt: joiStrictTimestamp.optional(), documentId: joi .string() .uuid({ @@ -51,12 +54,11 @@ joiValidationDecorator( filedBy: joi.string().optional(), isPaper: joi.boolean().optional(), processingStatus: joi.string().optional(), - receivedAt: joi.date().iso().optional(), - servedAt: joi.date().iso().optional(), + receivedAt: joiStrictTimestamp.optional(), + servedAt: joiStrictTimestamp.optional(), servedParties: joi.array().optional(), status: joi.string().optional(), }), - undefined, {}, ); diff --git a/shared/src/business/entities/contacts/ContactFactory.js b/shared/src/business/entities/contacts/ContactFactory.js index a80c65b78c9..cbe384ddd9b 100644 --- a/shared/src/business/entities/contacts/ContactFactory.js +++ b/shared/src/business/entities/contacts/ContactFactory.js @@ -443,7 +443,6 @@ ContactFactory.createContactFactory = ({ ...ContactFactory.getValidationObject({ countryType, isPaper }), ...additionalValidation, }), - undefined, GenericContactConstructor.errorToMessageMap, ); diff --git a/shared/src/business/entities/contacts/ContactFactory.test.js b/shared/src/business/entities/contacts/ContactFactory.test.js index aa944841e52..a6e8dda8fb6 100644 --- a/shared/src/business/entities/contacts/ContactFactory.test.js +++ b/shared/src/business/entities/contacts/ContactFactory.test.js @@ -12,7 +12,7 @@ describe('Petition', () => { caseType: 'Other', filingType: 'Myself', hasIrsNotice: true, - irsNoticeDate: '2009-10-13', + irsNoticeDate: '2009-10-13T08:06:07.539Z', mailingDate: 'testing', partyType: ContactFactory.PARTY_TYPES.corporation, petitionFile: {}, @@ -43,7 +43,7 @@ describe('Petition', () => { }, filingType: 'Myself', hasIrsNotice: true, - irsNoticeDate: '2009-10-13', + irsNoticeDate: '2009-10-13T08:06:07.539Z', mailingDate: 'testing', partyType: ContactFactory.PARTY_TYPES.corporation, petitionFile: {}, @@ -75,7 +75,7 @@ describe('Petition', () => { }, filingType: 'Myself', hasIrsNotice: true, - irsNoticeDate: '2009-10-13', + irsNoticeDate: '2009-10-13T08:06:07.539Z', mailingDate: 'testing', partyType: ContactFactory.PARTY_TYPES.petitioner, petitionFile: {}, @@ -106,7 +106,7 @@ describe('Petition', () => { }, filingType: 'Myself', hasIrsNotice: true, - irsNoticeDate: '2009-10-13', + irsNoticeDate: '2009-10-13T08:06:07.539Z', mailingDate: 'testing', partyType: ContactFactory.PARTY_TYPES.estateWithoutExecutor, petitionFile: {}, @@ -125,7 +125,7 @@ describe('Petition', () => { caseType: 'Other', filingType: 'Myself', hasIrsNotice: true, - irsNoticeDate: '2009-10-13', + irsNoticeDate: '2009-10-13T08:06:07.539Z', mailingDate: 'testing', partyType: ContactFactory.PARTY_TYPES.estate, petitionFile: {}, @@ -157,7 +157,7 @@ describe('Petition', () => { }, filingType: 'Myself', hasIrsNotice: true, - irsNoticeDate: '2009-10-13', + irsNoticeDate: '2009-10-13T08:06:07.539Z', mailingDate: 'testing', partyType: ContactFactory.PARTY_TYPES.estate, petitionFile: {}, @@ -188,7 +188,7 @@ describe('Petition', () => { }, filingType: 'Myself', hasIrsNotice: true, - irsNoticeDate: '2009-10-13', + irsNoticeDate: '2009-10-13T08:06:07.539Z', mailingDate: 'testing', partyType: ContactFactory.PARTY_TYPES.estate, petitionFile: {}, @@ -208,7 +208,7 @@ describe('Petition', () => { filingType: 'Myself', hasIrsNotice: true, - irsNoticeDate: '2009-10-13', + irsNoticeDate: '2009-10-13T08:06:07.539Z', mailingDate: 'testing', partyType: ContactFactory.PARTY_TYPES.partnershipBBA, petitionFile: {}, @@ -241,7 +241,7 @@ describe('Petition', () => { }, filingType: 'Myself', hasIrsNotice: true, - irsNoticeDate: '2009-10-13', + irsNoticeDate: '2009-10-13T08:06:07.539Z', mailingDate: 'testing', partyType: ContactFactory.PARTY_TYPES.partnershipBBA, petitionFile: {}, @@ -261,7 +261,7 @@ describe('Petition', () => { filingType: 'Myself', hasIrsNotice: true, - irsNoticeDate: '2009-10-13', + irsNoticeDate: '2009-10-13T08:06:07.539Z', mailingDate: 'testing', partyType: ContactFactory.PARTY_TYPES.trust, petitionFile: {}, @@ -293,7 +293,7 @@ describe('Petition', () => { }, filingType: 'Myself', hasIrsNotice: true, - irsNoticeDate: '2009-10-13', + irsNoticeDate: '2009-10-13T08:06:07.539Z', mailingDate: 'testing', partyType: ContactFactory.PARTY_TYPES.trust, petitionFile: {}, @@ -313,7 +313,7 @@ describe('Petition', () => { filingType: 'Myself', hasIrsNotice: true, - irsNoticeDate: '2009-10-13', + irsNoticeDate: '2009-10-13T08:06:07.539Z', mailingDate: 'testing', partyType: ContactFactory.PARTY_TYPES.conservator, petitionFile: {}, @@ -343,7 +343,7 @@ describe('Petition', () => { }, filingType: 'Myself', hasIrsNotice: true, - irsNoticeDate: '2009-10-13', + irsNoticeDate: '2009-10-13T08:06:07.539Z', mailingDate: 'testing', partyType: ContactFactory.PARTY_TYPES.conservator, petitionFile: {}, @@ -363,7 +363,7 @@ describe('Petition', () => { filingType: 'Myself', hasIrsNotice: true, - irsNoticeDate: '2009-10-13', + irsNoticeDate: '2009-10-13T08:06:07.539Z', mailingDate: 'testing', partyType: ContactFactory.PARTY_TYPES.guardian, petitionFile: {}, @@ -393,7 +393,7 @@ describe('Petition', () => { }, filingType: 'Myself', hasIrsNotice: true, - irsNoticeDate: '2009-10-13', + irsNoticeDate: '2009-10-13T08:06:07.539Z', mailingDate: 'testing', partyType: ContactFactory.PARTY_TYPES.guardian, petitionFile: {}, @@ -413,7 +413,7 @@ describe('Petition', () => { filingType: 'Myself', hasIrsNotice: true, - irsNoticeDate: '2009-10-13', + irsNoticeDate: '2009-10-13T08:06:07.539Z', mailingDate: 'testing', partyType: ContactFactory.PARTY_TYPES.custodian, petitionFile: {}, @@ -443,7 +443,7 @@ describe('Petition', () => { }, filingType: 'Myself', hasIrsNotice: true, - irsNoticeDate: '2009-10-13', + irsNoticeDate: '2009-10-13T08:06:07.539Z', mailingDate: 'testing', partyType: ContactFactory.PARTY_TYPES.custodian, petitionFile: {}, @@ -463,7 +463,7 @@ describe('Petition', () => { filingType: 'Myself', hasIrsNotice: true, - irsNoticeDate: '2009-10-13', + irsNoticeDate: '2009-10-13T08:06:07.539Z', mailingDate: 'testing', partyType: ContactFactory.PARTY_TYPES.donor, petitionFile: {}, @@ -494,7 +494,7 @@ describe('Petition', () => { }, filingType: 'Myself', hasIrsNotice: true, - irsNoticeDate: '2009-10-13', + irsNoticeDate: '2009-10-13T08:06:07.539Z', mailingDate: 'testing', partyType: ContactFactory.PARTY_TYPES.donor, petitionFile: {}, @@ -514,7 +514,7 @@ describe('Petition', () => { filingType: 'Myself', hasIrsNotice: true, - irsNoticeDate: '2009-10-13', + irsNoticeDate: '2009-10-13T08:06:07.539Z', mailingDate: 'testing', partyType: ContactFactory.PARTY_TYPES.transferee, petitionFile: {}, @@ -545,7 +545,7 @@ describe('Petition', () => { }, filingType: 'Myself', hasIrsNotice: true, - irsNoticeDate: '2009-10-13', + irsNoticeDate: '2009-10-13T08:06:07.539Z', mailingDate: 'testing', partyType: ContactFactory.PARTY_TYPES.transferee, petitionFile: {}, @@ -575,7 +575,7 @@ describe('Petition', () => { }, filingType: 'Myself', hasIrsNotice: true, - irsNoticeDate: '2009-10-13', + irsNoticeDate: '2009-10-13T08:06:07.539Z', mailingDate: 'testing', partyType: ContactFactory.PARTY_TYPES.transferee, petitionFile: {}, @@ -583,7 +583,7 @@ describe('Petition', () => { petitionPaymentStatus: Case.PAYMENT_STATUS.UNPAID, preferredTrialCity: 'Chattanooga, Tennessee', procedureType: 'Small', - receivedAt: '2009-10-13', + receivedAt: '2009-10-13T08:06:07.539Z', requestForPlaceOfTrialFile: new File( [], 'requestForPlaceOfTrialFile.pdf', diff --git a/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentDefault.js b/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentDefault.js index 83c29775c5e..8522c4f280d 100644 --- a/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentDefault.js +++ b/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentDefault.js @@ -25,7 +25,6 @@ CourtIssuedDocumentDefault.schema = { joiValidationDecorator( CourtIssuedDocumentDefault, CourtIssuedDocumentDefault.schema, - undefined, VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeA.js b/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeA.js index 6e5d431c87d..0a8bf782c0c 100644 --- a/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeA.js +++ b/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeA.js @@ -47,7 +47,6 @@ CourtIssuedDocumentTypeA.schema = { joiValidationDecorator( CourtIssuedDocumentTypeA, CourtIssuedDocumentTypeA.schema, - undefined, VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeB.js b/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeB.js index e534ffa9b1e..b0173e6bd01 100644 --- a/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeB.js +++ b/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeB.js @@ -33,7 +33,6 @@ CourtIssuedDocumentTypeB.schema = { joiValidationDecorator( CourtIssuedDocumentTypeB, CourtIssuedDocumentTypeB.schema, - undefined, VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeC.js b/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeC.js index d6b641f296d..79d0d215c51 100644 --- a/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeC.js +++ b/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeC.js @@ -31,7 +31,6 @@ CourtIssuedDocumentTypeC.schema = { joiValidationDecorator( CourtIssuedDocumentTypeC, CourtIssuedDocumentTypeC.schema, - undefined, VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeD.js b/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeD.js index a93f470d346..fe1ef66b625 100644 --- a/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeD.js +++ b/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeD.js @@ -1,6 +1,6 @@ const joi = require('@hapi/joi'); -const moment = require('moment'); const { + calculateISODate, createISODateString, formatDateString, FORMATS, @@ -8,10 +8,13 @@ const { const { joiValidationDecorator, } = require('../../../utilities/JoiValidationDecorator'); +const { getTimestampSchema } = require('../../../utilities/dateSchema'); const { replaceBracketed } = require('../../utilities/replaceBracketed'); const { VALIDATION_ERROR_MESSAGES } = require('./CourtIssuedDocumentConstants'); -const yesterdayMoment = moment().subtract(1, 'd'); +const joiStrictTimestamp = getTimestampSchema(); + +const yesterdayMoment = calculateISODate({ howMuch: -1, unit: 'days' }); const yesterdayFormatted = formatDateString( createISODateString(yesterdayMoment), FORMATS.MMDDYYYY, @@ -40,7 +43,7 @@ CourtIssuedDocumentTypeD.prototype.getDocumentTitle = function () { CourtIssuedDocumentTypeD.schema = { attachments: joi.boolean().required(), - date: joi.date().iso().min(yesterdayFormatted).required(), + date: joiStrictTimestamp.min(yesterdayFormatted).required(), documentTitle: joi.string().optional(), documentType: joi.string().required(), freeText: joi.string().optional(), @@ -49,7 +52,6 @@ CourtIssuedDocumentTypeD.schema = { joiValidationDecorator( CourtIssuedDocumentTypeD, CourtIssuedDocumentTypeD.schema, - undefined, VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeD.test.js b/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeD.test.js index 0efbc54b03c..6b2ea788bee 100644 --- a/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeD.test.js +++ b/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeD.test.js @@ -1,4 +1,7 @@ -const moment = require('moment'); +const { + calculateISODate, + createISODateString, +} = require('../../utilities/DateHandler'); const { CourtIssuedDocumentFactory } = require('./CourtIssuedDocumentFactory'); const { VALIDATION_ERROR_MESSAGES } = require('./CourtIssuedDocumentConstants'); @@ -16,7 +19,11 @@ describe('CourtIssuedDocumentTypeD', () => { }); it('should have error message for past date', () => { - const date = moment().subtract(5, 'days').format(); + const date = calculateISODate({ + dateString: createISODateString(), + howMuch: -5, + unit: 'days', + }); const extDoc = CourtIssuedDocumentFactory.get({ attachments: false, date, diff --git a/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeE.js b/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeE.js index e6141336d4c..d9c6c8deb36 100644 --- a/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeE.js +++ b/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeE.js @@ -1,6 +1,6 @@ const joi = require('@hapi/joi'); -const moment = require('moment'); const { + calculateISODate, createISODateString, formatDateString, FORMATS, @@ -8,10 +8,13 @@ const { const { joiValidationDecorator, } = require('../../../utilities/JoiValidationDecorator'); +const { getTimestampSchema } = require('../../../utilities/dateSchema'); const { replaceBracketed } = require('../../utilities/replaceBracketed'); const { VALIDATION_ERROR_MESSAGES } = require('./CourtIssuedDocumentConstants'); -const yesterdayMoment = moment().subtract(1, 'd'); +const joiStrictTimestamp = getTimestampSchema(); + +const yesterdayMoment = calculateISODate({ howMuch: -1, unit: 'days' }); const yesterdayFormatted = formatDateString( createISODateString(yesterdayMoment), FORMATS.MMDDYYYY, @@ -38,7 +41,7 @@ CourtIssuedDocumentTypeE.prototype.getDocumentTitle = function () { CourtIssuedDocumentTypeE.schema = { attachments: joi.boolean().required(), - date: joi.date().iso().min(yesterdayFormatted).required(), + date: joiStrictTimestamp.min(yesterdayFormatted).required(), documentTitle: joi.string().optional(), documentType: joi.string().required(), }; @@ -46,7 +49,6 @@ CourtIssuedDocumentTypeE.schema = { joiValidationDecorator( CourtIssuedDocumentTypeE, CourtIssuedDocumentTypeE.schema, - undefined, VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeE.test.js b/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeE.test.js index 5b96438fdb2..752f6357560 100644 --- a/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeE.test.js +++ b/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeE.test.js @@ -1,4 +1,7 @@ -const moment = require('moment'); +const { + calculateISODate, + createISODateString, +} = require('../../utilities/DateHandler'); const { CourtIssuedDocumentFactory } = require('./CourtIssuedDocumentFactory'); const { VALIDATION_ERROR_MESSAGES } = require('./CourtIssuedDocumentConstants'); @@ -16,7 +19,11 @@ describe('CourtIssuedDocumentTypeE', () => { }); it('should have error message for past date', () => { - const date = moment().subtract(5, 'days').format(); + const date = calculateISODate({ + dateString: createISODateString(), + howMuch: -5, + unit: 'days', + }); const extDoc = CourtIssuedDocumentFactory.get({ attachments: false, date, diff --git a/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeF.js b/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeF.js index 2bb0b3522cd..2845549774f 100644 --- a/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeF.js +++ b/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeF.js @@ -33,7 +33,6 @@ CourtIssuedDocumentTypeF.schema = { joiValidationDecorator( CourtIssuedDocumentTypeF, CourtIssuedDocumentTypeF.schema, - undefined, VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeG.js b/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeG.js index 7075c68ef64..536888dcad3 100644 --- a/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeG.js +++ b/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeG.js @@ -3,9 +3,12 @@ const { joiValidationDecorator, } = require('../../../utilities/JoiValidationDecorator'); const { formatDateString } = require('../../utilities/DateHandler'); +const { getTimestampSchema } = require('../../../utilities/dateSchema'); const { replaceBracketed } = require('../../utilities/replaceBracketed'); const { VALIDATION_ERROR_MESSAGES } = require('./CourtIssuedDocumentConstants'); +const joiStrictTimestamp = getTimestampSchema(); + /** * * @param {object} rawProps the raw document data @@ -29,7 +32,7 @@ CourtIssuedDocumentTypeG.prototype.getDocumentTitle = function () { CourtIssuedDocumentTypeG.schema = { attachments: joi.boolean().required(), - date: joi.date().iso().required(), + date: joiStrictTimestamp.required(), documentTitle: joi.string().optional(), documentType: joi.string().required(), trialLocation: joi.string().required(), @@ -38,7 +41,6 @@ CourtIssuedDocumentTypeG.schema = { joiValidationDecorator( CourtIssuedDocumentTypeG, CourtIssuedDocumentTypeG.schema, - undefined, VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeH.js b/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeH.js index 5b877d6bddb..ff220dee7fa 100644 --- a/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeH.js +++ b/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeH.js @@ -3,9 +3,12 @@ const { joiValidationDecorator, } = require('../../../utilities/JoiValidationDecorator'); const { formatDateString } = require('../../utilities/DateHandler'); +const { getTimestampSchema } = require('../../../utilities/dateSchema'); const { replaceBracketed } = require('../../utilities/replaceBracketed'); const { VALIDATION_ERROR_MESSAGES } = require('./CourtIssuedDocumentConstants'); +const joiStrictTimestamp = getTimestampSchema(); + /** * * @param {object} rawProps the raw document data @@ -29,7 +32,7 @@ CourtIssuedDocumentTypeH.prototype.getDocumentTitle = function () { CourtIssuedDocumentTypeH.schema = { attachments: joi.boolean().required(), - date: joi.date().iso().max('now').required(), + date: joiStrictTimestamp.max('now').required(), documentTitle: joi.string().optional(), documentType: joi.string().required(), freeText: joi.string().required(), @@ -38,7 +41,6 @@ CourtIssuedDocumentTypeH.schema = { joiValidationDecorator( CourtIssuedDocumentTypeH, CourtIssuedDocumentTypeH.schema, - undefined, VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeH.test.js b/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeH.test.js index f52ab6fd785..179846bed72 100644 --- a/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeH.test.js +++ b/shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentTypeH.test.js @@ -1,4 +1,4 @@ -const moment = require('moment'); +const { calculateISODate } = require('../../utilities/DateHandler'); const { CourtIssuedDocumentFactory } = require('./CourtIssuedDocumentFactory'); const { VALIDATION_ERROR_MESSAGES } = require('./CourtIssuedDocumentConstants'); @@ -17,7 +17,7 @@ describe('CourtIssuedDocumentTypeH', () => { }); it('should have error message for future date', () => { - const date = moment().add(5, 'days').format(); + const date = calculateISODate({ howMuch: 5, unit: 'days' }); const extDoc = CourtIssuedDocumentFactory.get({ attachments: false, date, diff --git a/shared/src/business/entities/docketEntry/DocketEntryFactory.js b/shared/src/business/entities/docketEntry/DocketEntryFactory.js index 3f94298fdff..cdc75de66b5 100644 --- a/shared/src/business/entities/docketEntry/DocketEntryFactory.js +++ b/shared/src/business/entities/docketEntry/DocketEntryFactory.js @@ -13,7 +13,9 @@ const { VALIDATION_ERROR_MESSAGES, } = require('../externalDocument/ExternalDocumentInformationFactory'); const { Document } = require('../Document'); +const { getTimestampSchema } = require('../../../utilities/dateSchema'); +const joiStrictTimestamp = getTimestampSchema(); DocketEntryFactory.VALIDATION_ERROR_MESSAGES = { ...VALIDATION_ERROR_MESSAGES, dateReceived: [ @@ -77,7 +79,7 @@ function DocketEntryFactory(rawProps) { additionalInfo2: joi.string(), attachments: joi.boolean(), certificateOfService: joi.boolean(), - dateReceived: joi.date().iso().max('now').required(), + dateReceived: joiStrictTimestamp.max('now').required(), documentType: joi.string().optional(), eventCode: joi.string().required(), freeText: joi.string().optional(), @@ -91,12 +93,12 @@ function DocketEntryFactory(rawProps) { otherwise: joi.optional().allow(null), then: joi.number().required().min(1).max(MAX_FILE_SIZE_BYTES).integer(), }), - serviceDate: joi.date().iso().max('now').optional(), + serviceDate: joiStrictTimestamp.max('now').optional(), trialLocation: joi.string().optional(), }); let schemaOptionalItems = { - certificateOfServiceDate: joi.date().iso().max('now').required(), + certificateOfServiceDate: joiStrictTimestamp.max('now').required(), objections: joi.string().required(), partyIrsPractitioner: joi.boolean().required(), partyPrimary: joi.boolean().invalid(false).required(), @@ -104,8 +106,6 @@ function DocketEntryFactory(rawProps) { secondaryDocumentFile: joi.object().optional(), }; - let customValidate; - const addToSchema = itemName => { schema = schema.keys({ [itemName]: schemaOptionalItems[itemName], @@ -160,7 +160,6 @@ function DocketEntryFactory(rawProps) { joiValidationDecorator( entityConstructor, schema, - customValidate, DocketEntryFactory.VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/docketEntry/DocketEntryFactory.test.js b/shared/src/business/entities/docketEntry/DocketEntryFactory.test.js index f54ebf3ae47..ccb9a098b4a 100644 --- a/shared/src/business/entities/docketEntry/DocketEntryFactory.test.js +++ b/shared/src/business/entities/docketEntry/DocketEntryFactory.test.js @@ -1,4 +1,7 @@ -const moment = require('moment'); +const { + calculateISODate, + createISODateString, +} = require('../../utilities/DateHandler'); const { DocketEntryFactory } = require('./DocketEntryFactory'); const { VALIDATION_ERROR_MESSAGES } = DocketEntryFactory; @@ -37,12 +40,12 @@ describe('DocketEntryFactory', () => { expect(errors().dateReceived).toEqual( VALIDATION_ERROR_MESSAGES.dateReceived[1], ); - rawEntity.dateReceived = moment().format(); + rawEntity.dateReceived = createISODateString(); expect(errors().dateReceived).toEqual(undefined); }); it('should not allow received date be in the future', () => { - rawEntity.dateReceived = moment().add(1, 'days').format(); + rawEntity.dateReceived = calculateISODate({ howMuch: 1, unit: 'days' }); expect(errors().dateReceived).toEqual( VALIDATION_ERROR_MESSAGES.dateReceived[0].message, ); @@ -106,12 +109,15 @@ describe('DocketEntryFactory', () => { expect(errors().certificateOfServiceDate).toEqual( VALIDATION_ERROR_MESSAGES.certificateOfServiceDate[1], ); - rawEntity.certificateOfServiceDate = moment().format(); + rawEntity.certificateOfServiceDate = createISODateString(); expect(errors().certificateOfServiceDate).toEqual(undefined); }); it('should not allow certificate of service date be in the future', () => { - rawEntity.certificateOfServiceDate = moment().add(1, 'days').format(); + rawEntity.certificateOfServiceDate = calculateISODate({ + howMuch: 1, + unit: 'days', + }); expect(errors().certificateOfServiceDate).toEqual( VALIDATION_ERROR_MESSAGES.certificateOfServiceDate[0].message, ); diff --git a/shared/src/business/entities/externalDocument/ExternalDocumentInformationFactory.js b/shared/src/business/entities/externalDocument/ExternalDocumentInformationFactory.js index c94ec25b83f..160615602b7 100644 --- a/shared/src/business/entities/externalDocument/ExternalDocumentInformationFactory.js +++ b/shared/src/business/entities/externalDocument/ExternalDocumentInformationFactory.js @@ -17,8 +17,11 @@ const { SupportingDocumentInformationFactory, } = require('./SupportingDocumentInformationFactory'); const { Document } = require('../Document'); +const { getTimestampSchema } = require('../../../utilities/dateSchema'); const { includes, isEqual, reduce, some, sortBy, values } = require('lodash'); +const joiStrictTimestamp = getTimestampSchema(); + const VALIDATION_ERROR_MESSAGES = { attachments: 'Enter selection for Attachments.', category: 'Select a Category.', @@ -177,7 +180,7 @@ ExternalDocumentInformationFactory.get = documentMetadata => { }; let schemaOptionalItems = { - certificateOfServiceDate: joi.date().iso().max('now'), + certificateOfServiceDate: joiStrictTimestamp.max('now'), hasSecondarySupportingDocuments: joi.boolean(), objections: joi.string(), partyIrsPractitioner: joi.boolean(), @@ -236,7 +239,10 @@ ExternalDocumentInformationFactory.get = documentMetadata => { makeRequired('objections'); } - if (documentMetadata.scenario.toLowerCase().trim() === 'nonstandard h') { + if ( + documentMetadata.scenario && + documentMetadata.scenario.toLowerCase().trim() === 'nonstandard h' + ) { if ( includes( documentMetadata.documentType, @@ -285,12 +291,7 @@ ExternalDocumentInformationFactory.get = documentMetadata => { } } - joiValidationDecorator( - entityConstructor, - schema, - undefined, - VALIDATION_ERROR_MESSAGES, - ); + joiValidationDecorator(entityConstructor, schema, VALIDATION_ERROR_MESSAGES); return new entityConstructor(documentMetadata); }; diff --git a/shared/src/business/entities/externalDocument/ExternalDocumentInformationFactory.test.js b/shared/src/business/entities/externalDocument/ExternalDocumentInformationFactory.test.js index 233254b19a3..42bc3bcc5b4 100644 --- a/shared/src/business/entities/externalDocument/ExternalDocumentInformationFactory.test.js +++ b/shared/src/business/entities/externalDocument/ExternalDocumentInformationFactory.test.js @@ -1,4 +1,7 @@ -const moment = require('moment'); +const { + calculateISODate, + createISODateString, +} = require('../../utilities/DateHandler'); const { ExternalDocumentInformationFactory, VALIDATION_ERROR_MESSAGES, @@ -47,12 +50,15 @@ describe('ExternalDocumentInformationFactory', () => { expect(errors().certificateOfServiceDate).toEqual( VALIDATION_ERROR_MESSAGES.certificateOfServiceDate[1], ); - baseDoc.certificateOfServiceDate = moment().format(); + baseDoc.certificateOfServiceDate = createISODateString(); expect(errors().certificateOfServiceDate).toEqual(undefined); }); it('should not allow certificate of service date to be in the future', () => { - baseDoc.certificateOfServiceDate = moment().add(1, 'days').format(); + baseDoc.certificateOfServiceDate = calculateISODate({ + howMuch: 1, + unit: 'days', + }); expect(errors().certificateOfServiceDate).toEqual( VALIDATION_ERROR_MESSAGES.certificateOfServiceDate[0].message, ); @@ -141,7 +147,7 @@ describe('ExternalDocumentInformationFactory', () => { expect( errors().supportingDocuments[0].certificateOfServiceDate, ).toEqual(VALIDATION_ERROR_MESSAGES.certificateOfServiceDate[1]); - baseDoc.supportingDocuments[0].certificateOfServiceDate = moment().format(); + baseDoc.supportingDocuments[0].certificateOfServiceDate = createISODateString(); expect(errors().supportingDocuments).toEqual(undefined); }); @@ -314,7 +320,7 @@ describe('ExternalDocumentInformationFactory', () => { expect( errors().secondarySupportingDocuments[0].certificateOfServiceDate, ).toEqual(VALIDATION_ERROR_MESSAGES.certificateOfServiceDate[1]); - baseDoc.secondarySupportingDocuments[0].certificateOfServiceDate = moment().format(); + baseDoc.secondarySupportingDocuments[0].certificateOfServiceDate = createISODateString(); expect(errors().secondarySupportingDocuments).toEqual(undefined); }); diff --git a/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardA.js b/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardA.js index 879ea2e1c2e..dfe6dab81e5 100644 --- a/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardA.js +++ b/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardA.js @@ -46,7 +46,6 @@ ExternalDocumentNonStandardA.schema = { joiValidationDecorator( ExternalDocumentNonStandardA, ExternalDocumentNonStandardA.schema, - undefined, ExternalDocumentNonStandardA.VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardB.js b/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardB.js index 082f77e86f5..318f2124a8d 100644 --- a/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardB.js +++ b/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardB.js @@ -37,7 +37,6 @@ ExternalDocumentNonStandardB.schema = { joiValidationDecorator( ExternalDocumentNonStandardB, ExternalDocumentNonStandardB.schema, - undefined, ExternalDocumentNonStandardB.VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardC.js b/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardC.js index a11bbdbc8ab..4846a07dff0 100644 --- a/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardC.js +++ b/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardC.js @@ -50,7 +50,6 @@ ExternalDocumentNonStandardC.schema = { joiValidationDecorator( ExternalDocumentNonStandardC, ExternalDocumentNonStandardC.schema, - undefined, ExternalDocumentNonStandardC.VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardD.js b/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardD.js index a5b452626b3..df8a09fa986 100644 --- a/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardD.js +++ b/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardD.js @@ -6,8 +6,11 @@ const { VALIDATION_ERROR_MESSAGES, } = require('./ExternalDocumentInformationFactory'); const { formatDateString } = require('../../utilities/DateHandler'); +const { getTimestampSchema } = require('../../../utilities/dateSchema'); const { replaceBracketed } = require('../../utilities/replaceBracketed'); +const joiStrictTimestamp = getTimestampSchema(); + /** * * @param {object} rawProps the raw document data @@ -44,13 +47,12 @@ ExternalDocumentNonStandardD.schema = { documentType: joi.string().required(), }) .required(), - serviceDate: joi.date().iso().max('now').required(), + serviceDate: joiStrictTimestamp.max('now').required(), }; joiValidationDecorator( ExternalDocumentNonStandardD, ExternalDocumentNonStandardD.schema, - undefined, ExternalDocumentNonStandardD.VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardD.test.js b/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardD.test.js index 0aafcb47bd8..a955888aa1b 100644 --- a/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardD.test.js +++ b/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardD.test.js @@ -1,4 +1,7 @@ -const moment = require('moment'); +const { + calculateISODate, + createISODateString, +} = require('../../utilities/DateHandler'); const { VALIDATION_ERROR_MESSAGES, } = require('./ExternalDocumentInformationFactory'); @@ -19,7 +22,7 @@ describe('ExternalDocumentNonStandardD', () => { }); it('should have error message for future date', () => { - const serviceDate = moment().add(1, 'days').format(); + const serviceDate = calculateISODate({ howMuch: 1, unit: 'days' }); const extDoc = ExternalDocumentFactory.get({ category: 'Supporting Document', documentTitle: 'Certificate of Service [Document Name] [Date]', @@ -34,7 +37,7 @@ describe('ExternalDocumentNonStandardD', () => { }); it('should be valid when all fields are present', () => { - const serviceDate = moment().format(); + const serviceDate = createISODateString(); const extDoc = ExternalDocumentFactory.get({ category: 'Supporting Document', documentTitle: 'Certificate of Service [Document Name] [Date]', diff --git a/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardE.js b/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardE.js index 388b9aa328f..1783c5b7f2f 100644 --- a/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardE.js +++ b/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardE.js @@ -37,7 +37,6 @@ ExternalDocumentNonStandardE.schema = { joiValidationDecorator( ExternalDocumentNonStandardE, ExternalDocumentNonStandardE.schema, - undefined, ExternalDocumentNonStandardE.VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardF.js b/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardF.js index a0a8a10f216..7f93992cbf8 100644 --- a/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardF.js +++ b/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardF.js @@ -49,7 +49,6 @@ ExternalDocumentNonStandardF.schema = { joiValidationDecorator( ExternalDocumentNonStandardF, ExternalDocumentNonStandardF.schema, - undefined, ExternalDocumentNonStandardF.VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardG.js b/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardG.js index abd2b69c4f8..015703f9479 100644 --- a/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardG.js +++ b/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardG.js @@ -41,7 +41,6 @@ ExternalDocumentNonStandardG.schema = { joiValidationDecorator( ExternalDocumentNonStandardG, joi.object(ExternalDocumentNonStandardG.schema), - undefined, ExternalDocumentNonStandardG.VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardH.js b/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardH.js index 1bb7ef3c430..fd5686bc075 100644 --- a/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardH.js +++ b/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardH.js @@ -43,9 +43,6 @@ ExternalDocumentNonStandardH.schema = { joiValidationDecorator( ExternalDocumentNonStandardH, ExternalDocumentNonStandardH.schema, - function () { - return !this.getFormattedValidationErrors(); - }, ExternalDocumentNonStandardH.VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardI.js b/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardI.js index 3be545a73c9..1d5beba6770 100644 --- a/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardI.js +++ b/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardI.js @@ -39,7 +39,6 @@ ExternalDocumentNonStandardI.schema = { joiValidationDecorator( ExternalDocumentNonStandardI, ExternalDocumentNonStandardI.schema, - undefined, ExternalDocumentNonStandardI.VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardJ.js b/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardJ.js index 850f0377185..c4a619c6a55 100644 --- a/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardJ.js +++ b/shared/src/business/entities/externalDocument/ExternalDocumentNonStandardJ.js @@ -39,7 +39,6 @@ ExternalDocumentNonStandardJ.schema = { joiValidationDecorator( ExternalDocumentNonStandardJ, ExternalDocumentNonStandardJ.schema, - undefined, ExternalDocumentNonStandardJ.VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/externalDocument/ExternalDocumentStandard.js b/shared/src/business/entities/externalDocument/ExternalDocumentStandard.js index 06f1f71ab82..edb3ee71866 100644 --- a/shared/src/business/entities/externalDocument/ExternalDocumentStandard.js +++ b/shared/src/business/entities/externalDocument/ExternalDocumentStandard.js @@ -42,7 +42,6 @@ ExternalDocumentStandard.schema = joi.object({ joiValidationDecorator( ExternalDocumentStandard, ExternalDocumentStandard.schema, - undefined, ExternalDocumentStandard.VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/externalDocument/SecondaryDocumentInformationFactory.js b/shared/src/business/entities/externalDocument/SecondaryDocumentInformationFactory.js index a4d8154c37f..65b6eef34bb 100644 --- a/shared/src/business/entities/externalDocument/SecondaryDocumentInformationFactory.js +++ b/shared/src/business/entities/externalDocument/SecondaryDocumentInformationFactory.js @@ -2,9 +2,11 @@ const joi = require('@hapi/joi'); const { joiValidationDecorator, } = require('../../../utilities/JoiValidationDecorator'); +const { getTimestampSchema } = require('../../../utilities/dateSchema'); const { includes } = require('lodash'); const { makeRequiredHelper } = require('./externalDocumentHelpers'); +const joiStrictTimestamp = getTimestampSchema(); /** * * @constructor @@ -36,7 +38,7 @@ SecondaryDocumentInformationFactory.get = ( let schemaOptionalItems = { attachments: joi.boolean(), certificateOfService: joi.boolean(), - certificateOfServiceDate: joi.date().iso().max('now'), + certificateOfServiceDate: joiStrictTimestamp.max('now'), objections: joi.string(), }; @@ -71,12 +73,7 @@ SecondaryDocumentInformationFactory.get = ( } } - joiValidationDecorator( - entityConstructor, - schema, - undefined, - VALIDATION_ERROR_MESSAGES, - ); + joiValidationDecorator(entityConstructor, schema, VALIDATION_ERROR_MESSAGES); return new entityConstructor(documentMetadata); }; diff --git a/shared/src/business/entities/externalDocument/SupportingDocumentInformationFactory.js b/shared/src/business/entities/externalDocument/SupportingDocumentInformationFactory.js index 0952db74b15..9436c4644ba 100644 --- a/shared/src/business/entities/externalDocument/SupportingDocumentInformationFactory.js +++ b/shared/src/business/entities/externalDocument/SupportingDocumentInformationFactory.js @@ -5,9 +5,11 @@ const { const { MAX_FILE_SIZE_BYTES, } = require('../../../persistence/s3/getUploadPolicy'); +const { getTimestampSchema } = require('../../../utilities/dateSchema'); const { includes } = require('lodash'); const { makeRequiredHelper } = require('./externalDocumentHelpers'); +const joiStrictTimestamp = getTimestampSchema(); /** * * @constructor @@ -41,7 +43,7 @@ SupportingDocumentInformationFactory.get = ( }; let schemaOptionalItems = { - certificateOfServiceDate: joi.date().iso().max('now'), + certificateOfServiceDate: joiStrictTimestamp.max('now'), supportingDocumentFile: joi.object(), supportingDocumentFileSize: joi .number() @@ -95,12 +97,7 @@ SupportingDocumentInformationFactory.get = ( makeRequired('supportingDocumentFile'); } - joiValidationDecorator( - entityConstructor, - schema, - undefined, - VALIDATION_ERROR_MESSAGES, - ); + joiValidationDecorator(entityConstructor, schema, VALIDATION_ERROR_MESSAGES); return new entityConstructor(documentMetadata); }; diff --git a/shared/src/business/entities/notes/Note.js b/shared/src/business/entities/notes/Note.js index da479a22d06..3b84691ab0f 100644 --- a/shared/src/business/entities/notes/Note.js +++ b/shared/src/business/entities/notes/Note.js @@ -23,11 +23,6 @@ Note.schema = joi.object().keys({ notes: joi.string().required(), }); -joiValidationDecorator( - Note, - Note.schema, - undefined, - Note.VALIDATION_ERROR_MESSAGES, -); +joiValidationDecorator(Note, Note.schema, Note.VALIDATION_ERROR_MESSAGES); module.exports = { Note }; diff --git a/shared/src/business/entities/notes/UserCaseNote.js b/shared/src/business/entities/notes/UserCaseNote.js index c63d1d6c126..030608442b7 100644 --- a/shared/src/business/entities/notes/UserCaseNote.js +++ b/shared/src/business/entities/notes/UserCaseNote.js @@ -12,6 +12,8 @@ UserCaseNote.validationName = 'UserCaseNote'; * @constructor */ function UserCaseNote(rawProps) { + this.entityName = 'UserCaseNote'; + this.caseId = rawProps.caseId; this.userId = rawProps.userId; this.notes = rawProps.notes; @@ -28,6 +30,7 @@ UserCaseNote.schema = joi.object().keys({ version: ['uuidv4'], }) .required(), + entityName: joi.string().valid('UserCaseNote').required(), notes: joi.string().required(), userId: joi .string() @@ -40,7 +43,6 @@ UserCaseNote.schema = joi.object().keys({ joiValidationDecorator( UserCaseNote, UserCaseNote.schema, - undefined, UserCaseNote.VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/orders/Order.js b/shared/src/business/entities/orders/Order.js index 7c718a76c30..4f1c71a001c 100644 --- a/shared/src/business/entities/orders/Order.js +++ b/shared/src/business/entities/orders/Order.js @@ -69,9 +69,6 @@ joiValidationDecorator( eventCode: joi.string().optional(), orderBody: joi.string().required(), }), - function () { - return !this.getFormattedValidationErrors(); - }, Order.VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/orders/OrderSearch.js b/shared/src/business/entities/orders/OrderSearch.js index 1d777bf5ebe..35dec362ec2 100644 --- a/shared/src/business/entities/orders/OrderSearch.js +++ b/shared/src/business/entities/orders/OrderSearch.js @@ -1,7 +1,14 @@ const joi = require('@hapi/joi'); +const { + createEndOfDayISO, + createStartOfDayISO, +} = require('../../utilities/DateHandler'); const { joiValidationDecorator, } = require('../../../utilities/JoiValidationDecorator'); +const { getTimestampSchema } = require('../../../utilities/dateSchema'); +const { isEmpty } = require('lodash'); +const joiStrictTimestamp = getTimestampSchema(); OrderSearch.ORDER_SEARCH_PAGE_LOAD_SIZE = 6; @@ -14,30 +21,113 @@ OrderSearch.validationName = 'OrderSearch'; * @constructor */ function OrderSearch(rawProps = {}) { + if (!isEmpty(rawProps.judge)) { + this.judge = rawProps.judge; + } + this.orderKeyword = rawProps.orderKeyword; - this.docketNumber = rawProps.docketNumber; - this.caseTitleOrPetitioner = rawProps.caseTitleOrPetitioner; + + if (!isEmpty(rawProps.docketNumber)) { + this.docketNumber = rawProps.docketNumber; + } + + if ( + rawProps.startDateDay || + rawProps.startDateMonth || + rawProps.startDateYear + ) { + this.startDate = createStartOfDayISO({ + day: rawProps.startDateDay, + month: rawProps.startDateMonth, + year: rawProps.startDateYear, + }); + } + + if (rawProps.endDateDay || rawProps.endDateMonth || rawProps.endDateYear) { + this.endDate = createEndOfDayISO({ + day: rawProps.endDateDay, + month: rawProps.endDateMonth, + year: rawProps.endDateYear, + }); + + this.tomorrow = new Date(); + this.tomorrow.setDate(this.tomorrow.getDate() + 1); + } + + if (!isEmpty(rawProps.caseTitleOrPetitioner)) { + this.caseTitleOrPetitioner = rawProps.caseTitleOrPetitioner; + } } OrderSearch.VALIDATION_ERROR_MESSAGES = { chooseOneValue: 'Enter either a Docket number or a Case name/Petitioner name, not both', + endDate: 'Enter a valid end date', orderKeyword: 'Enter a keyword or phrase', + startDate: 'Enter a valid start date', }; OrderSearch.schema = joi .object() .keys({ - caseTitleOrPetitioner: joi.string().empty(''), - docketNumber: joi.string().empty(''), - orderKeyword: joi.string().required(), + caseTitleOrPetitioner: joi + .string() + .description( + 'The case title or petitioner name to filter the search results by', + ), + docketNumber: joi + .string() + .description('The docket number to filter the search results by'), + endDate: joi.alternatives().conditional('startDate', { + is: joi.exist().not(null), + otherwise: joiStrictTimestamp + .less(joi.ref('tomorrow')) + .optional() + .description( + 'The end date search filter is not required if there is no start date', + ), + then: joiStrictTimestamp + .min(joi.ref('startDate')) + .less(joi.ref('tomorrow')) + .optional() + .description( + 'The end date search filter must be greater than or equal to the start date, and less than or equal to the current date', + ), + }), + judge: joi + .string() + .optional() + .description('The name of the judge to filter the search results by'), + orderKeyword: joi + .string() + .required() + .description('The only required field to filter the search by'), + startDate: joi.alternatives().conditional('endDate', { + is: joi.exist().not(null), + otherwise: joiStrictTimestamp + .max('now') + .optional() + .description( + 'The start date to search by, which cannot be greater than the current date, and is optional when there is no end date provided', + ), + then: joiStrictTimestamp + .max('now') + .required() + .description( + 'The start date to search by, which cannot be greater than the current date, and is required when there is an end date provided', + ), + }), + tomorrow: joi + .optional() + .description( + 'The computed value to validate the endDate against, in order to verify that the endDate is less than or equal to the current date', + ), }) .oxor('caseTitleOrPetitioner', 'docketNumber'); joiValidationDecorator( OrderSearch, OrderSearch.schema, - undefined, OrderSearch.VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/orders/OrderSearch.test.js b/shared/src/business/entities/orders/OrderSearch.test.js index 1e67de50931..32f9224339c 100644 --- a/shared/src/business/entities/orders/OrderSearch.test.js +++ b/shared/src/business/entities/orders/OrderSearch.test.js @@ -32,4 +32,126 @@ describe('Order Search entity', () => { errorMessages.chooseOneValue, ); }); + + it('should pass validation when judge provided is empty', () => { + const orderSearch = new OrderSearch({ + judge: '', + orderKeyword: 'sunglasses', + }); + + const validationErrors = orderSearch.getFormattedValidationErrors(); + + expect(orderSearch.judge).toBeUndefined(); + expect(validationErrors).toBeNull(); + }); + + describe('date search validation', () => { + it('should not validate end date and start date when no date range is provided', () => { + const orderSearch = new OrderSearch({ + orderKeyword: 'sunglasses', + }); + + const validationErrors = orderSearch.getFormattedValidationErrors(); + + expect(validationErrors).toBeNull(); + }); + + it('should fail validation when the start date is greater than the end date', () => { + const orderSearch = new OrderSearch({ + endDateDay: '2', + endDateMonth: '10', + endDateYear: '2020', + orderKeyword: 'sunglasses', + startDateDay: '10', + startDateMonth: '10', + startDateYear: '2020', + }); + + const validationErrors = orderSearch.getFormattedValidationErrors(); + + expect(validationErrors.endDate).toEqual('Enter a valid end date'); + }); + + it('should pass validation when a start date is provided without an end date', () => { + const orderSearch = new OrderSearch({ + orderKeyword: 'sunglasses', + startDateDay: '2', + startDateMonth: '2', + startDateYear: '2020', + }); + + const validationErrors = orderSearch.getFormattedValidationErrors(); + + expect(validationErrors).toBeNull(); + }); + + it('should fail validation when an end date is provided without a start date', () => { + const orderSearch = new OrderSearch({ + endDateDay: '02', + endDateMonth: '10', + endDateYear: '2020', + orderKeyword: 'sunglasses', + }); + + const validationErrors = orderSearch.getFormattedValidationErrors(); + + expect(validationErrors.startDate).toEqual('Enter a valid start date'); + }); + + it('should fail validation when the end date year is not provided', () => { + const orderSearch = new OrderSearch({ + endDateDay: '12', + endDateMonth: '10', + orderKeyword: 'sunglasses', + startDateDay: '10', + startDateMonth: '10', + startDateYear: '2020', + }); + + const validationErrors = orderSearch.getFormattedValidationErrors(); + + expect(validationErrors.endDate).toEqual('Enter a valid end date'); + }); + + it('should fail validation when the start date year is not provided', () => { + const orderSearch = new OrderSearch({ + orderKeyword: 'sunglasses', + startDateDay: '10', + startDateMonth: '10', + }); + + const validationErrors = orderSearch.getFormattedValidationErrors(); + + expect(validationErrors.startDate).toEqual('Enter a valid start date'); + }); + + it('should fail validation when the start date is in the future', () => { + const orderSearch = new OrderSearch({ + orderKeyword: 'sunglasses', + startDateDay: '10', + startDateMonth: '10', + startDateYear: '3000', + }); + + const validationErrors = orderSearch.getFormattedValidationErrors(); + + expect(validationErrors.startDate).toEqual('Enter a valid start date'); + }); + + it('should fail validation when the end date is in the future', () => { + const orderSearch = new OrderSearch({ + endDateDay: '20', + endDateMonth: '20', + endDateYear: '3000', + orderKeyword: 'sunglasses', + startDateDay: '10', + startDateMonth: '10', + startDateYear: '2000', + }); + + const validationErrors = orderSearch.getFormattedValidationErrors(); + + expect(validationErrors.endDate).toEqual('Enter a valid end date'); + }); + }); }); diff --git a/shared/src/business/entities/orders/OrderWithoutBody.js b/shared/src/business/entities/orders/OrderWithoutBody.js index e89e389f160..c2077901ae8 100644 --- a/shared/src/business/entities/orders/OrderWithoutBody.js +++ b/shared/src/business/entities/orders/OrderWithoutBody.js @@ -25,9 +25,6 @@ joiValidationDecorator( documentType: joi.string().required(), eventCode: joi.string().required(), }), - function () { - return !this.getFormattedValidationErrors(); - }, OrderWithoutBody.VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/trialSessions/NewTrialSession.js b/shared/src/business/entities/trialSessions/NewTrialSession.js index 28518f1c2f3..8befb8dcd9f 100644 --- a/shared/src/business/entities/trialSessions/NewTrialSession.js +++ b/shared/src/business/entities/trialSessions/NewTrialSession.js @@ -2,8 +2,11 @@ const joi = require('@hapi/joi'); const { joiValidationDecorator, } = require('../../../utilities/JoiValidationDecorator'); +const { getTimestampSchema } = require('../../../utilities/dateSchema'); const { TrialSession } = require('./TrialSession'); +const joiStrictTimestamp = getTimestampSchema(); + NewTrialSession.validationName = 'TrialSession'; /** @@ -24,11 +27,8 @@ joiValidationDecorator( NewTrialSession, joi.object().keys({ ...TrialSession.validationRules.COMMON, - startDate: joi.date().iso().min('now').required(), + startDate: joiStrictTimestamp.min('now').required(), }), - function () { - return !this.getFormattedValidationErrors(); - }, NewTrialSession.VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/trialSessions/TrialSession.js b/shared/src/business/entities/trialSessions/TrialSession.js index f2032aaad0c..da850ffbfe6 100644 --- a/shared/src/business/entities/trialSessions/TrialSession.js +++ b/shared/src/business/entities/trialSessions/TrialSession.js @@ -6,8 +6,11 @@ const { joiValidationDecorator, } = require('../../../utilities/JoiValidationDecorator'); const { createISODateString } = require('../../utilities/DateHandler'); +const { getTimestampSchema } = require('../../../utilities/dateSchema'); const { isEmpty } = require('lodash'); +const joiStrictTimestamp = getTimestampSchema(); + const COMMON_CITIES = [ { city: 'Birmingham', state: 'Alabama' }, { city: 'Mobile', state: 'Alabama' }, @@ -140,6 +143,8 @@ TrialSession.prototype.init = function (rawSession, { applicationContext }) { if (!applicationContext) { throw new TypeError('applicationContext must be defined'); } + this.entityName = 'TrialSession'; + this.address1 = rawSession.address1; this.address2 = rawSession.address2; this.caseOrder = (rawSession.caseOrder || []).map(caseOrder => ({ @@ -204,19 +209,20 @@ TrialSession.validationRules = { city: joi.string().allow('').optional(), courtReporter: joi.string().optional(), courthouseName: joi.string().allow('').optional(), - createdAt: joi.date().iso().optional(), + createdAt: joiStrictTimestamp.optional(), + entityName: joi.string().valid('TrialSession').required(), irsCalendarAdministrator: joi.string().optional(), isCalendared: joi.boolean().required(), judge: joi.object().optional(), maxCases: joi.number().greater(0).integer().required(), notes: joi.string().max(400).optional(), - noticeIssuedDate: joi.date().iso().optional(), + noticeIssuedDate: joiStrictTimestamp.optional(), postalCode: JoiValidationConstants.US_POSTAL_CODE.optional(), sessionType: joi .string() .valid(...TrialSession.SESSION_TYPES) .required(), - startDate: joi.date().iso().required(), + startDate: joiStrictTimestamp.required(), startTime: JoiValidationConstants.TWENTYFOUR_HOUR_MINUTES, state: joi.string().allow('').optional(), swingSession: joi.boolean().optional(), @@ -265,15 +271,12 @@ joiValidationDecorator( removedFromTrialDate: joi.when('removedFromTrial', { is: true, otherwise: joi.optional().allow(null), - then: joi.date().iso().required(), + then: joiStrictTimestamp.required(), }), }), ), isCalendared: joi.boolean().required(), }), - function () { - return !this.getFormattedValidationErrors(); - }, TrialSession.VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/entities/trialSessions/TrialSessionWorkingCopy.js b/shared/src/business/entities/trialSessions/TrialSessionWorkingCopy.js index 84b7eb353cf..411a46ba18c 100644 --- a/shared/src/business/entities/trialSessions/TrialSessionWorkingCopy.js +++ b/shared/src/business/entities/trialSessions/TrialSessionWorkingCopy.js @@ -28,6 +28,8 @@ function TrialSessionWorkingCopy(rawSession) { } TrialSessionWorkingCopy.prototype.init = function (rawSession) { + this.entityName = 'TrialSessionWorkingCopy'; + this.caseMetadata = rawSession.caseMetadata || {}; this.filters = rawSession.filters || { aBasisReached: true, @@ -60,6 +62,7 @@ TrialSessionWorkingCopy.validationRules = { }), ) .optional(), + entityName: joi.string().valid('TrialSessionWorkingCopy').required(), filters: joi .object() .keys({ @@ -95,9 +98,6 @@ TrialSessionWorkingCopy.validationRules = { joiValidationDecorator( TrialSessionWorkingCopy, joi.object().keys(TrialSessionWorkingCopy.validationRules), - function () { - return !this.getFormattedValidationErrors(); - }, TrialSessionWorkingCopy.VALIDATION_ERROR_MESSAGES, ); diff --git a/shared/src/business/test/createTestApplicationContext.js b/shared/src/business/test/createTestApplicationContext.js index 9f3b3fba4f4..d6b1ae6bf4b 100644 --- a/shared/src/business/test/createTestApplicationContext.js +++ b/shared/src/business/test/createTestApplicationContext.js @@ -8,23 +8,10 @@ const { const { appendPaperServiceAddressPageToPdf, } = require('../useCaseHelper/service/appendPaperServiceAddressPageToPdf'); -const { - CaseAssociationRequestFactory, -} = require('../entities/CaseAssociationRequestFactory'); -const { - CaseExternalIncomplete, -} = require('../entities/cases/CaseExternalIncomplete'); const { compareISODateStrings, compareStrings, } = require('../utilities/sortFunctions'); -const { - CourtIssuedDocumentFactory, -} = require('../entities/courtIssuedDocument/CourtIssuedDocumentFactory'); -const { - formattedTrialSessionDetails, -} = require('../utilities/getFormattedTrialSessionDetails'); - const { createDocketNumber, } = require('../../persistence/dynamo/cases/docketNumberGenerator'); @@ -46,12 +33,12 @@ const { const { deleteWorkItemFromInbox, } = require('../../persistence/dynamo/workitems/deleteWorkItemFromInbox'); -const { - ExternalDocumentFactory, -} = require('../entities/externalDocument/ExternalDocumentFactory'); const { formatDocument, } = require('../../../src/business/utilities/getFormattedCaseDetail'); +const { + formattedTrialSessionDetails, +} = require('../utilities/getFormattedTrialSessionDetails'); const { getCaseByCaseId, } = require('../../persistence/dynamo/cases/getCaseByCaseId'); @@ -113,20 +100,25 @@ const { verifyCaseForUser, } = require('../../persistence/dynamo/cases/verifyCaseForUser'); const { Case } = require('../entities/cases/Case'); -const { CaseInternal } = require('../entities/cases/CaseInternal'); const { createCase } = require('../../persistence/dynamo/cases/createCase'); const { createMockDocumentClient } = require('./createMockDocumentClient'); -const { DocketRecord } = require('../entities/DocketRecord'); -const { Document } = require('../entities/Document'); const { filterEmptyStrings } = require('../utilities/filterEmptyStrings'); const { getConstants } = require('../../../../web-client/src/getConstants'); const { getItem } = require('../../persistence/localStorage/getItem'); const { removeItem } = require('../../persistence/localStorage/removeItem'); const { setItem } = require('../../persistence/localStorage/setItem'); -const { TrialSession } = require('../entities/trialSessions/TrialSession'); const { updateCase } = require('../../persistence/dynamo/cases/updateCase'); const { User } = require('../entities/User'); -const { WorkItem } = require('../entities/WorkItem'); + +const fakeData = + 'JVBERi0xLjEKJcKlwrHDqwoKMSAwIG9iagogIDw8IC9UeXBlIC9DYXRhbG9nCiAgICAgL1BhZ2VzIDIgMCBSCiAgPj4KZW5kb2JqCgoyIDAgb2JqCiAgPDwgL1R5cGUgL1BhZ2VzCiAgICAgL0tpZHMgWzMgMCBSXQogICAgIC9Db3VudCAxCiAgICAgL01lZGlhQm94IFswIDAgMzAwIDE0NF0KICA+PgplbmRvYmoKCjMgMCBvYmoKICA8PCAgL1R5cGUgL1BhZ2UKICAgICAgL1BhcmVudCAyIDAgUgogICAgICAvUmVzb3VyY2VzCiAgICAgICA8PCAvRm9udAogICAgICAgICAgIDw8IC9GMQogICAgICAgICAgICAgICA8PCAvVHlwZSAvRm9udAogICAgICAgICAgICAgICAgICAvU3VidHlwZSAvVHlwZTEKICAgICAgICAgICAgICAgICAgL0Jhc2VGb250IC9UaW1lcy1Sb21hbgogICAgICAgICAgICAgICA+PgogICAgICAgICAgID4+CiAgICAgICA+PgogICAgICAvQ29udGVudHMgNCAwIFIKICA+PgplbmRvYmoKCjQgMCBvYmoKICA8PCAvTGVuZ3RoIDg0ID4+CnN0cmVhbQogIEJUCiAgICAvRjEgMTggVGYKICAgIDUgODAgVGQKICAgIChDb25ncmF0aW9ucywgeW91IGZvdW5kIHRoZSBFYXN0ZXIgRWdnLikgVGoKICBFVAplbmRzdHJlYW0KZW5kb2JqCgp4cmVmCjAgNQowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAwMTggMDAwMDAgbiAKMDAwMDAwMDA3NyAwMDAwMCBuIAowMDAwMDAwMTc4IDAwMDAwIG4gCjAwMDAwMDA0NTcgMDAwMDAgbiAKdHJhaWxlcgogIDw8ICAvUm9vdCAxIDAgUgogICAgICAvU2l6ZSA1CiAgPj4Kc3RhcnR4cmVmCjU2NQolJUVPRgo='; + +// TODO: Abstract for use elsewhere +const getFakeFile = () => { + const fakeFile = Buffer.from(fakeData, 'base64'); + fakeFile.name = 'fakeFile.pdf'; + return fakeFile; +}; const scannerResourcePath = path.join(__dirname, '../../../shared/test-assets'); @@ -191,6 +183,7 @@ const createTestApplicationContext = ({ user } = {}) => { .fn() .mockImplementation(formattedTrialSessionDetails), getAddressPhoneDiff: jest.fn().mockImplementation(getAddressPhoneDiff), + getCaseCaption: jest.fn().mockImplementation(Case.getCaseCaption), getFilingsAndProceedings: jest.fn().mockReturnValue(''), getFormattedCaseDetail: jest .fn() @@ -228,6 +221,12 @@ const createTestApplicationContext = ({ user } = {}) => { .mockImplementation(updateCaseAutomaticBlock), }); + const getDocumentGeneratorsReturnMock = { + changeOfAddress: jest.fn().mockImplementation(getFakeFile), + docketRecord: jest.fn().mockImplementation(getFakeFile), + standingPretrialOrder: jest.fn().mockImplementation(getFakeFile), + }; + const getTemplateGeneratorsReturnMock = { generateChangeOfAddressTemplate: jest.fn().mockResolvedValue('
'), generateHTMLTemplateForPDF: jest.fn().mockReturnValue('
'), @@ -282,6 +281,7 @@ const createTestApplicationContext = ({ user } = {}) => { getDocumentQCServedForSection: jest .fn() .mockImplementation(getDocumentQCInboxForSectionPersistence), + getDownloadPolicyUrl: jest.fn(), getElasticsearchReindexRecords: jest.fn(), getInboxMessagesForSection: jest .fn() @@ -299,6 +299,7 @@ const createTestApplicationContext = ({ user } = {}) => { incrementCounter, putWorkItemInOutbox: jest.fn().mockImplementation(putWorkItemInOutbox), removeItem: jest.fn().mockImplementation(removeItem), + saveDocumentFromLambda: jest.fn(), saveWorkItemForNonPaper: jest .fn() .mockImplementation(saveWorkItemForNonPaper), @@ -344,7 +345,7 @@ const createTestApplicationContext = ({ user } = {}) => { }, filterCaseMetadata: jest.fn(), getBaseUrl: () => 'http://localhost', - getCaseCaptionNames: jest.fn().mockImplementation(Case.getCaseCaptionNames), + getCaseTitle: jest.fn().mockImplementation(Case.getCaseTitle), getChiefJudgeNameForSigning: jest.fn(), getChromiumBrowser: jest.fn().mockImplementation(() => { return mockGetChromiumBrowserReturnValue; @@ -372,22 +373,13 @@ const createTestApplicationContext = ({ user } = {}) => { sendBulkTemplatedEmail: jest.fn(), }), getDocumentClient: jest.fn().mockImplementation(() => mockDocumentClient), + getDocumentGenerators: jest + .fn() + .mockReturnValue(getDocumentGeneratorsReturnMock), getDocumentsBucketName: jest.fn().mockReturnValue('DocumentBucketName'), + getElasticsearchIndexes: () => ['efcms-case'], getEmailClient: jest.fn().mockReturnValue(mockGetEmailClient), getEntityByName: jest.fn(), - getEntityConstructors: () => ({ - Case, - CaseAssociationRequestFactory, - CaseExternal: CaseExternalIncomplete, - CaseInternal: CaseInternal, - CourtIssuedDocumentFactory, - DocketRecord, - Document, - ExternalDocumentFactory: ExternalDocumentFactory, - TrialSession: TrialSession, - User, - WorkItem: WorkItem, - }), getFileReaderInstance: jest.fn(), getHttpClient: jest.fn().mockReturnValue(mockGetHttpClientReturnValue), getNodeSass: jest.fn().mockReturnValue(nodeSassMockReturnValue), @@ -396,7 +388,11 @@ const createTestApplicationContext = ({ user } = {}) => { getPdfJs: jest.fn().mockReturnValue(mockGetPdfJsReturnValue), getPdfStyles: jest.fn(), getPersistenceGateway: mockGetPersistenceGateway, - getPug: jest.fn(), + getPug: jest.fn(() => ({ + compile: () => { + return () => null; + }, + })), getScanner: jest.fn().mockReturnValue(mockGetScannerReturnValue), getScannerResourceUri: jest.fn().mockReturnValue(scannerResourcePath), getSearchClient: appContextProxy(), @@ -417,6 +413,7 @@ const createTestApplicationContext = ({ user } = {}) => { time: () => jest.fn().mockReturnValue(null), timeEnd: () => jest.fn().mockReturnValue(null), }, + notifyHoneybadger: jest.fn(), setCurrentUser: jest.fn(), setCurrentUserToken: jest.fn(), }; diff --git a/shared/src/business/useCaseHelper/caseAssociation/associateIrsPractitionerToCase.test.js b/shared/src/business/useCaseHelper/caseAssociation/associateIrsPractitionerToCase.test.js index baeb07c05c9..94f12b5abf3 100644 --- a/shared/src/business/useCaseHelper/caseAssociation/associateIrsPractitionerToCase.test.js +++ b/shared/src/business/useCaseHelper/caseAssociation/associateIrsPractitionerToCase.test.js @@ -16,6 +16,16 @@ describe('associateIrsPractitionerToCase', () => { caseCaption: 'Caption', caseId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', caseType: 'Deficiency', + contactPrimary: { + address1: '123 Main St', + city: 'Somewhere', + countryType: 'domestic', + email: 'fieri@example.com', + name: 'Guy Fieri', + phone: '1234567890', + postalCode: '12345', + state: 'CA', + }, docketNumber: '123-19', docketRecord: [ { diff --git a/shared/src/business/useCaseHelper/caseInventoryReport/caseInventoryReport.pug b/shared/src/business/useCaseHelper/caseInventoryReport/caseInventoryReport.pug index e8a415969e1..1d48330b1d1 100644 --- a/shared/src/business/useCaseHelper/caseInventoryReport/caseInventoryReport.pug +++ b/shared/src/business/useCaseHelper/caseInventoryReport/caseInventoryReport.pug @@ -24,7 +24,7 @@ html(lang="en") each formattedCase in formattedCases tr td.no-wrap #{formattedCase.docketNumber}#{formattedCase.docketNumberSuffix} - td= formattedCase.caseCaptionNames + td= formattedCase.caseTitle if showStatusColumn td= formattedCase.status if showJudgeColumn diff --git a/shared/src/business/useCaseHelper/caseInventoryReport/generateCaseInventoryReportPdf.js b/shared/src/business/useCaseHelper/caseInventoryReport/generateCaseInventoryReportPdf.js index efeead9595e..976bbd163e4 100644 --- a/shared/src/business/useCaseHelper/caseInventoryReport/generateCaseInventoryReportPdf.js +++ b/shared/src/business/useCaseHelper/caseInventoryReport/generateCaseInventoryReportPdf.js @@ -64,9 +64,7 @@ exports.generateCaseInventoryReportPdf = async ({ .sort(applicationContext.getUtilities().compareCasesByDocketNumber) .map(caseItem => ({ ...caseItem, - caseCaptionNames: applicationContext.getCaseCaptionNames( - caseItem.caseCaption || '', - ), + caseTitle: applicationContext.getCaseTitle(caseItem.caseCaption || ''), })); let reportTitle = ''; diff --git a/shared/src/business/useCaseHelper/countPagesInDocument.js b/shared/src/business/useCaseHelper/countPagesInDocument.js new file mode 100644 index 00000000000..58db3cba61f --- /dev/null +++ b/shared/src/business/useCaseHelper/countPagesInDocument.js @@ -0,0 +1,12 @@ +const { PDFDocument } = require('pdf-lib'); + +exports.countPagesInDocument = async ({ applicationContext, documentId }) => { + const bytes = await applicationContext.getPersistenceGateway().getDocument({ + applicationContext, + documentId, + protocol: 'S3', + useTempBucket: false, + }); + const pdfDoc = await PDFDocument.load(bytes); + return pdfDoc.getPages().length; +}; diff --git a/shared/src/business/useCaseHelper/pendingReport/generatePendingReportPdf.js b/shared/src/business/useCaseHelper/pendingReport/generatePendingReportPdf.js index cd2542f78a7..f69479bca08 100644 --- a/shared/src/business/useCaseHelper/pendingReport/generatePendingReportPdf.js +++ b/shared/src/business/useCaseHelper/pendingReport/generatePendingReportPdf.js @@ -62,9 +62,7 @@ exports.generatePendingReportPdf = async ({ /^Judge\s+/, '', ), - caseCaptionNames: applicationContext.getCaseCaptionNames( - pendingItem.caseCaption || '', - ), + caseTitle: applicationContext.getCaseTitle(pendingItem.caseCaption || ''), formattedFiledDate: applicationContext .getUtilities() .formatDateString(pendingItem.receivedAt, 'MMDDYY'), diff --git a/shared/src/business/useCaseHelper/pendingReport/generatePendingReportPdf.test.js b/shared/src/business/useCaseHelper/pendingReport/generatePendingReportPdf.test.js index dc5bea3c2fa..85815c5f529 100644 --- a/shared/src/business/useCaseHelper/pendingReport/generatePendingReportPdf.test.js +++ b/shared/src/business/useCaseHelper/pendingReport/generatePendingReportPdf.test.js @@ -47,9 +47,9 @@ const mockPendingItems = [ { assigneeId: '1805d1ab-18d0-43ec-bafb-654e83405416', assigneeName: 'Test Docketclerk', - caseCaptionNames: 'Brett Osborne', caseId: '2fa6da8d-4328-4a20-a5d7-b76637e1dc02', caseStatus: 'New', + caseTitle: 'Brett Osborne', completedAt: '2019-11-13T00:38:59.049Z', completedBy: 'Test Docketclerk', completedByUserId: '1805d1ab-18d0-43ec-bafb-654e83405416', @@ -132,9 +132,9 @@ const mockPendingItems = [ { assigneeId: '1805d1ab-18d0-43ec-bafb-654e83405416', assigneeName: 'Test Docketclerk', - caseCaptionNames: 'Brett Osborne', caseId: '2fa6da8d-4328-4a20-a5d7-b76637e1dc02', caseStatus: 'New', + caseTitle: 'Brett Osborne', completedAt: '2019-11-13T02:27:07.801Z', completedBy: 'Test Docketclerk', completedByUserId: '1805d1ab-18d0-43ec-bafb-654e83405416', @@ -214,7 +214,7 @@ describe('generatePendingReportPdf', () => { environment: { tempDocumentsBucketName: 'MockDocumentBucketName', }, - getCaseCaptionNames: Case.getCaseCaptionNames, + getCaseTitle: Case.getCaseTitle, getChromiumBrowser: () => { throw new Error('bad!'); }, @@ -257,7 +257,7 @@ describe('generatePendingReportPdf', () => { environment: { tempDocumentsBucketName: 'MockDocumentBucketName', }, - getCaseCaptionNames: Case.getCaseCaptionNames, + getCaseTitle: Case.getCaseTitle, getChromiumBrowser: () => chromiumBrowserMock, getCurrentUser: () => { return { role: User.ROLES.petitionsClerk, userId: 'petitionsClerk' }; @@ -299,7 +299,7 @@ describe('generatePendingReportPdf', () => { environment: { tempDocumentsBucketName: 'MockDocumentBucketName', }, - getCaseCaptionNames: Case.getCaseCaptionNames, + getCaseTitle: Case.getCaseTitle, getChromiumBrowser: () => { throw new Error('bad!'); }, diff --git a/shared/src/business/useCaseHelper/pendingReport/pendingReport.pug b/shared/src/business/useCaseHelper/pendingReport/pendingReport.pug index fb351c86950..55e9721db30 100644 --- a/shared/src/business/useCaseHelper/pendingReport/pendingReport.pug +++ b/shared/src/business/useCaseHelper/pendingReport/pendingReport.pug @@ -24,7 +24,7 @@ html(lang="en") tr td.no-wrap #{pendingItem.docketNumber}#{pendingItem.docketNumberSuffix} td= pendingItem.formattedFiledDate - td= pendingItem.caseCaptionNames + td= pendingItem.caseTitle td= pendingItem.formattedName td= pendingItem.caseStatus td= pendingItem.associatedJudgeFormatted diff --git a/shared/src/business/useCaseHelper/saveFileAndGenerateUrl.js b/shared/src/business/useCaseHelper/saveFileAndGenerateUrl.js new file mode 100644 index 00000000000..72634dedc0e --- /dev/null +++ b/shared/src/business/useCaseHelper/saveFileAndGenerateUrl.js @@ -0,0 +1,28 @@ +/** + * + * Save provided file to temp s3 bucket and return file url + * + * @param {object} providers the providers object + * @param {object} providers.applicationContext the application context + * @param {string} providers.file the file to save + * @returns {string} the url to the file + */ +exports.saveFileAndGenerateUrl = async ({ applicationContext, file }) => { + const fileId = applicationContext.getUniqueId(); + + await applicationContext.getPersistenceGateway().saveDocumentFromLambda({ + applicationContext, + document: file, + documentId: fileId, + useTempBucket: true, + }); + + const { + url, + } = await applicationContext.getPersistenceGateway().getDownloadPolicyUrl({ + applicationContext, + documentId: fileId, + useTempBucket: true, + }); + return { fileId, url }; +}; diff --git a/shared/src/business/useCaseHelper/saveFileAndGenerateUrl.test.js b/shared/src/business/useCaseHelper/saveFileAndGenerateUrl.test.js new file mode 100644 index 00000000000..bf50acf477e --- /dev/null +++ b/shared/src/business/useCaseHelper/saveFileAndGenerateUrl.test.js @@ -0,0 +1,27 @@ +const { applicationContext } = require('../test/createTestApplicationContext'); +const { saveFileAndGenerateUrl } = require('./saveFileAndGenerateUrl'); + +describe('saveFileAndGenerateUrl', () => { + it('saves the file to s3 and returns the file ID and url to the file', async () => { + const mockUUID = '12345'; + const mockPdfUrlAndId = { fileId: mockUUID, url: 'www.example.com' }; + applicationContext + .getPersistenceGateway() + .getDownloadPolicyUrl.mockReturnValue(mockPdfUrlAndId); + applicationContext.getUniqueId.mockReturnValue(mockUUID); + + const result = await saveFileAndGenerateUrl({ + applicationContext, + file: '', + }); + + expect(applicationContext.getUniqueId).toBeCalled(); + expect( + applicationContext.getPersistenceGateway().saveDocumentFromLambda, + ).toBeCalled(); + expect( + applicationContext.getPersistenceGateway().getDownloadPolicyUrl, + ).toBeCalled(); + expect(result).toEqual(mockPdfUrlAndId); + }); +}); diff --git a/shared/src/business/useCaseHelper/standingPretrialNotice/generateStandingPretrialNoticeTemplate.js b/shared/src/business/useCaseHelper/standingPretrialNotice/generateStandingPretrialNoticeTemplate.js index 3c533219540..d8c65c70052 100644 --- a/shared/src/business/useCaseHelper/standingPretrialNotice/generateStandingPretrialNoticeTemplate.js +++ b/shared/src/business/useCaseHelper/standingPretrialNotice/generateStandingPretrialNoticeTemplate.js @@ -36,11 +36,11 @@ const generateStandingPretrialNoticeTemplate = async ({ ); trialInfo.startDate = formatDateString(trialInfo.startDate, 'MMDDYYYY'); - let caseName = Case.getCaseCaptionNames(caseCaption); + let caseTitle = Case.getCaseTitle(caseCaption); let caseCaptionExtension = ''; - if (caseName !== caseCaption) { - caseName += ', '; - caseCaptionExtension = caseCaption.replace(caseName, ''); + if (caseTitle !== caseCaption) { + caseTitle += ', '; + caseCaptionExtension = caseCaption.replace(caseTitle, ''); } let respondentContactText = 'not available at this time'; @@ -53,7 +53,7 @@ const generateStandingPretrialNoticeTemplate = async ({ const compiledFunction = pug.compile(template); const main = compiledFunction({ caseCaptionExtension, - caseName, + caseTitle, docketNumberWithSuffix, footerDate, headerDate, diff --git a/shared/src/business/useCaseHelper/standingPretrialNotice/standingPretrialNotice.pug b/shared/src/business/useCaseHelper/standingPretrialNotice/standingPretrialNotice.pug index 1feb8612db7..cd8f5bc25cb 100644 --- a/shared/src/business/useCaseHelper/standingPretrialNotice/standingPretrialNotice.pug +++ b/shared/src/business/useCaseHelper/standingPretrialNotice/standingPretrialNotice.pug @@ -32,7 +32,7 @@ mixin case-info-box .case-information #case-caption - p #{caseName} + p #{caseTitle} p.space #{caseCaptionExtension} .clear #caption diff --git a/shared/src/business/useCaseHelper/standingPretrialOrder/generateStandingPretrialOrderTemplate.js b/shared/src/business/useCaseHelper/standingPretrialOrder/generateStandingPretrialOrderTemplate.js index 58e7e518fba..ec7068e728e 100644 --- a/shared/src/business/useCaseHelper/standingPretrialOrder/generateStandingPretrialOrderTemplate.js +++ b/shared/src/business/useCaseHelper/standingPretrialOrder/generateStandingPretrialOrderTemplate.js @@ -35,17 +35,17 @@ const generateStandingPretrialOrderTemplate = async ({ ); trialInfo.startDate = formatDateString(trialInfo.startDate, 'MMDDYYYY'); - let caseName = Case.getCaseCaptionNames(caseCaption); + let caseTitle = Case.getCaseTitle(caseCaption); let caseCaptionExtension = ''; - if (caseName !== caseCaption) { - caseName += ', '; - caseCaptionExtension = caseCaption.replace(caseName, ''); + if (caseTitle !== caseCaption) { + caseTitle += ', '; + caseCaptionExtension = caseCaption.replace(caseTitle, ''); } const compiledFunction = pug.compile(template); const main = compiledFunction({ caseCaptionExtension, - caseName, + caseTitle, docketNumberWithSuffix, footerDate, headerDate, diff --git a/shared/src/business/useCaseHelper/standingPretrialOrder/standingPretrialOrder.pug b/shared/src/business/useCaseHelper/standingPretrialOrder/standingPretrialOrder.pug index 38d4bb8a9de..3c844e83ecb 100644 --- a/shared/src/business/useCaseHelper/standingPretrialOrder/standingPretrialOrder.pug +++ b/shared/src/business/useCaseHelper/standingPretrialOrder/standingPretrialOrder.pug @@ -10,7 +10,7 @@ .case-information #case-caption - p #{caseName} + p #{caseTitle} p.space #{caseCaptionExtension} .clear #caption diff --git a/shared/src/business/useCases/addCoversheetInteractor.js b/shared/src/business/useCases/addCoversheetInteractor.js index ee56428fb31..5c2f288d1c0 100644 --- a/shared/src/business/useCases/addCoversheetInteractor.js +++ b/shared/src/business/useCases/addCoversheetInteractor.js @@ -1,9 +1,8 @@ -const { Case } = require('../entities/cases/Case'); -const { PDFDocument } = require('pdf-lib'); - const { generateCoverPagePdf, } = require('../utilities/generateHTMLTemplateForPDF/generateCoverPagePdf'); +const { Case } = require('../entities/cases/Case'); +const { PDFDocument } = require('pdf-lib'); /** * a helper function which assembles the correct data to be used in the generation of a PDF @@ -56,11 +55,11 @@ exports.generateCoverSheetData = ({ ''; const caseCaption = caseEntity.caseCaption || Case.getCaseCaption(caseEntity); - let caseCaptionNames = applicationContext.getCaseCaptionNames(caseCaption); + let caseTitle = applicationContext.getCaseTitle(caseCaption); let caseCaptionExtension = ''; - if (caseCaptionNames !== caseCaption) { - caseCaptionNames += ', '; - caseCaptionExtension = caseCaption.replace(caseCaptionNames, ''); + if (caseTitle !== caseCaption) { + caseTitle += ', '; + caseCaptionExtension = caseCaption.replace(caseTitle, ''); } let documentTitle = @@ -74,7 +73,7 @@ exports.generateCoverSheetData = ({ const coverSheetData = { caseCaptionExtension, - caseCaptionNames, + caseTitle, certificateOfService: documentEntity.certificateOfService === true ? 'Certificate of Service' @@ -130,7 +129,7 @@ exports.addCoverToPdf = async ({ pdfDoc.insertPage(0, coverPageDocumentPages[0]); - return pdfDoc.save(); + return await pdfDoc.save(); }; /** @@ -140,7 +139,6 @@ exports.addCoverToPdf = async ({ * @param {object} providers.applicationContext the application context * @param {string} providers.caseId the case id * @param {string} providers.documentId the document id - * @returns {Uint8Array} the new pdf data */ exports.addCoversheetInteractor = async ({ applicationContext, @@ -197,6 +195,4 @@ exports.addCoversheetInteractor = async ({ document: newPdfData, documentId, }); - - return newPdfData; }; diff --git a/shared/src/business/useCases/addCoversheetInteractor.test.js b/shared/src/business/useCases/addCoversheetInteractor.test.js index 77eae5dfda0..5e7169ee2ef 100644 --- a/shared/src/business/useCases/addCoversheetInteractor.test.js +++ b/shared/src/business/useCases/addCoversheetInteractor.test.js @@ -6,12 +6,14 @@ const { } = require('./addCoversheetInteractor.js'); const { applicationContext } = require('../test/createTestApplicationContext'); const { ContactFactory } = require('../entities/contacts/ContactFactory'); -const { getChromiumBrowser } = require('../utilities/getChromiumBrowser'); -const { PDFDocument } = require('pdf-lib'); + +jest.mock('../utilities/generateHTMLTemplateForPDF/generateCoverPagePdf'); +const { + generateCoverPagePdf, +} = require('../utilities/generateHTMLTemplateForPDF/generateCoverPagePdf'); describe('addCoversheetInteractor', () => { const testAssetsPath = path.join(__dirname, '../../../test-assets/'); - const testOutputPath = path.join(__dirname, '../../../test-output/'); const testPdfDocBytes = () => { // sample.pdf is a 1 page document @@ -73,15 +75,13 @@ describe('addCoversheetInteractor', () => { beforeAll(() => { jest.setTimeout(30000); + generateCoverPagePdf.mockImplementation(testPdfDocBytes); + applicationContext.getStorageClient().getObject.mockReturnValue({ promise: async () => ({ Body: testPdfDoc, }), }); - - applicationContext.getChromiumBrowser.mockImplementation( - async () => await getChromiumBrowser(), - ); }); it('adds a cover page to a pdf document', async () => { @@ -95,30 +95,17 @@ describe('addCoversheetInteractor', () => { documentId: 'a6b81f4d-1e47-423a-8caf-6d2fdc3d3859', }; - const newPdfData = await addCoversheetInteractor(params); - - const newPdfDoc = await PDFDocument.load(newPdfData); - const newPdfDocPages = newPdfDoc.getPages(); + await addCoversheetInteractor(params); expect( applicationContext.getPersistenceGateway().saveDocumentFromLambda, ).toHaveBeenCalled(); - expect(newPdfDocPages.length).toEqual(2); - expect(applicationContext.getChromiumBrowser).toHaveBeenCalled(); }); it('adds a cover page to a pdf document with optional data', async () => { applicationContext .getPersistenceGateway() .getCaseByCaseId.mockReturnValue(optionalTestingCaseData); - applicationContext - .getPersistenceGateway() - .saveDocumentFromLambda.mockImplementation(({ document: newPdfData }) => { - fs.writeFileSync( - testOutputPath + 'addCoverToPDFDocument_2.pdf', - newPdfData, - ); - }); const params = { applicationContext, @@ -126,14 +113,11 @@ describe('addCoversheetInteractor', () => { documentId: 'b6b81f4d-1e47-423a-8caf-6d2fdc3d3858', }; - const newPdfData = await addCoversheetInteractor(params); + await addCoversheetInteractor(params); - const newPdfDoc = await PDFDocument.load(newPdfData); - const newPdfDocPages = newPdfDoc.getPages(); expect( applicationContext.getPersistenceGateway().saveDocumentFromLambda, ).toHaveBeenCalled(); - expect(newPdfDocPages.length).toEqual(2); }); describe('coversheet data generator', () => { diff --git a/shared/src/business/useCases/caseAdvancedSearchInteractor.js b/shared/src/business/useCases/caseAdvancedSearchInteractor.js index 3e4a6a31cc0..6837c565db7 100644 --- a/shared/src/business/useCases/caseAdvancedSearchInteractor.js +++ b/shared/src/business/useCases/caseAdvancedSearchInteractor.js @@ -13,7 +13,11 @@ const { UnauthorizedError } = require('../../errors/errors'); */ exports.caseAdvancedSearchInteractor = async ({ applicationContext, - ...searchTerms + countryType, + petitionerName, + petitionerState, + yearFiledMax, + yearFiledMin, }) => { const authorizedUser = applicationContext.getCurrentUser(); @@ -23,7 +27,16 @@ exports.caseAdvancedSearchInteractor = async ({ let foundCases = await applicationContext .getPersistenceGateway() - .caseAdvancedSearch({ applicationContext, searchTerms }); + .caseAdvancedSearch({ + applicationContext, + searchTerms: { + countryType, + petitionerName, + petitionerState, + yearFiledMax, + yearFiledMin, + }, + }); const filteredCases = caseSearchFilter(foundCases, authorizedUser); diff --git a/shared/src/business/useCases/caseAssociation/updateCounselOnCaseInteractor.js b/shared/src/business/useCases/caseAssociation/updateCounselOnCaseInteractor.js index d9c984cfadf..251bbe5ffe8 100644 --- a/shared/src/business/useCases/caseAssociation/updateCounselOnCaseInteractor.js +++ b/shared/src/business/useCases/caseAssociation/updateCounselOnCaseInteractor.js @@ -3,8 +3,6 @@ const { ROLE_PERMISSIONS, } = require('../../../authorization/authorizationClientService'); const { Case } = require('../../entities/cases/Case'); -const { IrsPractitioner } = require('../../entities/IrsPractitioner'); -const { PrivatePractitioner } = require('../../entities/PrivatePractitioner'); const { UnauthorizedError } = require('../../../errors/errors'); const { User } = require('../../entities/User'); @@ -26,6 +24,12 @@ exports.updateCounselOnCaseInteractor = async ({ }) => { const user = applicationContext.getCurrentUser(); + const editableFields = { + representingPrimary: userData.representingPrimary, + representingSecondary: userData.representingSecondary, + serviceIndicator: userData.serviceIndicator, + }; + if (!isAuthorized(user, ROLE_PERMISSIONS.ASSOCIATE_USER_WITH_CASE)) { throw new UnauthorizedError('Unauthorized'); } @@ -47,13 +51,15 @@ exports.updateCounselOnCaseInteractor = async ({ const caseEntity = new Case(caseToUpdate, { applicationContext }); if (userToUpdate.role === User.ROLES.privatePractitioner) { - caseEntity.updatePrivatePractitioner( - new PrivatePractitioner({ userId: userToUpdate.userId, ...userData }), - ); + caseEntity.updatePrivatePractitioner({ + userId: userToUpdate.userId, + ...editableFields, + }); } else if (userToUpdate.role === User.ROLES.irsPractitioner) { - caseEntity.updateIrsPractitioner( - new IrsPractitioner({ userId: userToUpdate.userId, ...userData }), - ); + caseEntity.updateIrsPractitioner({ + userId: userToUpdate.userId, + ...editableFields, + }); } else { throw new Error('User is not a practitioner'); } diff --git a/shared/src/business/useCases/caseAssociation/updateCounselOnCaseInteractor.test.js b/shared/src/business/useCases/caseAssociation/updateCounselOnCaseInteractor.test.js index 7e37a9b66ec..ad352987a21 100644 --- a/shared/src/business/useCases/caseAssociation/updateCounselOnCaseInteractor.test.js +++ b/shared/src/business/useCases/caseAssociation/updateCounselOnCaseInteractor.test.js @@ -4,20 +4,31 @@ const { const { updateCounselOnCaseInteractor, } = require('./updateCounselOnCaseInteractor'); +const { IrsPractitioner } = require('../../entities/IrsPractitioner'); const { MOCK_CASE } = require('../../../test/mockCase.js'); +const { PrivatePractitioner } = require('../../entities/PrivatePractitioner'); const { User } = require('../../entities/User'); describe('updateCounselOnCaseInteractor', () => { const mockPrivatePractitioners = [ - { role: User.ROLES.privatePractitioner, userId: '456' }, - { role: User.ROLES.privatePractitioner, userId: '789' }, - { role: User.ROLES.privatePractitioner, userId: '012' }, + new PrivatePractitioner({ + role: User.ROLES.privatePractitioner, + userId: '456', + }), + new PrivatePractitioner({ + role: User.ROLES.privatePractitioner, + userId: '789', + }), + new PrivatePractitioner({ + role: User.ROLES.privatePractitioner, + userId: '012', + }), ]; const mockIrsPractitioners = [ - { role: User.ROLES.irsPractitioner, userId: '654' }, - { role: User.ROLES.irsPractitioner, userId: '987' }, - { role: User.ROLES.irsPractitioner, userId: '210' }, + new IrsPractitioner({ role: User.ROLES.irsPractitioner, userId: '654' }), + new IrsPractitioner({ role: User.ROLES.irsPractitioner, userId: '987' }), + new IrsPractitioner({ role: User.ROLES.irsPractitioner, userId: '210' }), ]; const mockPetitioners = [{ role: User.ROLES.petitioner, userId: '111' }]; @@ -41,6 +52,16 @@ describe('updateCounselOnCaseInteractor', () => { caseCaption: 'Caption', caseId, caseType: 'Deficiency', + contactPrimary: { + address1: '123 Main St', + city: 'Somewhere', + countryType: 'domestic', + email: 'fieri@example.com', + name: 'Guy Fieri', + phone: '1234567890', + postalCode: '12345', + state: 'CA', + }, docketNumber: '123-19', docketRecord: [ { @@ -82,6 +103,8 @@ describe('updateCounselOnCaseInteractor', () => { caseId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', userData: { representingPrimary: true, + representingSecondary: false, + serviceIndicator: 'Electronic', }, userIdToUpdate: '789', }); @@ -96,7 +119,9 @@ describe('updateCounselOnCaseInteractor', () => { applicationContext, caseId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', userData: { - email: 'irsPractitioner@example.com', + representingPrimary: true, + representingSecondary: false, + serviceIndicator: 'Electronic', }, userIdToUpdate: '987', }); @@ -106,6 +131,30 @@ describe('updateCounselOnCaseInteractor', () => { ).toHaveBeenCalled(); }); + it('updates only editable practitioner fields on the case', async () => { + await updateCounselOnCaseInteractor({ + applicationContext, + caseId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', + userData: { + email: 'not.editable@example.com', + representingPrimary: true, + representingSecondary: false, + serviceIndicator: 'Electronic', + }, + userIdToUpdate: '987', + }); + + const updatedPractitioner = applicationContext + .getPersistenceGateway() + .updateCase.mock.calls[0][0].caseToUpdate.irsPractitioners.find( + p => p.userId === '987', + ); + expect(updatedPractitioner.email).toBeUndefined(); + expect(updatedPractitioner.representingPrimary).toBe(true); + expect(updatedPractitioner.representingSecondary).toBe(false); + expect(updatedPractitioner.serviceIndicator).toBe('Electronic'); + }); + it('throws an error if the userIdToUpdate is not a privatePractitioner or irsPractitioner role', async () => { await expect( updateCounselOnCaseInteractor({ diff --git a/shared/src/business/useCases/caseAssociation/validateAddIrsPractitionerInteractor.js b/shared/src/business/useCases/caseAssociation/validateAddIrsPractitionerInteractor.js index 6f534d07ca0..12a56a16acd 100644 --- a/shared/src/business/useCases/caseAssociation/validateAddIrsPractitionerInteractor.js +++ b/shared/src/business/useCases/caseAssociation/validateAddIrsPractitionerInteractor.js @@ -1,3 +1,7 @@ +const { + AddIrsPractitioner, +} = require('../../entities/caseAssociation/AddIrsPractitioner'); + /** * validateAddIrsPractitionerInteractor * @@ -10,9 +14,9 @@ exports.validateAddIrsPractitionerInteractor = ({ applicationContext, counsel, }) => { - const errors = new (applicationContext.getEntityConstructors().AddIrsPractitioner)( - counsel, - ).getFormattedValidationErrors(); + const errors = new AddIrsPractitioner(counsel, { + applicationContext, + }).getFormattedValidationErrors(); if (!errors) return null; return errors; diff --git a/shared/src/business/useCases/caseAssociation/validateAddIrsPractitionerInteractor.test.js b/shared/src/business/useCases/caseAssociation/validateAddIrsPractitionerInteractor.test.js index 48f4b4810a9..3b1b1395492 100644 --- a/shared/src/business/useCases/caseAssociation/validateAddIrsPractitionerInteractor.test.js +++ b/shared/src/business/useCases/caseAssociation/validateAddIrsPractitionerInteractor.test.js @@ -1,6 +1,9 @@ const { AddIrsPractitioner, } = require('../../entities/caseAssociation/AddIrsPractitioner'); +const { + applicationContext, +} = require('../../test/createTestApplicationContext'); const { validateAddIrsPractitionerInteractor, } = require('./validateAddIrsPractitionerInteractor'); @@ -8,11 +11,7 @@ const { describe('validateAddIrsPractitionerInteractor', () => { it('returns the expected errors object on an empty add irsPractitioner', () => { const errors = validateAddIrsPractitionerInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - AddIrsPractitioner, - }), - }, + applicationContext, counsel: {}, }); @@ -23,11 +22,7 @@ describe('validateAddIrsPractitionerInteractor', () => { it('returns null when no errors occur', () => { const errors = validateAddIrsPractitionerInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - AddIrsPractitioner, - }), - }, + applicationContext, counsel: { representingPrimary: true, user: {} }, }); diff --git a/shared/src/business/useCases/caseAssociation/validateAddPrivatePractitionerInteractor.js b/shared/src/business/useCases/caseAssociation/validateAddPrivatePractitionerInteractor.js index b744090507f..7fcf536b927 100644 --- a/shared/src/business/useCases/caseAssociation/validateAddPrivatePractitionerInteractor.js +++ b/shared/src/business/useCases/caseAssociation/validateAddPrivatePractitionerInteractor.js @@ -1,3 +1,7 @@ +const { + AddPrivatePractitionerFactory, +} = require('../../entities/caseAssociation/AddPrivatePractitionerFactory'); + /** * validateAddPrivatePractitionerInteractor * @@ -10,10 +14,9 @@ exports.validateAddPrivatePractitionerInteractor = ({ applicationContext, counsel, }) => { - const errors = applicationContext - .getEntityConstructors() - .AddPrivatePractitionerFactory.get(counsel) - .getFormattedValidationErrors(); + const errors = AddPrivatePractitionerFactory.get(counsel, { + applicationContext, + }).getFormattedValidationErrors(); if (!errors) return null; return errors; diff --git a/shared/src/business/useCases/caseAssociation/validateAddPrivatePractitionerInteractor.test.js b/shared/src/business/useCases/caseAssociation/validateAddPrivatePractitionerInteractor.test.js index d05f12e12da..33f5e624dab 100644 --- a/shared/src/business/useCases/caseAssociation/validateAddPrivatePractitionerInteractor.test.js +++ b/shared/src/business/useCases/caseAssociation/validateAddPrivatePractitionerInteractor.test.js @@ -1,6 +1,6 @@ const { - AddPrivatePractitionerFactory, -} = require('../../entities/caseAssociation/AddPrivatePractitionerFactory'); + applicationContext, +} = require('../../test/createTestApplicationContext'); const { validateAddPrivatePractitionerInteractor, } = require('./validateAddPrivatePractitionerInteractor'); @@ -8,11 +8,7 @@ const { describe('validateAddPrivatePractitionerInteractor', () => { it('returns the expected errors object on an empty add practitioner', () => { const errors = validateAddPrivatePractitionerInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - AddPrivatePractitionerFactory, - }), - }, + applicationContext, counsel: {}, }); @@ -21,11 +17,7 @@ describe('validateAddPrivatePractitionerInteractor', () => { it('returns null when no errors occur', () => { const errors = validateAddPrivatePractitionerInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - AddPrivatePractitionerFactory, - }), - }, + applicationContext, counsel: { representingPrimary: true, user: {} }, }); diff --git a/shared/src/business/useCases/caseAssociation/validateEditPrivatePractitionerInteractor.js b/shared/src/business/useCases/caseAssociation/validateEditPrivatePractitionerInteractor.js index c596cf29a71..7395456de0f 100644 --- a/shared/src/business/useCases/caseAssociation/validateEditPrivatePractitionerInteractor.js +++ b/shared/src/business/useCases/caseAssociation/validateEditPrivatePractitionerInteractor.js @@ -1,3 +1,7 @@ +const { + EditPrivatePractitionerFactory, +} = require('../../entities/caseAssociation/EditPrivatePractitionerFactory'); + /** * validateEditPrivatePractitionerInteractor * @@ -10,10 +14,9 @@ exports.validateEditPrivatePractitionerInteractor = ({ applicationContext, practitioner, }) => { - const errors = applicationContext - .getEntityConstructors() - .EditPrivatePractitionerFactory.get(practitioner) - .getFormattedValidationErrors(); + const errors = EditPrivatePractitionerFactory.get(practitioner, { + applicationContext, + }).getFormattedValidationErrors(); if (!errors) return null; return errors; diff --git a/shared/src/business/useCases/caseAssociation/validateEditPrivatePractitionerInteractor.test.js b/shared/src/business/useCases/caseAssociation/validateEditPrivatePractitionerInteractor.test.js index c09ed306e91..b18aab79de3 100644 --- a/shared/src/business/useCases/caseAssociation/validateEditPrivatePractitionerInteractor.test.js +++ b/shared/src/business/useCases/caseAssociation/validateEditPrivatePractitionerInteractor.test.js @@ -1,6 +1,6 @@ const { - EditPrivatePractitionerFactory, -} = require('../../entities/caseAssociation/EditPrivatePractitionerFactory'); + applicationContext, +} = require('../../test/createTestApplicationContext'); const { validateEditPrivatePractitionerInteractor, } = require('./validateEditPrivatePractitionerInteractor'); @@ -8,11 +8,7 @@ const { describe('validateEditPrivatePractitionerInteractor', () => { it('returns the expected errors object on an empty add practitioner', () => { const errors = validateEditPrivatePractitionerInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - EditPrivatePractitionerFactory, - }), - }, + applicationContext, practitioner: {}, }); @@ -21,11 +17,7 @@ describe('validateEditPrivatePractitionerInteractor', () => { it('returns null when no errors occur', () => { const errors = validateEditPrivatePractitionerInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - EditPrivatePractitionerFactory, - }), - }, + applicationContext, practitioner: { representingPrimary: true }, }); diff --git a/shared/src/business/useCases/caseAssociationRequest/generateCaseAssociationDocumentTitleInteractor.js b/shared/src/business/useCases/caseAssociationRequest/generateCaseAssociationDocumentTitleInteractor.js index 8aca6a1abeb..4db05199c04 100644 --- a/shared/src/business/useCases/caseAssociationRequest/generateCaseAssociationDocumentTitleInteractor.js +++ b/shared/src/business/useCases/caseAssociationRequest/generateCaseAssociationDocumentTitleInteractor.js @@ -1,3 +1,7 @@ +const { + CaseAssociationRequestFactory, +} = require('../../entities/CaseAssociationRequestFactory'); + /** * generateCaseAssociationDocumentTitleInteractor * @@ -14,9 +18,10 @@ exports.generateCaseAssociationDocumentTitleInteractor = ({ contactPrimaryName, contactSecondaryName, }) => { - const caseAssociation = applicationContext - .getEntityConstructors() - .CaseAssociationRequestFactory(caseAssociationRequest); + const caseAssociation = CaseAssociationRequestFactory( + caseAssociationRequest, + { applicationContext }, + ); return caseAssociation.getDocumentTitle( contactPrimaryName, contactSecondaryName, diff --git a/shared/src/business/useCases/caseAssociationRequest/submitCaseAssociationRequestInteractor.test.js b/shared/src/business/useCases/caseAssociationRequest/submitCaseAssociationRequestInteractor.test.js index c7332a32ae8..9f5d37cdcab 100644 --- a/shared/src/business/useCases/caseAssociationRequest/submitCaseAssociationRequestInteractor.test.js +++ b/shared/src/business/useCases/caseAssociationRequest/submitCaseAssociationRequestInteractor.test.js @@ -12,6 +12,16 @@ describe('submitCaseAssociationRequest', () => { caseCaption: 'Caption', caseId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', caseType: 'Deficiency', + contactPrimary: { + address1: '123 Main St', + city: 'Somewhere', + countryType: 'domestic', + email: 'fieri@example.com', + name: 'Guy Fieri', + phone: '1234567890', + postalCode: '12345', + state: 'CA', + }, docketNumber: '123-19', docketRecord: [ { diff --git a/shared/src/business/useCases/caseAssociationRequest/validateCaseAssociationRequestInteractor.js b/shared/src/business/useCases/caseAssociationRequest/validateCaseAssociationRequestInteractor.js index adcdad08fe3..6d3ac2015ec 100644 --- a/shared/src/business/useCases/caseAssociationRequest/validateCaseAssociationRequestInteractor.js +++ b/shared/src/business/useCases/caseAssociationRequest/validateCaseAssociationRequestInteractor.js @@ -1,3 +1,7 @@ +const { + CaseAssociationRequestFactory, +} = require('../../entities/CaseAssociationRequestFactory'); + /** * validateCaseAssociationRequestInteractor * @@ -10,9 +14,8 @@ exports.validateCaseAssociationRequestInteractor = ({ applicationContext, caseAssociationRequest, }) => { - const errors = applicationContext - .getEntityConstructors() - .CaseAssociationRequestFactory(caseAssociationRequest) - .getFormattedValidationErrors(); + const errors = CaseAssociationRequestFactory(caseAssociationRequest, { + applicationContext, + }).getFormattedValidationErrors(); return errors || null; }; diff --git a/shared/src/business/useCases/caseAssociationRequest/validateCaseAssociationRequestInteractor.test.js b/shared/src/business/useCases/caseAssociationRequest/validateCaseAssociationRequestInteractor.test.js index 333d1599a5c..24dc0ce022c 100644 --- a/shared/src/business/useCases/caseAssociationRequest/validateCaseAssociationRequestInteractor.test.js +++ b/shared/src/business/useCases/caseAssociationRequest/validateCaseAssociationRequestInteractor.test.js @@ -1,6 +1,6 @@ const { - CaseAssociationRequestFactory, -} = require('../../entities/CaseAssociationRequestFactory'); + applicationContext, +} = require('../../test/createTestApplicationContext'); const { validateCaseAssociationRequestInteractor, } = require('./validateCaseAssociationRequestInteractor'); @@ -8,11 +8,7 @@ const { describe('validateCaseAssociationRequest', () => { it('returns the expected errors object on an empty case association request', () => { const errors = validateCaseAssociationRequestInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - CaseAssociationRequestFactory, - }), - }, + applicationContext, caseAssociationRequest: {}, }); @@ -29,14 +25,10 @@ describe('validateCaseAssociationRequest', () => { it('returns null for a valid case association request', () => { const errors = validateCaseAssociationRequestInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - CaseAssociationRequestFactory, - }), - }, + applicationContext, caseAssociationRequest: { certificateOfService: true, - certificateOfServiceDate: '1212-12-12', + certificateOfServiceDate: '1987-08-06T07:53:09.001Z', documentTitleTemplate: 'Entry of Appearance for [Petitioner Names]', documentType: 'Entry of Appearance', eventCode: '123', diff --git a/shared/src/business/useCases/caseConsolidation/canConsolidateInteractor.js b/shared/src/business/useCases/caseConsolidation/canConsolidateInteractor.js new file mode 100644 index 00000000000..e9b7d24b7e9 --- /dev/null +++ b/shared/src/business/useCases/caseConsolidation/canConsolidateInteractor.js @@ -0,0 +1,24 @@ +const { Case } = require('../../entities/cases/Case'); + +/** + * canConsolidateInteractor + * + * @param {object} providers the providers object + * @param {object} providers.applicationContext the application context + * @param {object} providers.caseToConsolidate the case to consolidate with + * @param {object} providers.currentCase the case to check if caseToConsolidate can be consolidated with + * @returns {object} whether or not the cases can be consolidated with the reason + */ +exports.canConsolidateInteractor = ({ + applicationContext, + caseToConsolidate, + currentCase, +}) => { + const caseEntity = new Case(currentCase, { applicationContext }); + + const results = caseEntity.getConsolidationStatus({ + caseEntity: caseToConsolidate, + }); + + return results; +}; diff --git a/shared/src/business/useCases/caseConsolidation/canConsolidateInteractor.test.js b/shared/src/business/useCases/caseConsolidation/canConsolidateInteractor.test.js new file mode 100644 index 00000000000..08ade508e3d --- /dev/null +++ b/shared/src/business/useCases/caseConsolidation/canConsolidateInteractor.test.js @@ -0,0 +1,49 @@ +const { + applicationContext, +} = require('../../test/createTestApplicationContext'); +const { canConsolidateInteractor } = require('./canConsolidateInteractor'); +const { MOCK_CASE } = require('../../../test/mockCase'); + +describe('canConsolidateInteractor', () => { + let currentCase; + let caseToConsolidate; + + beforeEach(() => { + currentCase = { + ...MOCK_CASE, + associatedJudge: 'Judge Buch', + procedureType: 'regular', + status: 'Submitted', + }; + + caseToConsolidate = { + ...MOCK_CASE, + associatedJudge: 'Judge Buch', + docketNumber: '102-19', + procedureType: 'regular', + status: 'Submitted', + }; + }); + + it('should return true when cases are consolidatable', () => { + const result = canConsolidateInteractor({ + applicationContext, + caseToConsolidate, + currentCase, + }); + + expect(result.canConsolidate).toEqual(true); + }); + + it('should return false when cases are not consolidatable', () => { + caseToConsolidate.status = 'Closed'; + + const result = canConsolidateInteractor({ + applicationContext, + caseToConsolidate, + currentCase, + }); + + expect(result.canConsolidate).toEqual(false); + }); +}); diff --git a/shared/src/business/useCases/caseDeadline/getAllCaseDeadlinesInteractor.test.js b/shared/src/business/useCases/caseDeadline/getAllCaseDeadlinesInteractor.test.js index 629530445b2..55016996119 100644 --- a/shared/src/business/useCases/caseDeadline/getAllCaseDeadlinesInteractor.test.js +++ b/shared/src/business/useCases/caseDeadline/getAllCaseDeadlinesInteractor.test.js @@ -22,6 +22,16 @@ describe('getAllCaseDeadlinesInteractor', () => { caseCaption: 'A caption, Petitioner', caseId: '01eebcc4-08aa-4550-b41b-982ffbd75192', caseType: 'CDP (Lien/Levy)', + contactPrimary: { + address1: '123 Main St', + city: 'Somewhere', + countryType: 'domestic', + email: 'fieri@example.com', + name: 'Guy Fieri', + phone: '1234567890', + postalCode: '12345', + state: 'CA', + }, docketNumber: '101-19', partyType: 'Petitioner', procedureType: 'Regular', @@ -71,6 +81,7 @@ describe('getAllCaseDeadlinesInteractor', () => { description: 'A deadline!', docketNumber: '101-19', docketNumberSuffix: 'L', + entityName: 'CaseDeadline', }, ]); }); diff --git a/shared/src/business/useCases/caseDeadline/validateCaseDeadlineInteractor.js b/shared/src/business/useCases/caseDeadline/validateCaseDeadlineInteractor.js index 51d680df62c..71299804573 100644 --- a/shared/src/business/useCases/caseDeadline/validateCaseDeadlineInteractor.js +++ b/shared/src/business/useCases/caseDeadline/validateCaseDeadlineInteractor.js @@ -1,3 +1,5 @@ +const { CaseDeadline } = require('../../entities/CaseDeadline'); + /** * validateCaseDeadlineInteractor * @@ -10,9 +12,8 @@ exports.validateCaseDeadlineInteractor = ({ applicationContext, caseDeadline, }) => { - const errors = new (applicationContext.getEntityConstructors().CaseDeadline)( - caseDeadline, - { applicationContext }, - ).getFormattedValidationErrors(); + const errors = new CaseDeadline(caseDeadline, { + applicationContext, + }).getFormattedValidationErrors(); return errors || null; }; diff --git a/shared/src/business/useCases/caseDeadline/validateCaseDeadlineInteractor.test.js b/shared/src/business/useCases/caseDeadline/validateCaseDeadlineInteractor.test.js index 972b18e67c9..74025afd160 100644 --- a/shared/src/business/useCases/caseDeadline/validateCaseDeadlineInteractor.test.js +++ b/shared/src/business/useCases/caseDeadline/validateCaseDeadlineInteractor.test.js @@ -1,3 +1,6 @@ +const { + applicationContext, +} = require('../../test/createTestApplicationContext'); const { validateCaseDeadlineInteractor, } = require('./validateCaseDeadlineInteractor'); @@ -6,12 +9,7 @@ const { CaseDeadline } = require('../../entities/CaseDeadline'); describe('validateCaseDeadlineInteractor', () => { it('returns the expected errors object on an empty case deadline', () => { const errors = validateCaseDeadlineInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - CaseDeadline, - }), - getUniqueId: () => 'c54ba5a9-b37b-479d-9201-067ec6e335bb', - }, + applicationContext, caseDeadline: {}, }); @@ -29,12 +27,7 @@ describe('validateCaseDeadlineInteractor', () => { }; const errors = validateCaseDeadlineInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - CaseDeadline, - }), - getUniqueId: () => 'c54ba5a9-b37b-479d-9201-067ec6e335bb', - }, + applicationContext, caseDeadline: mockCaseDeadline, }); diff --git a/shared/src/business/useCases/caseNote/getUserCaseNoteForCasesInteractor.test.js b/shared/src/business/useCases/caseNote/getUserCaseNoteForCasesInteractor.test.js index c15a83b6a71..1224d270a66 100644 --- a/shared/src/business/useCases/caseNote/getUserCaseNoteForCasesInteractor.test.js +++ b/shared/src/business/useCases/caseNote/getUserCaseNoteForCasesInteractor.test.js @@ -56,9 +56,7 @@ describe('getUserCaseNoteForCasesInteractor', () => { } catch (err) { error = err; } - expect(error.message).toContain( - 'The UserCaseNote entity was invalid ValidationError: "userId" is required', - ); + expect(error.message).toContain('The UserCaseNote entity was invalid'); }); it('correctly returns data from persistence', async () => { diff --git a/shared/src/business/useCases/caseNote/getUserCaseNoteInteractor.test.js b/shared/src/business/useCases/caseNote/getUserCaseNoteInteractor.test.js index 921588692dd..d0cb6cde476 100644 --- a/shared/src/business/useCases/caseNote/getUserCaseNoteInteractor.test.js +++ b/shared/src/business/useCases/caseNote/getUserCaseNoteInteractor.test.js @@ -60,9 +60,7 @@ describe('Get case note', () => { } catch (err) { error = err; } - expect(error.message).toContain( - 'The UserCaseNote entity was invalid ValidationError: "userId" is required', - ); + expect(error.message).toContain('The UserCaseNote entity was invalid'); }); it('correctly returns data from persistence', async () => { diff --git a/shared/src/business/useCases/caseNote/validateNoteInteractor.js b/shared/src/business/useCases/caseNote/validateNoteInteractor.js index fa3aec77fd8..3511f3580f9 100644 --- a/shared/src/business/useCases/caseNote/validateNoteInteractor.js +++ b/shared/src/business/useCases/caseNote/validateNoteInteractor.js @@ -1,3 +1,5 @@ +const { Note } = require('../../entities/notes/Note'); + /** * validateNote * @@ -7,9 +9,9 @@ * @returns {object} the errors or null */ exports.validateNoteInteractor = ({ applicationContext, note }) => { - const errors = new (applicationContext.getEntityConstructors().Note)( - note, - ).getFormattedValidationErrors(); + const errors = new Note(note, { + applicationContext, + }).getFormattedValidationErrors(); if (!errors) return null; return errors; }; diff --git a/shared/src/business/useCases/caseNote/validateNoteInteractor.test.js b/shared/src/business/useCases/caseNote/validateNoteInteractor.test.js index 1ce2148a9f6..72cf8b2452d 100644 --- a/shared/src/business/useCases/caseNote/validateNoteInteractor.test.js +++ b/shared/src/business/useCases/caseNote/validateNoteInteractor.test.js @@ -1,14 +1,12 @@ -const { Note } = require('../../entities/notes/Note'); +const { + applicationContext, +} = require('../../test/createTestApplicationContext'); const { validateNoteInteractor } = require('./validateNoteInteractor'); describe('validateNoteInteractor', () => { it('returns the expected errors object on an empty note', () => { const errors = validateNoteInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - Note, - }), - }, + applicationContext, note: {}, }); @@ -17,11 +15,7 @@ describe('validateNoteInteractor', () => { it('returns null on no errors', () => { const errors = validateNoteInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - Note, - }), - }, + applicationContext, note: { notes: 'hello world', }, diff --git a/shared/src/business/useCases/courtIssuedDocument/generateCourtIssuedDocumentTitleInteractor.js b/shared/src/business/useCases/courtIssuedDocument/generateCourtIssuedDocumentTitleInteractor.js index db3ce1f56e7..3b77c40eaea 100644 --- a/shared/src/business/useCases/courtIssuedDocument/generateCourtIssuedDocumentTitleInteractor.js +++ b/shared/src/business/useCases/courtIssuedDocument/generateCourtIssuedDocumentTitleInteractor.js @@ -1,20 +1,16 @@ +const { + CourtIssuedDocumentFactory, +} = require('../../entities/courtIssuedDocument/CourtIssuedDocumentFactory'); +const { Document } = require('../../entities/Document'); + /** * generateCourtIssuedDocumentTitleInteractor * * @param {object} providers the providers object - * @param {object} providers.applicationContext the application context * @param {object} providers.documentMetadata the document metadata * @returns {string} document title */ -exports.generateCourtIssuedDocumentTitleInteractor = ({ - applicationContext, - documentMetadata, -}) => { - const { - CourtIssuedDocumentFactory, - Document, - } = applicationContext.getEntityConstructors(); - +exports.generateCourtIssuedDocumentTitleInteractor = ({ documentMetadata }) => { const filingEvent = Document.COURT_ISSUED_EVENT_CODES.find( document => documentMetadata.eventCode === document.eventCode, ); diff --git a/shared/src/business/useCases/courtIssuedDocument/serveCourtIssuedDocumentInteractor.js b/shared/src/business/useCases/courtIssuedDocument/serveCourtIssuedDocumentInteractor.js index ff8ee3ce96d..bfb23a333d7 100644 --- a/shared/src/business/useCases/courtIssuedDocument/serveCourtIssuedDocumentInteractor.js +++ b/shared/src/business/useCases/courtIssuedDocument/serveCourtIssuedDocumentInteractor.js @@ -13,6 +13,9 @@ const { isAuthorized, ROLE_PERMISSIONS, } = require('../../../authorization/authorizationClientService'); +const { + saveFileAndGenerateUrl, +} = require('../../useCaseHelper/saveFileAndGenerateUrl'); const { addServedStampToDocument } = require('./addServedStampToDocument'); const { Case } = require('../../entities/cases/Case'); const { DocketRecord } = require('../../entities/DocketRecord'); @@ -87,6 +90,13 @@ exports.serveCourtIssuedDocumentInteractor = async ({ throw new NotFoundError(`Document ${documentId} was not found.`); } + courtIssuedDocument.numberOfPages = await applicationContext + .getUseCaseHelpers() + .countPagesInDocument({ + applicationContext, + documentId, + }); + const docketEntry = caseEntity.getDocketRecordByDocumentId(documentId); // Serve on all parties @@ -197,7 +207,6 @@ exports.serveCourtIssuedDocumentInteractor = async ({ servedParties, }); - let paperServicePdfBuffer; if (servedParties.paper.length > 0) { const courtIssuedOrderDoc = await PDFDocument.load(newPdfData); @@ -214,8 +223,11 @@ exports.serveCourtIssuedDocumentInteractor = async ({ }); const paperServicePdfData = await newPdfDoc.save(); - paperServicePdfBuffer = Buffer.from(paperServicePdfData); - } + const { url } = await saveFileAndGenerateUrl({ + applicationContext, + file: paperServicePdfData, + }); - return paperServicePdfBuffer; + return { pdfUrl: url }; + } }; diff --git a/shared/src/business/useCases/courtIssuedDocument/serveCourtIssuedDocumentInteractor.test.js b/shared/src/business/useCases/courtIssuedDocument/serveCourtIssuedDocumentInteractor.test.js index 36f45bf6b65..a776d944530 100644 --- a/shared/src/business/useCases/courtIssuedDocument/serveCourtIssuedDocumentInteractor.test.js +++ b/shared/src/business/useCases/courtIssuedDocument/serveCourtIssuedDocumentInteractor.test.js @@ -24,6 +24,9 @@ describe('serveCourtIssuedDocumentInteractor', () => { let testPdfDoc; let extendCase; + const mockPdfUrl = 'www.example.com'; + const mockDocumentId = 'cf105788-5d34-4451-aa8d-dfd9a851b675'; + const testPdfDocBytes = () => { // sample.pdf is a 1 page document return fs.readFileSync(testAssetsPath + 'sample.pdf'); @@ -101,8 +104,8 @@ describe('serveCourtIssuedDocumentInteractor', () => { }, { description: 'Docket Record 1', - docketRecordId: 'cf105788-5d34-4451-aa8d-dfd9a851b675', - documentId: 'cf105788-5d34-4451-aa8d-dfd9a851b675', + docketRecordId: mockDocumentId, + documentId: mockDocumentId, eventCode: 'OAJ', filingDate: createISODateString(), index: 1, @@ -119,7 +122,7 @@ describe('serveCourtIssuedDocumentInteractor', () => { workItems: [mockWorkItem], }, { - documentId: 'cf105788-5d34-4451-aa8d-dfd9a851b675', + documentId: mockDocumentId, documentType: 'OAJ - Order that case is assigned', eventCode: 'OAJ', userId: '2474e5c0-f741-4120-befa-b77378ac8bf0', @@ -166,8 +169,8 @@ describe('serveCourtIssuedDocumentInteractor', () => { }, { description: 'Docket Record 0', - docketRecordId: 'cf105788-5d34-4451-aa8d-dfd9a851b675', - documentId: 'cf105788-5d34-4451-aa8d-dfd9a851b675', + docketRecordId: mockDocumentId, + documentId: mockDocumentId, eventCode: 'OAJ', filingDate: createISODateString(), index: 1, @@ -184,7 +187,7 @@ describe('serveCourtIssuedDocumentInteractor', () => { workItems: [mockWorkItem], }, { - documentId: 'cf105788-5d34-4451-aa8d-dfd9a851b675', + documentId: mockDocumentId, documentType: 'OAJ - Order that case is assigned', eventCode: 'OAJ', userId: '2474e5c0-f741-4120-befa-b77378ac8bf0', @@ -217,12 +220,18 @@ describe('serveCourtIssuedDocumentInteractor', () => { }; } }); + applicationContext + .getPersistenceGateway() + .getDownloadPolicyUrl.mockReturnValue(mockPdfUrl); applicationContext .getPersistenceGateway() .updateCase.mockImplementation(caseToUpdate => caseToUpdate); applicationContext .getUseCaseHelpers() .generatePaperServiceAddressPagePdf.mockResolvedValue(testPdfDoc); + applicationContext + .getUseCaseHelpers() + .countPagesInDocument.mockResolvedValue(1); applicationContext.getStorageClient().getObject.mockReturnValue({ promise: async () => ({ Body: testPdfDoc, @@ -313,8 +322,7 @@ describe('serveCourtIssuedDocumentInteractor', () => { document.documentId === 'c54ba5a9-b37b-479d-9201-067ec6e335bc', ); - expect(updatedDocument.status).toEqual('served'); - expect(updatedDocument.servedAt).toBeTruthy(); + expect(updatedDocument.servedAt).toBeDefined(); expect( applicationContext.getPersistenceGateway().updateCase, ).toHaveBeenCalled(); @@ -326,6 +334,26 @@ describe('serveCourtIssuedDocumentInteractor', () => { ).toHaveBeenCalled(); }); + it('should set the number of pages present in the document to be served', async () => { + await serveCourtIssuedDocumentInteractor({ + applicationContext, + caseId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', + documentId: mockDocumentId, + }); + + const updatedCase = applicationContext.getPersistenceGateway().updateCase + .mock.calls[0][0].caseToUpdate; + const updatedDocument = updatedCase.documents.find( + document => document.documentId === mockDocumentId, + ); + + expect(updatedDocument.numberOfPages).toBe(1); + expect( + applicationContext.getUseCaseHelpers().countPagesInDocument.mock + .calls[0][0], + ).toMatchObject({ documentId: mockDocumentId }); + }); + it('should set the document as served and update the case and work items for a non-generic order document', async () => { applicationContext .getPersistenceGateway() @@ -339,18 +367,16 @@ describe('serveCourtIssuedDocumentInteractor', () => { await serveCourtIssuedDocumentInteractor({ applicationContext, caseId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', - documentId: 'cf105788-5d34-4451-aa8d-dfd9a851b675', + documentId: mockDocumentId, }); const updatedCase = applicationContext.getPersistenceGateway().updateCase .mock.calls[0][0].caseToUpdate; const updatedDocument = updatedCase.documents.find( - document => - document.documentId === 'cf105788-5d34-4451-aa8d-dfd9a851b675', + document => document.documentId === mockDocumentId, ); - expect(updatedDocument.status).toEqual('served'); - expect(updatedDocument.servedAt).toBeTruthy(); + expect(updatedDocument.servedAt).toBeDefined(); expect( applicationContext.getPersistenceGateway().updateCase, ).toHaveBeenCalled(); @@ -382,7 +408,7 @@ describe('serveCourtIssuedDocumentInteractor', () => { documentId: 'c54ba5a9-b37b-479d-9201-067ec6e335bc', }); - expect(result).toBeDefined(); + expect(result.pdfUrl).toBe(mockPdfUrl.url); }); it('should remove the case from the trial session if the case has a trialSessionId', async () => { diff --git a/shared/src/business/useCases/courtIssuedDocument/validateCourtIssuedDocketEntryInteractor.js b/shared/src/business/useCases/courtIssuedDocument/validateCourtIssuedDocketEntryInteractor.js index 6258123f06f..21c6608f1be 100644 --- a/shared/src/business/useCases/courtIssuedDocument/validateCourtIssuedDocketEntryInteractor.js +++ b/shared/src/business/useCases/courtIssuedDocument/validateCourtIssuedDocketEntryInteractor.js @@ -1,3 +1,7 @@ +const { + CourtIssuedDocumentFactory, +} = require('../../entities/courtIssuedDocument/CourtIssuedDocumentFactory'); + /** * validateCourtIssuedDocketEntryInteractor * @@ -10,9 +14,9 @@ exports.validateCourtIssuedDocketEntryInteractor = ({ applicationContext, entryMetadata, }) => { - const courtIssuedDocument = applicationContext - .getEntityConstructors() - .CourtIssuedDocumentFactory.get(entryMetadata); + const courtIssuedDocument = CourtIssuedDocumentFactory.get(entryMetadata, { + applicationContext, + }); return courtIssuedDocument.getFormattedValidationErrors(); }; diff --git a/shared/src/business/useCases/courtIssuedDocument/validateCourtIssuedDocketEntryInteractor.test.js b/shared/src/business/useCases/courtIssuedDocument/validateCourtIssuedDocketEntryInteractor.test.js index 8a22d2891a8..7bf11818b23 100644 --- a/shared/src/business/useCases/courtIssuedDocument/validateCourtIssuedDocketEntryInteractor.test.js +++ b/shared/src/business/useCases/courtIssuedDocument/validateCourtIssuedDocketEntryInteractor.test.js @@ -1,6 +1,6 @@ const { - CourtIssuedDocumentFactory, -} = require('../../entities/courtIssuedDocument/CourtIssuedDocumentFactory'); + applicationContext, +} = require('../../test/createTestApplicationContext'); const { validateCourtIssuedDocketEntryInteractor, } = require('./validateCourtIssuedDocketEntryInteractor'); @@ -11,11 +11,7 @@ const { describe('validateCourtIssuedDocketEntryInteractor', () => { it('returns default errors on empty entryMetadata', () => { const errors = validateCourtIssuedDocketEntryInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - CourtIssuedDocumentFactory, - }), - }, + applicationContext, entryMetadata: {}, }); @@ -27,11 +23,7 @@ describe('validateCourtIssuedDocketEntryInteractor', () => { it('returns expected errors when only scenario is set', () => { const errors = validateCourtIssuedDocketEntryInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - CourtIssuedDocumentFactory, - }), - }, + applicationContext, entryMetadata: { scenario: 'Type A', }, @@ -45,11 +37,7 @@ describe('validateCourtIssuedDocketEntryInteractor', () => { it('returns no errors when all required data fields are set', () => { const errors = validateCourtIssuedDocketEntryInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - CourtIssuedDocumentFactory, - }), - }, + applicationContext, entryMetadata: { attachments: false, documentTitle: 'Order fixing amount of bond at [Anything]', diff --git a/shared/src/business/useCases/courtIssuedOrder/createCourtIssuedOrderPdfFromHtmlInteractor.js b/shared/src/business/useCases/courtIssuedOrder/createCourtIssuedOrderPdfFromHtmlInteractor.js index 7b8ad5520c8..9e4b313816f 100644 --- a/shared/src/business/useCases/courtIssuedOrder/createCourtIssuedOrderPdfFromHtmlInteractor.js +++ b/shared/src/business/useCases/courtIssuedOrder/createCourtIssuedOrderPdfFromHtmlInteractor.js @@ -71,5 +71,7 @@ exports.createCourtIssuedOrderPdfFromHtmlInteractor = async ({ } } - return result; + return await applicationContext + .getUseCaseHelpers() + .saveFileAndGenerateUrl({ applicationContext, file: result }); }; diff --git a/shared/src/business/useCases/courtIssuedOrder/createCourtIssuedOrderPdfFromHtmlInteractor.test.js b/shared/src/business/useCases/courtIssuedOrder/createCourtIssuedOrderPdfFromHtmlInteractor.test.js index 0747c3537ff..4a4b2b565c6 100644 --- a/shared/src/business/useCases/courtIssuedOrder/createCourtIssuedOrderPdfFromHtmlInteractor.test.js +++ b/shared/src/business/useCases/courtIssuedOrder/createCourtIssuedOrderPdfFromHtmlInteractor.test.js @@ -1,47 +1,33 @@ +const { + applicationContext, +} = require('../../test/createTestApplicationContext'); const { createCourtIssuedOrderPdfFromHtmlInteractor, } = require('./createCourtIssuedOrderPdfFromHtmlInteractor'); -const PDF_MOCK_BUFFER = 'Hello World'; -const pageMock = { - addStyleTag: () => {}, - pdf: () => { - return PDF_MOCK_BUFFER; - }, - setContent: () => {}, -}; - -const chromiumBrowserMock = { - close: () => {}, - newPage: () => pageMock, -}; describe('createCourtIssuedOrderPdfFromHtmlInteractor', () => { - it('returns the pdf buffer produced by chromium', async () => { + it('returns the pdf url', async () => { + const mockPdfUrl = 'www.example.com'; + applicationContext + .getUseCaseHelpers() + .saveFileAndGenerateUrl.mockReturnValue(mockPdfUrl); + const result = await createCourtIssuedOrderPdfFromHtmlInteractor({ - applicationContext: { - getChromiumBrowser: () => chromiumBrowserMock, - logger: { error: () => {}, info: () => {} }, - }, - htmlString: 'Hello World from the use case', + applicationContext, }); - expect(result).toEqual(PDF_MOCK_BUFFER); + expect(result).toEqual(mockPdfUrl); }); it('should catch, log, and rethrow an error thrown by chromium', async () => { - const loggerErrorMock = jest.fn(); + applicationContext.getChromiumBrowser.mockImplementation(() => { + throw new Error('some chromium error'); + }); + await expect( createCourtIssuedOrderPdfFromHtmlInteractor({ - applicationContext: { - getChromiumBrowser: () => { - throw new Error('some chromium error'); - }, - logger: { error: loggerErrorMock, info: () => {} }, - }, - htmlString: 'Hello World from the use case', + applicationContext, }), - ).rejects.toThrow(); - - expect(loggerErrorMock).toHaveBeenCalled(); + ).rejects.toThrow('some chromium error'); }); }); diff --git a/shared/src/business/useCases/courtIssuedOrder/fileCourtIssuedOrderInteractor.js b/shared/src/business/useCases/courtIssuedOrder/fileCourtIssuedOrderInteractor.js index 7436ccbcfba..8d48c8b777f 100644 --- a/shared/src/business/useCases/courtIssuedOrder/fileCourtIssuedOrderInteractor.js +++ b/shared/src/business/useCases/courtIssuedOrder/fileCourtIssuedOrderInteractor.js @@ -43,6 +43,51 @@ exports.fileCourtIssuedOrderInteractor = async ({ documentMetadata.freeText = documentMetadata.documentTitle; } + if (documentMetadata.documentContents) { + const documentContentsId = applicationContext.getUniqueId(); + + const contentToStore = { + documentContents: documentMetadata.documentContents, + richText: documentMetadata.draftState.richText, + }; + + applicationContext.getPersistenceGateway().saveDocumentFromLambda({ + applicationContext, + document: Buffer.from(JSON.stringify(contentToStore)), + documentId: documentContentsId, + useTempBucket: true, + }); + + delete documentMetadata.documentContents; + delete documentMetadata.draftState.documentContents; + delete documentMetadata.draftState.richText; + delete documentMetadata.draftState.editorDelta; + documentMetadata.documentContentsId = documentContentsId; + } + + /* eslint-disable spellcheck/spell-checker */ + /* POC for #4814 - leaving here for future work + if (!documentMetadata.documentContents) { + const { Body: pdfData } = await applicationContext + .getStorageClient() + .getObject({ + Bucket: applicationContext.environment.documentsBucketName, + Key: primaryDocumentFileId, + }) + .promise(); + + try { + const parsedDocument = await pdfParse(pdfData); + + if (parsedDocument.text) { + documentMetadata.documentContents = parsedDocument.text; + } + } catch (e) { + applicationContext.logger.info('Failed to parse PDF'); + } + } */ + /* eslint-enable spellcheck/spell-checker */ + const documentEntity = new Document( { ...documentMetadata, diff --git a/shared/src/business/useCases/courtIssuedOrder/fileCourtIssuedOrderInteractor.test.js b/shared/src/business/useCases/courtIssuedOrder/fileCourtIssuedOrderInteractor.test.js index 6d430f110ca..2eda67cec4f 100644 --- a/shared/src/business/useCases/courtIssuedOrder/fileCourtIssuedOrderInteractor.test.js +++ b/shared/src/business/useCases/courtIssuedOrder/fileCourtIssuedOrderInteractor.test.js @@ -11,6 +11,16 @@ describe('fileCourtIssuedOrderInteractor', () => { caseCaption: 'Caption', caseId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', caseType: 'Deficiency', + contactPrimary: { + address1: '123 Main St', + city: 'Somewhere', + countryType: 'domestic', + email: 'fieri@example.com', + name: 'Guy Fieri', + phone: '1234567890', + postalCode: '12345', + state: 'CA', + }, createdAt: '', docketNumber: '45678-18', docketRecord: [ @@ -158,4 +168,37 @@ describe('fileCourtIssuedOrderInteractor', () => { expect(result).toMatchObject({ freeText: 'Notice to be nice' }); expect(result.signedAt).toBeTruthy(); }); + + it('should store documentMetadata.documentContents in S3 and delete from data sent to persistence', async () => { + await fileCourtIssuedOrderInteractor({ + applicationContext, + documentMetadata: { + caseId: caseRecord.caseId, + docketNumber: '45678-18', + documentContents: 'I am some document contents', + documentType: 'Order to Show Cause', + draftState: { + documentContents: 'I am some document contents', + editorDelta: 'I am some document contents', + richText: 'I am some document contents', + }, + }, + primaryDocumentFileId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', + }); + + expect( + applicationContext.getPersistenceGateway().saveDocumentFromLambda, + ).toHaveBeenCalled(); + expect( + applicationContext.getPersistenceGateway().updateCase.mock.calls[0][0] + .caseToUpdate.documents[3].documentContents, + ).toBeUndefined(); + expect( + applicationContext.getPersistenceGateway().updateCase.mock.calls[0][0] + .caseToUpdate.documents[3], + ).toMatchObject({ + documentContentsId: expect.anything(), + draftState: {}, + }); + }); }); diff --git a/shared/src/business/useCases/courtIssuedOrder/updateCourtIssuedOrderInteractor.js b/shared/src/business/useCases/courtIssuedOrder/updateCourtIssuedOrderInteractor.js index 230aa72c5b5..7836250f48f 100644 --- a/shared/src/business/useCases/courtIssuedOrder/updateCourtIssuedOrderInteractor.js +++ b/shared/src/business/useCases/courtIssuedOrder/updateCourtIssuedOrderInteractor.js @@ -4,7 +4,7 @@ const { } = require('../../../authorization/authorizationClientService'); const { Case } = require('../../entities/cases/Case'); const { Document } = require('../../entities/Document'); -const { UnauthorizedError } = require('../../../errors/errors'); +const { NotFoundError, UnauthorizedError } = require('../../../errors/errors'); /** * @@ -39,11 +39,47 @@ exports.updateCourtIssuedOrderInteractor = async ({ const caseEntity = new Case(caseToUpdate, { applicationContext }); + const currentDocument = caseEntity.getDocumentById({ + documentId: documentIdToEdit, + }); + + if (!currentDocument) { + throw new NotFoundError('Document not found'); + } + + if (documentMetadata.documentContents) { + const { documentContentsId } = currentDocument; + + const contentToStore = { + documentContents: documentMetadata.documentContents, + richText: documentMetadata.draftState.richText, + }; + + applicationContext.getPersistenceGateway().saveDocumentFromLambda({ + applicationContext, + document: Buffer.from(JSON.stringify(contentToStore)), + documentId: documentContentsId, + useTempBucket: true, + }); + + delete documentMetadata.documentContents; + delete documentMetadata.draftState.documentContents; + delete documentMetadata.draftState.richText; + delete documentMetadata.draftState.editorDelta; + } + + const editableFields = { + documentTitle: documentMetadata.documentTitle, + documentType: documentMetadata.documentType, + draftState: documentMetadata.draftState, + freeText: documentMetadata.freeText, + }; + const documentEntity = new Document( { - ...documentMetadata, + ...currentDocument, + ...editableFields, documentId: documentIdToEdit, - documentType: documentMetadata.documentType, filedBy: user.name, relationship: 'primaryDocument', userId: user.userId, diff --git a/shared/src/business/useCases/courtIssuedOrder/updateCourtIssuedOrderInteractor.test.js b/shared/src/business/useCases/courtIssuedOrder/updateCourtIssuedOrderInteractor.test.js index c8a1162e468..c4512235e25 100644 --- a/shared/src/business/useCases/courtIssuedOrder/updateCourtIssuedOrderInteractor.test.js +++ b/shared/src/business/useCases/courtIssuedOrder/updateCourtIssuedOrderInteractor.test.js @@ -13,6 +13,16 @@ describe('updateCourtIssuedOrderInteractor', () => { caseCaption: 'Caption', caseId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', caseType: 'Deficiency', + contactPrimary: { + address1: '123 Main St', + city: 'Somewhere', + countryType: 'domestic', + email: 'fieri@example.com', + name: 'Guy Fieri', + phone: '1234567890', + postalCode: '12345', + state: 'CA', + }, createdAt: '', docketNumber: '45678-18', docketRecord: [ @@ -27,19 +37,20 @@ describe('updateCourtIssuedOrderInteractor', () => { documents: [ { docketNumber: '45678-18', + documentContentsId: '442f46fd-727b-485c-8998-a0138593cebe', documentId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', documentType: 'Answer', userId: 'irsPractitioner', }, { docketNumber: '45678-18', - documentId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', + documentId: 'a75e4cc8-deed-42d0-b7b0-3846004fe3f9', documentType: 'Answer', userId: 'irsPractitioner', }, { docketNumber: '45678-18', - documentId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', + documentId: 'd3cc11ab-bbee-4d09-bc66-da267f3cfd07', documentType: 'Answer', userId: 'irsPractitioner', }, @@ -86,32 +97,122 @@ describe('updateCourtIssuedOrderInteractor', () => { ).rejects.toThrow('Unauthorized'); }); - it('update existing document within case', async () => { + it('should throw an error if document is not found', async () => { mockUser = new User({ name: 'Olivia Jade', role: User.ROLES.petitionsClerk, userId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', }); - let error; - try { - applicationContext.getPersistenceGateway().getUserById.mockResolvedValue({ - name: 'bob', - userId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', - }); + applicationContext.getPersistenceGateway().getUserById.mockResolvedValue({ + name: 'bob', + userId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', + }); - await updateCourtIssuedOrderInteractor({ + await expect( + updateCourtIssuedOrderInteractor({ applicationContext, + documentIdToEdit: '986fece3-6325-4418-bb28-a7095e6707b4', documentMetadata: { caseId: caseRecord.caseId, documentType: 'Order to Show Cause', }, - primaryDocumentFileId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', - }); - } catch (err) { - error = err; - } - expect(error).toBeUndefined(); + }), + ).rejects.toThrow('Document not found'); + }); + + it('update existing document within case', async () => { + mockUser = new User({ + name: 'Olivia Jade', + role: User.ROLES.petitionsClerk, + userId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', + }); + + applicationContext.getPersistenceGateway().getUserById.mockResolvedValue({ + name: 'bob', + userId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', + }); + + await updateCourtIssuedOrderInteractor({ + applicationContext, + documentIdToEdit: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', + documentMetadata: { + caseId: caseRecord.caseId, + documentType: 'Order to Show Cause', + }, + }); + + expect( + applicationContext.getPersistenceGateway().getCaseByCaseId, + ).toBeCalled(); + expect( + applicationContext.getPersistenceGateway().updateCase.mock.calls[0][0] + .caseToUpdate.documents.length, + ).toEqual(3); + }); + + it('stores documentContents in S3 if present', async () => { + mockUser = new User({ + name: 'Olivia Jade', + role: User.ROLES.petitionsClerk, + userId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', + }); + + applicationContext.getPersistenceGateway().getUserById.mockResolvedValue({ + name: 'bob', + userId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', + }); + + await updateCourtIssuedOrderInteractor({ + applicationContext, + documentIdToEdit: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', + documentMetadata: { + caseId: caseRecord.caseId, + documentContents: 'the contents!', + documentType: 'Order to Show Cause', + draftState: { + documentContents: 'the contents!', + richText: 'the contents!', + }, + richText: 'the contents!', + }, + }); + + expect( + applicationContext.getPersistenceGateway().saveDocumentFromLambda, + ).toBeCalled(); + expect( + applicationContext.getPersistenceGateway().updateCase.mock.calls[0][0] + .caseToUpdate.documents[2].documentContents, + ).toBeUndefined(); + expect( + applicationContext.getPersistenceGateway().updateCase.mock.calls[0][0] + .caseToUpdate.documents[2].draftState, + ).toBeUndefined(); + }); + + it('does not update non-editable fields on document', async () => { + mockUser = new User({ + name: 'Olivia Jade', + role: User.ROLES.petitionsClerk, + userId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', + }); + + applicationContext.getPersistenceGateway().getUserById.mockResolvedValue({ + name: 'bob', + userId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', + }); + + await updateCourtIssuedOrderInteractor({ + applicationContext, + documentIdToEdit: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', + documentMetadata: { + caseId: caseRecord.caseId, + documentType: 'Order to Show Cause', + judge: 'Judge Judgy', + }, + }); + expect( applicationContext.getPersistenceGateway().getCaseByCaseId, ).toBeCalled(); diff --git a/shared/src/business/useCases/courtIssuedOrder/validateOrderWithoutBodyInteractor.js b/shared/src/business/useCases/courtIssuedOrder/validateOrderWithoutBodyInteractor.js index fda3144b2f6..80e02ae0b57 100644 --- a/shared/src/business/useCases/courtIssuedOrder/validateOrderWithoutBodyInteractor.js +++ b/shared/src/business/useCases/courtIssuedOrder/validateOrderWithoutBodyInteractor.js @@ -1,3 +1,5 @@ +const { OrderWithoutBody } = require('../../entities/orders/OrderWithoutBody'); + /** * validateOrderWithoutBodyInteractor * @@ -10,9 +12,9 @@ exports.validateOrderWithoutBodyInteractor = ({ applicationContext, orderMetadata, }) => { - const orderWithoutBody = new (applicationContext.getEntityConstructors().OrderWithoutBody)( - orderMetadata, - ); + const orderWithoutBody = new OrderWithoutBody(orderMetadata, { + applicationContext, + }); return orderWithoutBody.getFormattedValidationErrors(); }; diff --git a/shared/src/business/useCases/courtIssuedOrder/validateOrderWithoutBodyInteractor.test.js b/shared/src/business/useCases/courtIssuedOrder/validateOrderWithoutBodyInteractor.test.js index 43cac7a6b88..2b8ef4fa343 100644 --- a/shared/src/business/useCases/courtIssuedOrder/validateOrderWithoutBodyInteractor.test.js +++ b/shared/src/business/useCases/courtIssuedOrder/validateOrderWithoutBodyInteractor.test.js @@ -1,3 +1,6 @@ +const { + applicationContext, +} = require('../../test/createTestApplicationContext'); const { validateOrderWithoutBodyInteractor, } = require('./validateOrderWithoutBodyInteractor'); @@ -8,11 +11,7 @@ const errorMessages = OrderWithoutBody.VALIDATION_ERROR_MESSAGES; describe('validateOrderWithoutBodyInteractor', () => { it('returns the expected errors object on an empty order object', () => { const errors = validateOrderWithoutBodyInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - OrderWithoutBody, - }), - }, + applicationContext, orderMetadata: {}, }); @@ -25,11 +24,7 @@ describe('validateOrderWithoutBodyInteractor', () => { it('returns no errors when a valid order object is passed through', async () => { const errors = await validateOrderWithoutBodyInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - OrderWithoutBody, - }), - }, + applicationContext, orderMetadata: { documentTitle: 'Order to Be Awesome', documentType: 'Order', diff --git a/shared/src/business/useCases/createCaseFromPaperInteractor.js b/shared/src/business/useCases/createCaseFromPaperInteractor.js index f6b82e12e7b..718468197d0 100644 --- a/shared/src/business/useCases/createCaseFromPaperInteractor.js +++ b/shared/src/business/useCases/createCaseFromPaperInteractor.js @@ -3,6 +3,7 @@ const { ROLE_PERMISSIONS, } = require('../../authorization/authorizationClientService'); const { Case } = require('../entities/cases/Case'); +const { CaseInternal } = require('../entities/cases/CaseInternal'); const { Document } = require('../entities/Document'); const { Message } = require('../entities/Message'); const { replaceBracketed } = require('../utilities/replaceBracketed'); @@ -22,12 +23,10 @@ const addPetitionDocumentWithWorkItemToCase = ({ assigneeId: user.userId, assigneeName: user.name, associatedJudge: caseToAdd.associatedJudge, - caseCaptionNames: Case.getCaseCaptionNames( - Case.getCaseCaption(caseToAdd), - ), caseId: caseToAdd.caseId, - caseIsInProgress: caseToAdd.inProgress, + caseIsInProgress: true, caseStatus: caseToAdd.status, + caseTitle: Case.getCaseTitle(Case.getCaseCaption(caseToAdd)), docketNumber: caseToAdd.docketNumber, docketNumberSuffix: caseToAdd.docketNumberSuffix, document: { @@ -96,7 +95,6 @@ exports.createCaseFromPaperInteractor = async ({ .getPersistenceGateway() .getUserById({ applicationContext, userId: authorizedUser.userId }); - const { CaseInternal } = applicationContext.getEntityConstructors(); const petitionEntity = new CaseInternal({ ...petitionMetadata, applicationForWaiverOfFilingFeeFileId, diff --git a/shared/src/business/useCases/createCaseInteractor.js b/shared/src/business/useCases/createCaseInteractor.js index 50fd2fc00de..bb63184733b 100644 --- a/shared/src/business/useCases/createCaseInteractor.js +++ b/shared/src/business/useCases/createCaseInteractor.js @@ -25,12 +25,10 @@ const addPetitionDocumentToCase = ({ assigneeId: null, assigneeName: null, associatedJudge: caseToAdd.associatedJudge, - caseCaptionNames: Case.getCaseCaptionNames( - Case.getCaseCaption(caseToAdd), - ), caseId: caseToAdd.caseId, caseIsInProgress: caseToAdd.inProgress, caseStatus: caseToAdd.status, + caseTitle: Case.getCaseTitle(Case.getCaseCaption(caseToAdd)), docketNumber: caseToAdd.docketNumber, docketNumberSuffix: caseToAdd.docketNumberSuffix, document: { @@ -47,8 +45,8 @@ const addPetitionDocumentToCase = ({ let message; - const caseCaptionNames = Case.getCaseCaptionNames(caseToAdd.caseCaption); - message = `${documentEntity.documentType} filed by ${caseCaptionNames} is ready for review.`; + const caseTitle = Case.getCaseTitle(caseToAdd.caseCaption); + message = `${documentEntity.documentType} filed by ${caseTitle} is ready for review.`; workItemEntity.addMessage( new Message( diff --git a/shared/src/business/useCases/docketEntry/fileCourtIssuedDocketEntryInteractor.js b/shared/src/business/useCases/docketEntry/fileCourtIssuedDocketEntryInteractor.js index 584ea4b643e..a0742602450 100644 --- a/shared/src/business/useCases/docketEntry/fileCourtIssuedDocketEntryInteractor.js +++ b/shared/src/business/useCases/docketEntry/fileCourtIssuedDocketEntryInteractor.js @@ -65,12 +65,14 @@ exports.fileCourtIssuedDocketEntryInteractor = async ({ { ...omit(document, 'filedBy'), attachments: documentMeta.attachments, + date: documentMeta.date, documentTitle: documentMeta.generatedDocumentTitle, documentType: documentMeta.documentType, eventCode: documentMeta.eventCode, filedBy: undefined, freeText: documentMeta.freeText, isFileAttached: true, + judge: documentMeta.judge, scenario: documentMeta.scenario, secondaryDate, serviceStamp: documentMeta.serviceStamp, @@ -84,12 +86,10 @@ exports.fileCourtIssuedDocketEntryInteractor = async ({ assigneeId: null, assigneeName: null, associatedJudge: caseToUpdate.associatedJudge, - caseCaptionNames: Case.getCaseCaptionNames( - Case.getCaseCaption(caseEntity), - ), caseId: caseId, caseIsInProgress: caseEntity.inProgress, caseStatus: caseToUpdate.status, + caseTitle: Case.getCaseTitle(Case.getCaseCaption(caseEntity)), docketNumber: caseToUpdate.docketNumber, docketNumberSuffix: caseToUpdate.docketNumberSuffix, document: { @@ -136,7 +136,7 @@ exports.fileCourtIssuedDocketEntryInteractor = async ({ documentId: documentEntity.documentId, editState: JSON.stringify(documentMeta), eventCode: documentEntity.eventCode, - filingDate: documentEntity.date || createISODateString(), + filingDate: documentEntity.filingDate || createISODateString(), }, { applicationContext }, ), diff --git a/shared/src/business/useCases/docketEntry/fileCourtIssuedDocketEntryInteractor.test.js b/shared/src/business/useCases/docketEntry/fileCourtIssuedDocketEntryInteractor.test.js index 1c340f0a6ad..fc6fb2b7b17 100644 --- a/shared/src/business/useCases/docketEntry/fileCourtIssuedDocketEntryInteractor.test.js +++ b/shared/src/business/useCases/docketEntry/fileCourtIssuedDocketEntryInteractor.test.js @@ -28,7 +28,14 @@ describe('fileCourtIssuedDocketEntryInteractor', () => { caseId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', caseType: 'Deficiency', contactPrimary: { + address1: '123 Main St', + city: 'Somewhere', + countryType: 'domestic', + email: 'fieri@example.com', name: 'Guy Fieri', + phone: '1234567890', + postalCode: '12345', + state: 'CA', }, createdAt: '', docketNumber: '45678-18', diff --git a/shared/src/business/useCases/docketEntry/fileDocketEntryInteractor.js b/shared/src/business/useCases/docketEntry/fileDocketEntryInteractor.js index 3204bbdddc1..90476f41ead 100644 --- a/shared/src/business/useCases/docketEntry/fileDocketEntryInteractor.js +++ b/shared/src/business/useCases/docketEntry/fileDocketEntryInteractor.js @@ -117,12 +117,10 @@ exports.fileDocketEntryInteractor = async ({ assigneeId: null, assigneeName: null, associatedJudge: caseToUpdate.associatedJudge, - caseCaptionNames: Case.getCaseCaptionNames( - Case.getCaseCaption(caseEntity), - ), caseId: caseId, caseIsInProgress: caseEntity.inProgress, caseStatus: caseToUpdate.status, + caseTitle: Case.getCaseTitle(Case.getCaseCaption(caseEntity)), docketNumber: caseToUpdate.docketNumber, docketNumberSuffix: caseToUpdate.docketNumberSuffix, document: { diff --git a/shared/src/business/useCases/docketEntry/fileDocketEntryInteractor.test.js b/shared/src/business/useCases/docketEntry/fileDocketEntryInteractor.test.js index dd8cd79311e..4749d4dec21 100644 --- a/shared/src/business/useCases/docketEntry/fileDocketEntryInteractor.test.js +++ b/shared/src/business/useCases/docketEntry/fileDocketEntryInteractor.test.js @@ -21,7 +21,14 @@ describe('fileDocketEntryInteractor', () => { caseId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', caseType: 'Deficiency', contactPrimary: { + address1: '123 Main St', + city: 'Somewhere', + countryType: 'domestic', + email: 'fieri@example.com', name: 'Guy Fieri', + phone: '1234567890', + postalCode: '12345', + state: 'CA', }, createdAt: '', docketNumber: '45678-18', diff --git a/shared/src/business/useCases/docketEntry/updateCourtIssuedDocketEntryInteractor.js b/shared/src/business/useCases/docketEntry/updateCourtIssuedDocketEntryInteractor.js index bd0443fdbdc..e5f08a73f9a 100644 --- a/shared/src/business/useCases/docketEntry/updateCourtIssuedDocketEntryInteractor.js +++ b/shared/src/business/useCases/docketEntry/updateCourtIssuedDocketEntryInteractor.js @@ -57,17 +57,25 @@ exports.updateCourtIssuedDocketEntryInteractor = async ({ secondaryDate = documentMeta.date; } + const editableFields = { + attachments: documentMeta.attachments, + date: documentMeta.date, + docketNumbers: documentMeta.docketNumbers, + documentTitle: documentMeta.generatedDocumentTitle, + documentType: documentMeta.documentType, + eventCode: documentMeta.eventCode, + freeText: documentMeta.freeText, + judge: documentMeta.judge, + scenario: documentMeta.scenario, + serviceStamp: documentMeta.serviceStamp, + trialLocation: documentMeta.trialLocation, + }; + const documentEntity = new Document( { ...currentDocument, - attachments: documentMeta.attachments, - documentTitle: documentMeta.generatedDocumentTitle, - documentType: documentMeta.documentType, - eventCode: documentMeta.eventCode, - freeText: documentMeta.freeText, - scenario: documentMeta.scenario, + ...editableFields, secondaryDate, - serviceStamp: documentMeta.serviceStamp, userId: user.userId, }, { applicationContext }, @@ -80,9 +88,9 @@ exports.updateCourtIssuedDocketEntryInteractor = async ({ const docketRecordEntry = new DocketRecord( { ...existingDocketRecordEntry, - description: documentMeta.generatedDocumentTitle, + description: editableFields.documentTitle, documentId: documentEntity.documentId, - editState: JSON.stringify(documentMeta), + editState: JSON.stringify(editableFields), eventCode: documentEntity.eventCode, filingDate: documentEntity.receivedAt, }, diff --git a/shared/src/business/useCases/docketEntry/updateCourtIssuedDocketEntryInteractor.test.js b/shared/src/business/useCases/docketEntry/updateCourtIssuedDocketEntryInteractor.test.js index 49abcb21ce6..b4aed19525c 100644 --- a/shared/src/business/useCases/docketEntry/updateCourtIssuedDocketEntryInteractor.test.js +++ b/shared/src/business/useCases/docketEntry/updateCourtIssuedDocketEntryInteractor.test.js @@ -15,7 +15,14 @@ describe('updateCourtIssuedDocketEntryInteractor', () => { caseId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', caseType: 'Deficiency', contactPrimary: { + address1: '123 Main St', + city: 'Somewhere', + countryType: 'domestic', + email: 'fieri@example.com', name: 'Guy Fieri', + phone: '1234567890', + postalCode: '12345', + state: 'CA', }, createdAt: '', docketNumber: '45678-18', @@ -32,13 +39,13 @@ describe('updateCourtIssuedDocketEntryInteractor', () => { documents: [ { docketNumber: '45678-18', - documentId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', + documentId: '30413c1e-9a71-4c22-8c11-41f8689313ae', documentType: 'Answer', userId: 'irsPractitioner', }, { docketNumber: '45678-18', - documentId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', + documentId: 'e27d2d4e-f768-4167-b2c9-989dccbbb738', documentType: 'Answer', userId: 'irsPractitioner', }, @@ -57,9 +64,9 @@ describe('updateCourtIssuedDocketEntryInteractor', () => { { assigneeId: 'bob', assigneeName: 'bob', - caseCaptionNames: 'testing', caseId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', caseStatus: Case.STATUS_TYPES.new, + caseTitle: 'Johnny Joe Jacobson', docketNumber: '101-18', docketNumberSuffix: 'S', document: {}, @@ -205,4 +212,30 @@ describe('updateCourtIssuedDocketEntryInteractor', () => { secondaryDate: '2019-03-01T21:40:46.415Z', }); }); + + it('should not update non-editable fields on the document', async () => { + applicationContext.getCurrentUser.mockReturnValue({ + name: 'Olivia Jade', + role: User.ROLES.docketClerk, + userId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', + }); + + await updateCourtIssuedDocketEntryInteractor({ + applicationContext, + documentMeta: { + caseId: caseRecord.caseId, + documentId: 'c54ba5a9-b37b-479d-9201-067ec6e335ba', + documentType: 'Order', + objections: 'No', + }, + }); + + expect( + applicationContext.getPersistenceGateway().updateCase, + ).toHaveBeenCalled(); + expect( + applicationContext.getPersistenceGateway().updateCase.mock.calls[0][0] + .caseToUpdate.documents[3].objections, + ).toBeUndefined(); + }); }); diff --git a/shared/src/business/useCases/docketEntry/updateDocketEntryInteractor.test.js b/shared/src/business/useCases/docketEntry/updateDocketEntryInteractor.test.js index ecfd52eb510..bf8a580276a 100644 --- a/shared/src/business/useCases/docketEntry/updateDocketEntryInteractor.test.js +++ b/shared/src/business/useCases/docketEntry/updateDocketEntryInteractor.test.js @@ -26,6 +26,16 @@ describe('updateDocketEntryInteractor', () => { caseCaption: 'Caption', caseId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', caseType: 'Deficiency', + contactPrimary: { + address1: '123 Main St', + city: 'Somewhere', + countryType: 'domestic', + email: 'fieri@example.com', + name: 'Guy Fieri', + phone: '1234567890', + postalCode: '12345', + state: 'CA', + }, createdAt: '', docketNumber: '45678-18', docketRecord: [ diff --git a/shared/src/business/useCases/docketEntry/updateDocketEntryMetaInteractor.js b/shared/src/business/useCases/docketEntry/updateDocketEntryMetaInteractor.js index 6b0aaecf9a0..99c1d47bf58 100644 --- a/shared/src/business/useCases/docketEntry/updateDocketEntryMetaInteractor.js +++ b/shared/src/business/useCases/docketEntry/updateDocketEntryMetaInteractor.js @@ -54,6 +54,7 @@ exports.updateDocketEntryMetaInteractor = async ({ attachments, certificateOfService, certificateOfServiceDate, + date, description, documentTitle, documentType, @@ -97,6 +98,7 @@ exports.updateDocketEntryMetaInteractor = async ({ attachments || certificateOfServiceDate || certificateOfService || + date || documentType || eventCode || newFiledBy || @@ -145,6 +147,7 @@ exports.updateDocketEntryMetaInteractor = async ({ ? certificateOfService : documentDetail.certificateOfService, certificateOfServiceDate: newCertificateOfServiceDate, + date: date || documentDetail.date, documentTitle: documentTitle || documentDetail.documentTitle, // setting to null will regenerate it for the coversheet documentType: documentType || documentDetail.documentType, eventCode: eventCode || documentDetail.eventCode, diff --git a/shared/src/business/useCases/docketEntry/updateDocketEntryMetaInteractor.test.js b/shared/src/business/useCases/docketEntry/updateDocketEntryMetaInteractor.test.js index 9ba4a00daf7..4542caa32be 100644 --- a/shared/src/business/useCases/docketEntry/updateDocketEntryMetaInteractor.test.js +++ b/shared/src/business/useCases/docketEntry/updateDocketEntryMetaInteractor.test.js @@ -18,7 +18,7 @@ describe('updateDocketEntryMetaInteractor', () => { documentType: 'Order', filingDate: '2019-01-01T00:01:00.000Z', servedAt: '2019-01-01T00:01:00.000Z', - servedParties: ['Some Party'], + servedParties: [{ name: 'Some Party' }], userId: 'abcba5a9-b37b-479d-9201-067ec6e33abc', }, { @@ -26,7 +26,7 @@ describe('updateDocketEntryMetaInteractor', () => { documentType: 'Order', filingDate: '2019-01-01T00:01:00.000Z', servedAt: '2019-01-02T00:01:00.000Z', - servedParties: ['Some Other Party'], + servedParties: [{ name: 'Some Other Party' }], userId: 'abcba5a9-b37b-479d-9201-067ec6e33abc', }, ]; @@ -271,7 +271,7 @@ describe('updateDocketEntryMetaInteractor', () => { certificateOfServiceDate: null, description: 'Request for Place of Trial at Houston, Texas', eventCode: 'RQT', - filingDate: '2020-02-03', + filingDate: '2020-02-03T08:06:07.539Z', }, docketRecordIndex: 2, }), diff --git a/shared/src/business/useCases/docketEntry/validateDocketEntryInteractor.js b/shared/src/business/useCases/docketEntry/validateDocketEntryInteractor.js index 83aa8ed9877..6b44be1d77f 100644 --- a/shared/src/business/useCases/docketEntry/validateDocketEntryInteractor.js +++ b/shared/src/business/useCases/docketEntry/validateDocketEntryInteractor.js @@ -1,3 +1,7 @@ +const { + DocketEntryFactory, +} = require('../../entities/docketEntry/DocketEntryFactory'); + /** * validateDocketEntryInteractor * @@ -10,9 +14,7 @@ exports.validateDocketEntryInteractor = ({ applicationContext, entryMetadata, }) => { - const docketEntry = applicationContext - .getEntityConstructors() - .DocketEntryFactory(entryMetadata); + const docketEntry = DocketEntryFactory(entryMetadata, { applicationContext }); return docketEntry.getFormattedValidationErrors(); }; diff --git a/shared/src/business/useCases/docketEntry/validateDocketEntryInteractor.test.js b/shared/src/business/useCases/docketEntry/validateDocketEntryInteractor.test.js index 50a95a559cf..f7a30eea2d7 100644 --- a/shared/src/business/useCases/docketEntry/validateDocketEntryInteractor.test.js +++ b/shared/src/business/useCases/docketEntry/validateDocketEntryInteractor.test.js @@ -1,3 +1,6 @@ +const { + applicationContext, +} = require('../../test/createTestApplicationContext'); const { DocketEntryFactory, } = require('../../entities/docketEntry/DocketEntryFactory'); @@ -10,11 +13,7 @@ const { VALIDATION_ERROR_MESSAGES } = DocketEntryFactory; describe('validateDocketEntryInteractor', () => { it('returns the expected errors object on an empty message', () => { const errors = validateDocketEntryInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - DocketEntryFactory, - }), - }, + applicationContext, entryMetadata: {}, }); @@ -28,14 +27,10 @@ describe('validateDocketEntryInteractor', () => { it('returns no errors when valid docket entry is passed through', () => { const errors = validateDocketEntryInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - DocketEntryFactory, - }), - }, + applicationContext, entryMetadata: { category: 'Answer', - dateReceived: '1212-12-12', + dateReceived: '1987-08-06T07:53:09.001Z', documentTitle: '[First, Second, etc.] Amendment to Answer', documentType: 'Amendment to Answer', eventCode: 'ATAN', diff --git a/shared/src/business/useCases/document/getPdfFromUrlInteractor.js b/shared/src/business/useCases/document/getPdfFromUrlInteractor.js new file mode 100644 index 00000000000..b2c7df3b829 --- /dev/null +++ b/shared/src/business/useCases/document/getPdfFromUrlInteractor.js @@ -0,0 +1,15 @@ +/** + * Retrieves a pdf from persistence from the url provided + * + * @param {object} providers the providers object + * @param {object} providers.applicationContext the application context + * @param {object} providers.pdfUrl the url to the pdf to retrieve + * @returns {object} the pdf file + */ +exports.getPdfFromUrlInteractor = async ({ applicationContext, pdfUrl }) => { + const pdfFile = await applicationContext + .getPersistenceGateway() + .getPdfFromUrl({ applicationContext, url: pdfUrl }); + + return { pdfFile }; +}; diff --git a/shared/src/business/useCases/document/getPdfFromUrlInteractor.test.js b/shared/src/business/useCases/document/getPdfFromUrlInteractor.test.js new file mode 100644 index 00000000000..4cd158e9251 --- /dev/null +++ b/shared/src/business/useCases/document/getPdfFromUrlInteractor.test.js @@ -0,0 +1,26 @@ +const { + applicationContext, +} = require('../../test/createTestApplicationContext'); +const { getPdfFromUrlInteractor } = require('./getPdfFromUrlInteractor'); + +describe('getPdfFromUrlInteractor', () => { + it('should return the pdf from persistence', async () => { + const mockUrl = 'www.example.com'; + const mockFile = { + name: 'mockfile.pdf', + }; + applicationContext + .getPersistenceGateway() + .getPdfFromUrl.mockReturnValue(mockFile); + + const result = await getPdfFromUrlInteractor({ + applicationContext, + pdfUrl: mockUrl, + }); + + expect( + applicationContext.getPersistenceGateway().getPdfFromUrl.mock.calls[0][0], + ).toMatchObject({ url: mockUrl }); + expect(result.pdfFile).toBe(mockFile); + }); +}); diff --git a/shared/src/business/useCases/editDocketEntry/completeDocketEntryQCInteractor.test.js b/shared/src/business/useCases/editDocketEntry/completeDocketEntryQCInteractor.test.js index 34430ae10eb..a4c9598869b 100644 --- a/shared/src/business/useCases/editDocketEntry/completeDocketEntryQCInteractor.test.js +++ b/shared/src/business/useCases/editDocketEntry/completeDocketEntryQCInteractor.test.js @@ -40,6 +40,16 @@ describe('completeDocketEntryQCInteractor', () => { caseCaption: 'Caption', caseId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', caseType: 'Deficiency', + contactPrimary: { + address1: '123 Main St', + city: 'Somewhere', + countryType: 'domestic', + email: 'fieri@example.com', + name: 'Guy Fieri', + phone: '1234567890', + postalCode: '12345', + state: 'CA', + }, createdAt: '', docketNumber: '45678-18', docketRecord: [ @@ -173,29 +183,23 @@ describe('completeDocketEntryQCInteractor', () => { countryType: 'domestic', email: 'test@example.com', name: 'Test Petitioner', + phone: '1234567890', postalCode: '12345', state: 'AK', }; - let result, error; - - try { - result = await completeDocketEntryQCInteractor({ - applicationContext, - entryMetadata: { - caseId: caseRecord.caseId, - description: 'Memorandum in Support', - documentId: 'fffba5a9-b37b-479d-9201-067ec6e335bb', - documentTitle: 'Something Else', - documentType: 'Memorandum in Support', - eventCode: 'MISP', - }, - }); - } catch (err) { - error = err; - } + const result = await completeDocketEntryQCInteractor({ + applicationContext, + entryMetadata: { + caseId: caseRecord.caseId, + description: 'Memorandum in Support', + documentId: 'fffba5a9-b37b-479d-9201-067ec6e335bb', + documentTitle: 'Something Else', + documentType: 'Memorandum in Support', + eventCode: 'MISP', + }, + }); - expect(error).toBeUndefined(); expect( applicationContext.getPersistenceGateway().getCaseByCaseId, ).toBeCalled(); @@ -293,25 +297,18 @@ describe('completeDocketEntryQCInteractor', () => { caseRecord.isPaper = true; caseRecord.mailingDate = '2019-03-01T21:40:46.415Z'; - let error; - let result; + const result = await completeDocketEntryQCInteractor({ + applicationContext, + entryMetadata: { + caseId: caseRecord.caseId, + description: 'Memorandum in Support', + documentId: 'fffba5a9-b37b-479d-9201-067ec6e335bb', + documentTitle: 'Something Else', + documentType: 'Memorandum in Support', + eventCode: 'MISP', + }, + }); - try { - result = await completeDocketEntryQCInteractor({ - applicationContext, - entryMetadata: { - caseId: caseRecord.caseId, - description: 'Memorandum in Support', - documentId: 'fffba5a9-b37b-479d-9201-067ec6e335bb', - documentTitle: 'Something Else', - documentType: 'Memorandum in Support', - eventCode: 'MISP', - }, - }); - } catch (err) { - error = err; - } - expect(error).toBeUndefined(); expect( applicationContext.getPersistenceGateway().getCaseByCaseId, ).toBeCalled(); @@ -339,25 +336,18 @@ describe('completeDocketEntryQCInteractor', () => { caseRecord.isPaper = true; caseRecord.mailingDate = '2019-03-01T21:40:46.415Z'; - let error; - let result; + const result = await completeDocketEntryQCInteractor({ + applicationContext, + entryMetadata: { + caseId: caseRecord.caseId, + description: 'Memorandum in Support', + documentId: 'fffba5a9-b37b-479d-9201-067ec6e335bb', + documentTitle: 'Notice of Change of Address', + documentType: 'Notice of Change of Address', + eventCode: 'MISP', + }, + }); - try { - result = await completeDocketEntryQCInteractor({ - applicationContext, - entryMetadata: { - caseId: caseRecord.caseId, - description: 'Memorandum in Support', - documentId: 'fffba5a9-b37b-479d-9201-067ec6e335bb', - documentTitle: 'Notice of Change of Address', - documentType: 'Notice of Change of Address', - eventCode: 'MISP', - }, - }); - } catch (err) { - error = err; - } - expect(error).toBeUndefined(); expect( applicationContext.getPersistenceGateway().getCaseByCaseId, ).toBeCalled(); @@ -384,25 +374,18 @@ describe('completeDocketEntryQCInteractor', () => { state: 'AK', }; - let error; - let result; + const result = await completeDocketEntryQCInteractor({ + applicationContext, + entryMetadata: { + caseId: caseRecord.caseId, + description: 'Memorandum in Support', + documentId: 'fffba5a9-b37b-479d-9201-067ec6e335bb', + documentTitle: 'Notice of Change of Address', + documentType: 'Notice of Change of Address', + eventCode: 'NCA', + }, + }); - try { - result = await completeDocketEntryQCInteractor({ - applicationContext, - entryMetadata: { - caseId: caseRecord.caseId, - description: 'Memorandum in Support', - documentId: 'fffba5a9-b37b-479d-9201-067ec6e335bb', - documentTitle: 'Notice of Change of Address', - documentType: 'Notice of Change of Address', - eventCode: 'NCA', - }, - }); - } catch (err) { - error = err; - } - expect(error).toBeUndefined(); expect( applicationContext.getPersistenceGateway().getCaseByCaseId, ).toBeCalled(); diff --git a/shared/src/business/useCases/editDocketEntry/saveIntermediateDocketEntryInteractor.test.js b/shared/src/business/useCases/editDocketEntry/saveIntermediateDocketEntryInteractor.test.js index 20e2cba289d..5572bb0c812 100644 --- a/shared/src/business/useCases/editDocketEntry/saveIntermediateDocketEntryInteractor.test.js +++ b/shared/src/business/useCases/editDocketEntry/saveIntermediateDocketEntryInteractor.test.js @@ -26,6 +26,16 @@ describe('saveIntermediateDocketEntryInteractor', () => { caseCaption: 'Caption', caseId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', caseType: 'Deficiency', + contactPrimary: { + address1: '123 Main St', + city: 'Somewhere', + countryType: 'domestic', + email: 'fieri@example.com', + name: 'Guy Fieri', + phone: '1234567890', + postalCode: '12345', + state: 'CA', + }, createdAt: '', docketNumber: '45678-18', docketRecord: [ diff --git a/shared/src/business/useCases/externalDocument/fileExternalDocumentForConsolidatedInteractor.js b/shared/src/business/useCases/externalDocument/fileExternalDocumentForConsolidatedInteractor.js index 4489b5f73da..2d6addaf57c 100644 --- a/shared/src/business/useCases/externalDocument/fileExternalDocumentForConsolidatedInteractor.js +++ b/shared/src/business/useCases/externalDocument/fileExternalDocumentForConsolidatedInteractor.js @@ -172,12 +172,10 @@ exports.fileExternalDocumentForConsolidatedInteractor = async ({ assigneeId: null, assigneeName: null, associatedJudge: caseEntity.associatedJudge, - caseCaptionNames: Case.getCaseCaptionNames( - Case.getCaseCaption(caseEntity), - ), caseId: caseEntity.caseId, caseIsInProgress: caseEntity.inProgress, caseStatus: caseEntity.status, + caseTitle: Case.getCaseTitle(Case.getCaseCaption(caseEntity)), docketNumber: caseEntity.docketNumber, docketNumberSuffix: caseEntity.docketNumberSuffix, document: { diff --git a/shared/src/business/useCases/externalDocument/fileExternalDocumentForConsolidatedInteractor.test.js b/shared/src/business/useCases/externalDocument/fileExternalDocumentForConsolidatedInteractor.test.js index 4001893da5e..7cc483b8f5d 100644 --- a/shared/src/business/useCases/externalDocument/fileExternalDocumentForConsolidatedInteractor.test.js +++ b/shared/src/business/useCases/externalDocument/fileExternalDocumentForConsolidatedInteractor.test.js @@ -26,8 +26,14 @@ describe('fileExternalDocumentForConsolidatedInteractor', () => { caseId: caseId0, caseType: 'Deficiency', contactPrimary: { + address1: '123 Main St', + city: 'Somewhere', + countryType: 'domestic', email: 'fieri@example.com', name: 'Guy Fieri', + phone: '1234567890', + postalCode: '12345', + state: 'CA', }, createdAt: '2019-04-19T17:29:13.120Z', docketNumber: '123-19', @@ -46,8 +52,14 @@ describe('fileExternalDocumentForConsolidatedInteractor', () => { caseId: caseId1, caseType: 'Deficiency', contactPrimary: { + address1: '123 Main St', + city: 'Somewhere', + countryType: 'domestic', email: 'ferrari@example.com', name: 'Enzo Ferrari', + phone: '1234567890', + postalCode: '12345', + state: 'CA', }, createdAt: '2019-04-19T17:29:13.120Z', docketNumber: '234-19', @@ -66,8 +78,14 @@ describe('fileExternalDocumentForConsolidatedInteractor', () => { caseId: caseId2, caseType: 'Deficiency', contactPrimary: { + address1: '123 Main St', + city: 'Somewhere', + countryType: 'domestic', email: 'foreman@example.com', name: 'George Foreman', + phone: '1234567890', + postalCode: '12345', + state: 'CA', }, createdAt: '2019-04-19T17:29:13.120Z', docketNumber: '345-19', diff --git a/shared/src/business/useCases/externalDocument/fileExternalDocumentInteractor.js b/shared/src/business/useCases/externalDocument/fileExternalDocumentInteractor.js index fe389695009..570fb9fd59f 100644 --- a/shared/src/business/useCases/externalDocument/fileExternalDocumentInteractor.js +++ b/shared/src/business/useCases/externalDocument/fileExternalDocumentInteractor.js @@ -134,12 +134,10 @@ exports.fileExternalDocumentInteractor = async ({ assigneeId: null, assigneeName: null, associatedJudge: caseToUpdate.associatedJudge, - caseCaptionNames: Case.getCaseCaptionNames( - Case.getCaseCaption(caseEntity), - ), caseId: caseId, caseIsInProgress: caseEntity.inProgress, caseStatus: caseToUpdate.status, + caseTitle: Case.getCaseTitle(Case.getCaseCaption(caseEntity)), docketNumber: caseToUpdate.docketNumber, docketNumberSuffix: caseToUpdate.docketNumberSuffix, document: { diff --git a/shared/src/business/useCases/externalDocument/fileExternalDocumentInteractor.test.js b/shared/src/business/useCases/externalDocument/fileExternalDocumentInteractor.test.js index 6ebc3e9e1df..2e9c1815d93 100644 --- a/shared/src/business/useCases/externalDocument/fileExternalDocumentInteractor.test.js +++ b/shared/src/business/useCases/externalDocument/fileExternalDocumentInteractor.test.js @@ -18,8 +18,14 @@ describe('fileExternalDocumentInteractor', () => { caseId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', caseType: 'Deficiency', contactPrimary: { + address1: '123 Main St', + city: 'Somewhere', + countryType: 'domestic', email: 'fieri@example.com', name: 'Guy Fieri', + phone: '1234567890', + postalCode: '12345', + state: 'CA', }, createdAt: '', docketNumber: '45678-18', @@ -97,25 +103,18 @@ describe('fileExternalDocumentInteractor', () => { }); it('should add documents and workitems and auto-serve the documents on the parties with an electronic service indicator', async () => { - let error; + const updatedCase = await fileExternalDocumentInteractor({ + applicationContext, + documentIds: ['c54ba5a9-b37b-479d-9201-067ec6e335bb'], + documentMetadata: { + caseId: caseRecord.caseId, + docketNumber: '45678-18', + documentTitle: 'Memorandum in Support', + documentType: 'Memorandum in Support', + eventCode: 'A', + }, + }); - let updatedCase; - try { - updatedCase = await fileExternalDocumentInteractor({ - applicationContext, - documentIds: ['c54ba5a9-b37b-479d-9201-067ec6e335bb'], - documentMetadata: { - caseId: caseRecord.caseId, - docketNumber: '45678-18', - documentTitle: 'Memorandum in Support', - documentType: 'Memorandum in Support', - eventCode: 'A', - }, - }); - } catch (err) { - error = err; - } - expect(error).toBeUndefined(); expect( applicationContext.getPersistenceGateway().getCaseByCaseId, ).toBeCalled(); @@ -126,7 +125,6 @@ describe('fileExternalDocumentInteractor', () => { expect( applicationContext.getUseCaseHelpers().sendServedPartiesEmails, ).toHaveBeenCalled(); - expect(updatedCase.documents[3].status).toEqual('served'); expect(updatedCase.documents[3].servedAt).toBeDefined(); }); diff --git a/shared/src/business/useCases/externalDocument/generateDocumentTitleInteractor.js b/shared/src/business/useCases/externalDocument/generateDocumentTitleInteractor.js index b5a8c0884d2..718909a6730 100644 --- a/shared/src/business/useCases/externalDocument/generateDocumentTitleInteractor.js +++ b/shared/src/business/useCases/externalDocument/generateDocumentTitleInteractor.js @@ -1,3 +1,7 @@ +const { + ExternalDocumentFactory, +} = require('../../entities/externalDocument/ExternalDocumentFactory'); + /** * generateDocumentTitleInteractor * @@ -10,8 +14,8 @@ exports.generateDocumentTitleInteractor = ({ applicationContext, documentMetadata, }) => { - const externalDocument = applicationContext - .getEntityConstructors() - .ExternalDocumentFactory.get(documentMetadata); + const externalDocument = ExternalDocumentFactory.get(documentMetadata, { + applicationContext, + }); return externalDocument.getDocumentTitle(); }; diff --git a/shared/src/business/useCases/externalDocument/validateExternalDocumentInformationInteractor.js b/shared/src/business/useCases/externalDocument/validateExternalDocumentInformationInteractor.js index e4391ff7468..f1bb276eceb 100644 --- a/shared/src/business/useCases/externalDocument/validateExternalDocumentInformationInteractor.js +++ b/shared/src/business/useCases/externalDocument/validateExternalDocumentInformationInteractor.js @@ -1,3 +1,7 @@ +const { + ExternalDocumentInformationFactory, +} = require('../../entities/externalDocument/ExternalDocumentInformationFactory'); + /** * validateExternalDocumentInformationInteractor * @@ -10,9 +14,10 @@ exports.validateExternalDocumentInformationInteractor = ({ applicationContext, documentMetadata, }) => { - const externalDocument = applicationContext - .getEntityConstructors() - .ExternalDocumentInformationFactory.get(documentMetadata); + const externalDocument = ExternalDocumentInformationFactory.get( + documentMetadata, + { applicationContext }, + ); return externalDocument.getFormattedValidationErrors(); }; diff --git a/shared/src/business/useCases/externalDocument/validateExternalDocumentInformationInteractor.test.js b/shared/src/business/useCases/externalDocument/validateExternalDocumentInformationInteractor.test.js index 37b6b15f10f..198cd5161b2 100644 --- a/shared/src/business/useCases/externalDocument/validateExternalDocumentInformationInteractor.test.js +++ b/shared/src/business/useCases/externalDocument/validateExternalDocumentInformationInteractor.test.js @@ -1,28 +1,39 @@ +const { + applicationContext, +} = require('../../test/createTestApplicationContext'); const { validateExternalDocumentInformationInteractor, } = require('./validateExternalDocumentInformationInteractor'); +const { + VALIDATION_ERROR_MESSAGES, +} = require('../../entities/externalDocument/ExternalDocumentInformationFactory'); describe('validateExternalDocumentInformationInteractor', () => { - let ExternalDocumentInformationFactory; - let spy; + it('returns the expected errors object on an empty message', () => { + const errors = validateExternalDocumentInformationInteractor({ + applicationContext, + documentMetadata: {}, + }); - beforeEach(() => { - spy = jest.fn().mockReturnValue(null); - ExternalDocumentInformationFactory = { - get: () => ({ - getFormattedValidationErrors: spy, - }), - }; + expect(errors).toEqual({ + attachments: VALIDATION_ERROR_MESSAGES.attachments, + certificateOfService: VALIDATION_ERROR_MESSAGES.certificateOfService, + hasSupportingDocuments: VALIDATION_ERROR_MESSAGES.hasSupportingDocuments, + partyPrimary: VALIDATION_ERROR_MESSAGES.partyPrimary, + primaryDocumentFile: VALIDATION_ERROR_MESSAGES.primaryDocumentFile, + }); }); - it('calls external document information factory to get validation errors', () => { + it('returns no errors when all fields are defined', () => { const errors = validateExternalDocumentInformationInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - ExternalDocumentInformationFactory, - }), + applicationContext, + documentMetadata: { + attachments: false, + certificateOfService: false, + hasSupportingDocuments: false, + partyPrimary: true, + primaryDocumentFile: { file: 'yes!' }, }, - documentMetadata: {}, }); expect(errors).toEqual(null); diff --git a/shared/src/business/useCases/externalDocument/validateExternalDocumentInteractor.js b/shared/src/business/useCases/externalDocument/validateExternalDocumentInteractor.js index 3a3c074d45e..56a42f65357 100644 --- a/shared/src/business/useCases/externalDocument/validateExternalDocumentInteractor.js +++ b/shared/src/business/useCases/externalDocument/validateExternalDocumentInteractor.js @@ -1,3 +1,7 @@ +const { + ExternalDocumentFactory, +} = require('../../entities/externalDocument/ExternalDocumentFactory'); + /** * validateExternalDocumentInteractor * @@ -10,9 +14,9 @@ exports.validateExternalDocumentInteractor = ({ applicationContext, documentMetadata, }) => { - const externalDocument = applicationContext - .getEntityConstructors() - .ExternalDocumentFactory.get(documentMetadata); + const externalDocument = ExternalDocumentFactory.get(documentMetadata, { + applicationContext, + }); return externalDocument.getFormattedValidationErrors(); }; diff --git a/shared/src/business/useCases/externalDocument/validateExternalDocumentInteractor.test.js b/shared/src/business/useCases/externalDocument/validateExternalDocumentInteractor.test.js index 54c736f7c2c..22e4a07e2db 100644 --- a/shared/src/business/useCases/externalDocument/validateExternalDocumentInteractor.test.js +++ b/shared/src/business/useCases/externalDocument/validateExternalDocumentInteractor.test.js @@ -1,6 +1,6 @@ const { - ExternalDocumentFactory, -} = require('../../entities/externalDocument/ExternalDocumentFactory'); + applicationContext, +} = require('../../test/createTestApplicationContext'); const { validateExternalDocumentInteractor, } = require('./validateExternalDocumentInteractor'); @@ -11,11 +11,7 @@ const { describe('validateExternalDocumentInteractor', () => { it('returns the expected errors object on an empty message', () => { const errors = validateExternalDocumentInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - ExternalDocumentFactory, - }), - }, + applicationContext, documentMetadata: {}, }); @@ -27,11 +23,7 @@ describe('validateExternalDocumentInteractor', () => { it('returns no errors when all fields are defined', () => { const errors = validateExternalDocumentInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - ExternalDocumentFactory, - }), - }, + applicationContext, documentMetadata: { category: 'Application', documentType: 'Application for Waiver of Filing Fee', diff --git a/shared/src/business/useCases/generateDocketRecordPdfInteractor.js b/shared/src/business/useCases/generateDocketRecordPdfInteractor.js index bee99e9b4aa..91b6af9befb 100644 --- a/shared/src/business/useCases/generateDocketRecordPdfInteractor.js +++ b/shared/src/business/useCases/generateDocketRecordPdfInteractor.js @@ -1,5 +1,5 @@ const { Case } = require('../entities/cases/Case'); -const { ContactFactory } = require('../entities/contacts/ContactFactory'); +const { getCaseCaptionMeta } = require('../utilities/getCaseCaptionMeta'); /** * generateDocketRecordPdfInteractor @@ -13,7 +13,6 @@ exports.generateDocketRecordPdfInteractor = async ({ applicationContext, caseId, docketRecordSort, - includePartyDetail = false, }) => { const caseSource = await applicationContext .getPersistenceGateway() @@ -30,245 +29,23 @@ exports.generateDocketRecordPdfInteractor = async ({ caseDetail: caseEntity, docketRecordSort, }); - formattedCaseDetail.showCaseNameForPrimary = caseEntity.getShowCaseNameForPrimary(); - const getPartyInfoContent = detail => { - const { - contactPrimary, - contactSecondary, - irsPractitioners, - privatePractitioners, - } = detail; + const { caseCaptionExtension, caseTitle } = getCaseCaptionMeta(caseEntity); - const getAddress = contact => { - const isInternational = - contact.countryType === ContactFactory.COUNTRY_TYPES.INTERNATIONAL; - - let content = ` - ${contact.inCareOf ? `
${contact.inCareOf}
` : ''} - ${contact.title ? `
${contact.title}
` : ''} - ${contact.address1 ? `
${contact.address1}
` : ''} - ${contact.address2 ? `
${contact.address2}
` : ''} - ${contact.address3 ? `
${contact.address3}
` : ''} -
- ${contact.city ? `${contact.city}, ` : ''} - ${contact.state ? `${contact.state}, ` : ''} - ${contact.postalCode ? `${contact.postalCode}, ` : ''} -
- ${isInternational ? contact.country : ''} - ${contact.phone ? `

${contact.phone}

` : ''} - `; - - return content; - }; - - const getContactPrimary = () => { - const name = detail.showCaseNameForPrimary - ? detail.caseName - : contactPrimary.name; - - return ` -
-

${name}

- ${getAddress(contactPrimary)} -
- `; - }; - - const getContactSecondary = () => ` -
-

${contactSecondary.name ? contactSecondary.name : ''}

- ${getAddress(contactSecondary)} -
- `; - - let partyInfoContent = ` -
-
${detail.partyType}
-
- ${contactPrimary ? getContactPrimary() : ''} - ${contactSecondary ? getContactSecondary() : ''} -
-
- `; - - // privatePractitioners - if (privatePractitioners.length > 0) { - const getPractitioners = () => { - let result = ''; - - privatePractitioners.map(practitioner => { - if (practitioner.formattedName) { - const { representingPrimary, representingSecondary } = practitioner; - result += ` -
-

${practitioner.formattedName}

- ${getAddress({ - ...practitioner, - ...practitioner.contact, - })} -

- Representing -
- ${representingPrimary ? contactPrimary.name : ''} - ${representingSecondary ? '
' : ''} - ${ - representingSecondary && - contactSecondary && - contactSecondary.name - ? contactSecondary.name - : '' - } -

-
- `; - } - }); - - return result; - }; - - partyInfoContent += ` -
-
Petitioner Counsel
-
- ${getPractitioners()} -
-
- `; - } - - // irsPractitioners - if (irsPractitioners.length > 0) { - const getIrsPractitioners = () => { - let result = ''; - - irsPractitioners.map(practitioner => { - if (practitioner.name) { - result += ` -
-

${practitioner.name}

- ${getAddress({ - ...practitioner, - ...practitioner.contact, - })} -
- `; - } - }); - - return result; - }; - - partyInfoContent += ` -
-
Respondent Counsel
-
- ${getIrsPractitioners()} -
-
- `; - } - - return partyInfoContent; - }; - - const getDocketRecordContent = detail => { - let docketRecordContent = ` - - - - - - - - - - - - - - - `; - - detail.docketRecordWithDocument.map(({ document, index, record }) => { - let documentEventCode = ''; - let documentFiledBy = ''; - let documentDateServed = ''; - let documentServedPartiesCode = ''; - let recordDescription = `${record.description}`; - - if (record.filingsAndProceedings) { - recordDescription += ' ' + record.filingsAndProceedings; - } - - const recordCreatedAtFormatted = record.createdAtFormatted; - const recordAction = record.action || ''; - - if (document) { - documentEventCode = document.eventCode || ''; - documentFiledBy = document.filedBy || ''; - documentServedPartiesCode = document.servedPartiesCode || ''; - - if (document.isStatusServed) { - documentDateServed = document.servedAtFormatted || ''; - } - - if (document.additionalInfo2) { - recordDescription += ' ' + document.additionalInfo2; - } - } - - if (documentDateServed) { - const arrDateServed = documentDateServed.split(' '); - documentDateServed = `${ - arrDateServed[0] - } ${arrDateServed.slice(1).join(' ')}`; - } else if (document && document.isNotServedCourtIssuedDocument) { - documentDateServed = 'Not served'; - } - - docketRecordContent += ` - - - - - - - - - - - `; - }); - - docketRecordContent += ` - -
No.DateEventFilings and proceedingsFiled byActionServedParties
${index}${recordCreatedAtFormatted ? recordCreatedAtFormatted : ''}${documentEventCode}${recordDescription}${documentFiledBy}${recordAction}${documentDateServed}${documentServedPartiesCode}
- `; - - return docketRecordContent; - }; - - const { caseCaption, docketNumber, docketNumberSuffix } = formattedCaseDetail; - - const contentHtml = await applicationContext - .getTemplateGenerators() - .generatePrintableDocketRecordTemplate({ - applicationContext, - content: { - caption: caseCaption, - docketNumberWithSuffix: docketNumber + (docketNumberSuffix || ''), - docketRecord: getDocketRecordContent(formattedCaseDetail), - partyInfo: includePartyDetail - ? getPartyInfoContent(formattedCaseDetail) - : '', - }, - }); - - return await applicationContext.getUseCases().generatePdfFromHtmlInteractor({ + const pdf = await applicationContext.getDocumentGenerators().docketRecord({ applicationContext, - contentHtml, - docketNumber, + data: { + caseCaptionExtension, + caseDetail: formattedCaseDetail, + caseTitle, + docketNumberWithSuffix: `${caseEntity.docketNumber}${ + caseEntity.docketNumberSuffix || '' + }`, + entries: formattedCaseDetail.docketRecordWithDocument, + }, }); + + return await applicationContext + .getUseCaseHelpers() + .saveFileAndGenerateUrl({ applicationContext, file: pdf }); }; diff --git a/shared/src/business/useCases/generateDocketRecordPdfInteractor.test.js b/shared/src/business/useCases/generateDocketRecordPdfInteractor.test.js index 4753f98d3fb..f67c46db52b 100644 --- a/shared/src/business/useCases/generateDocketRecordPdfInteractor.test.js +++ b/shared/src/business/useCases/generateDocketRecordPdfInteractor.test.js @@ -3,6 +3,8 @@ import { generateDocketRecordPdfInteractor } from './generateDocketRecordPdfInte const { applicationContext } = require('../test/createTestApplicationContext'); const { MOCK_USERS } = require('../../test/mockUsers'); +const mockId = '12345'; +const mockPdfUrlAndID = { fileId: mockId, url: 'www.example.com' }; const caseDetail = { caseCaption: 'Test Case Caption', caseId: 'ca-123', @@ -73,218 +75,34 @@ beforeAll(() => { return contentHtml; }); applicationContext - .getTemplateGenerators() - .generatePrintableDocketRecordTemplate.mockImplementation( - async ({ content }) => { - return `${content.docketRecord} ${content.partyInfo}`; - }, - ); + .getUseCaseHelpers() + .saveFileAndGenerateUrl.mockReturnValue(mockPdfUrlAndID); + applicationContext.getUniqueId.mockReturnValue(mockId); }); describe('generateDocketRecordPdfInteractor', () => { - it('Calls generatePdfFromHtmlInteractor and generatePrintableDocketRecordTemplate to build a PDF', async () => { - const result = await generateDocketRecordPdfInteractor({ + it('Calls docketRecord document generator to build a PDF', async () => { + await generateDocketRecordPdfInteractor({ applicationContext, caseDetail, includePartyDetail: true, }); - expect(result.indexOf('')).toBe(0); - expect( - applicationContext.getTemplateGenerators() - .generatePrintableDocketRecordTemplate, - ).toHaveBeenCalled(); expect( - applicationContext.getUseCases().generatePdfFromHtmlInteractor, + applicationContext.getDocumentGenerators().docketRecord, ).toHaveBeenCalled(); }); - it('Displays contactSecondary if associated with the case', async () => { - applicationContext - .getPersistenceGateway() - .getCaseByCaseId.mockImplementation(() => ({ - ...caseDetail, - caseId: 'ca123', - contactSecondary: { - address1: 'address 1', - city: 'City', - countryType: 'domestic', - name: 'Test Secondary', - phone: '123-123-1234', - postalCode: '12345', - state: 'ST', - }, - includePartyDetail: true, - partyType: ContactFactory.PARTY_TYPES.petitionerSpouse, - })); - + it('Returns a file ID and url to the generated file', async () => { const result = await generateDocketRecordPdfInteractor({ applicationContext, - caseId: 'ca123', - includePartyDetail: true, - }); - - expect(result.includes('Test Secondary')).toEqual(true); - }); - - it('displays no party information if "includePartyDetail" flag is undefined or falsy', async () => { - let result = await generateDocketRecordPdfInteractor({ - applicationContext: { - ...applicationContext, - getPersistenceGateway: () => ({ - getCaseByCaseId: () => ({ - ...caseDetail, - contactSecondary: { - address1: 'address 1', - city: 'City', - countryType: 'domestic', - name: 'Test Secondary', - phone: '123-123-1234', - postalCode: '12345', - state: 'ST', - }, - }), - }), - }, - caseId: 'ca123', - // includePartyDetail not provided, is undefined - }); - - expect(result.includes('Test Secondary')).toEqual(false); - - result = await generateDocketRecordPdfInteractor({ - applicationContext: { - ...applicationContext, - getPersistenceGateway: () => ({ - getCaseByCaseId: () => ({ - ...caseDetail, - contactSecondary: { - address1: 'address 1', - city: 'City', - countryType: 'domestic', - name: 'Test Secondary', - phone: '123-123-1234', - postalCode: '12345', - state: 'ST', - }, - }), - }), - }, - caseId: 'ca123', - includePartyDetail: false, - }); - - expect(result.includes('Test Secondary')).toEqual(false); - }); - - it('Displays privatePractitioners associated with the case', async () => { - const result = await generateDocketRecordPdfInteractor({ - applicationContext: { - ...applicationContext, - getPersistenceGateway: () => ({ - getCaseByCaseId: () => ({ - ...caseDetail, - contactSecondary: { - address1: 'address 1', - city: 'City', - countryType: 'domestic', - name: 'Test Secondary', - phone: '123-123-1234', - postalCode: '12345', - state: 'ST', - }, - privatePractitioners: [ - { - addressLine1: '123 Address 1', - city: 'Some City', - name: 'Test Practitioner', - phoneNumber: '99999999', - representingPrimary: true, - state: 'ST', - }, - { - addressLine1: '321 Address 1', - city: 'Some City', - name: 'Test Practitioner 2', - phoneNumber: '99999999', - representingSecondary: true, - state: 'ST', - }, - ], - }), - }), - }, - caseId: 'ca-123', - includePartyDetail: true, - }); - - expect(result.includes('Test Practitioner')).toEqual(true); - expect(result.includes('Test Practitioner 2')).toEqual(true); - }); - - it('Displays irsPractitioners associated with the case', async () => { - const result = await generateDocketRecordPdfInteractor({ - applicationContext: { - ...applicationContext, - getPersistenceGateway: () => ({ - getCaseByCaseId: () => ({ - ...caseDetail, - irsPractitioners: [ - { - addressLine1: '123 Address 1', - city: 'Some City', - name: 'Test Respondent', - phoneNumber: '99999999', - representingPrimary: true, - state: 'ST', - }, - ], - }), - }), - }, - caseId: 'ca123', - includePartyDetail: true, - }); - - expect(result.includes('Respondent Counsel')).toEqual(true); - expect(result.includes('Test Respondent')).toEqual(true); - }); - - it('Displays optional contact information if present', async () => { - applicationContext - .getPersistenceGateway() - .getCaseByCaseId.mockImplementation(() => { - return { - ...caseDetail, - contactPrimary: { - ...caseDetail.contactPrimary, - address2: 'Address Two', - address3: 'Address Three', - inCareOf: 'Test C/O', - title: 'Test Title', - }, - }; - }); - - const result = await generateDocketRecordPdfInteractor({ - applicationContext, - caseId: 'ca-123', - includePartyDetail: true, - }); - - expect(result.includes('Test C/O')).toEqual(true); - expect(result.includes('Test Title')).toEqual(true); - expect(result.includes('Address Two')).toEqual(true); - expect(result.includes('Address Three')).toEqual(true); - }); - - it('Displays caseName instead of contactPrimary name when showCaseNameForPrimary is set', async () => { - const result = await generateDocketRecordPdfInteractor({ - applicationContext, - caseDetail: { ...caseDetail }, + caseDetail, includePartyDetail: true, }); - expect(result.includes(caseDetail.caseCaption)).toEqual(true); + expect( + applicationContext.getUseCaseHelpers().saveFileAndGenerateUrl, + ).toHaveBeenCalled(); + expect(result).toEqual(mockPdfUrlAndID); }); }); diff --git a/shared/src/business/useCases/generatePdfFromHtmlInteractor.js b/shared/src/business/useCases/generatePdfFromHtmlInteractor.js index 0b422b616bc..664e1c463b0 100644 --- a/shared/src/business/useCases/generatePdfFromHtmlInteractor.js +++ b/shared/src/business/useCases/generatePdfFromHtmlInteractor.js @@ -38,31 +38,18 @@ exports.generatePdfFromHtmlInteractor = async ({ `; const headerTemplate = ` - - - - -
${headerContent}
- `; const footerTemplate = overwriteFooter ? `${footerHtml ? footerHtml : ''}` : ` - - - - - - - `; + `; result = await page.pdf({ displayHeaderFooter, diff --git a/shared/src/business/useCases/generatePrintableFilingReceiptInteractor.js b/shared/src/business/useCases/generatePrintableFilingReceiptInteractor.js index 3d05aa16f28..3fca4e9e5c7 100644 --- a/shared/src/business/useCases/generatePrintableFilingReceiptInteractor.js +++ b/shared/src/business/useCases/generatePrintableFilingReceiptInteractor.js @@ -1,40 +1,33 @@ const { Case } = require('../entities/cases/Case'); +const { Document } = require('../entities/Document'); /** * generateHtmlForFilingReceipt * * @param {object} providers the providers object * @param {object} providers.applicationContext the application context + * @param {object} providers.caseEntity the case entity the documents were filed in * @param {object} providers.documents object containing the caseId and documents for the filing receipt to be generated * @returns {object} contentHtml, the generated HTML for the receipt; and docketNumber for the case */ const generateHtmlForFilingReceipt = async ({ applicationContext, + caseEntity, documents, }) => { const { - caseId, primaryDocument, secondaryDocument, secondarySupportingDocuments, supportingDocuments, } = documents; - const caseSource = await applicationContext - .getPersistenceGateway() - .getCaseByCaseId({ - applicationContext, - caseId, - }); - - const caseEntity = new Case(caseSource, { applicationContext }); const formattedCaseDetail = applicationContext .getUtilities() .getFormattedCaseDetail({ applicationContext, caseDetail: caseEntity, }); - formattedCaseDetail.showCaseNameForPrimary = caseEntity.getShowCaseNameForPrimary(); const getDocumentContent = document => { const hasDocumentIncludes = @@ -98,7 +91,7 @@ const generateHtmlForFilingReceipt = async ({ secondarySupportingDocuments.forEach((secondarySupportingDocument, idx) => { documentsFiledContent += getDocumentContent(secondarySupportingDocument); - if (idx < secondarySupportingDocument.length - 1) { + if (idx < secondarySupportingDocuments.length - 1) { documentsFiledContent += '
'; } }); @@ -131,15 +124,67 @@ exports.generateHtmlForFilingReceipt = generateHtmlForFilingReceipt; * * @param {object} providers the providers object * @param {object} providers.applicationContext the application context - * @param {object} providers.documents object containing the caseId and documents for the filing receipt to be generated + * @param {string} providers.caseId the id of the case the documents were filed in + * @param {object} providers.documentsFiled object containing the caseId and documents for the filing receipt to be generated * @returns {string} url for the generated document on the storage client */ exports.generatePrintableFilingReceiptInteractor = async ({ applicationContext, - documents, + caseId, + documentsFiled, }) => { + const caseSource = await applicationContext + .getPersistenceGateway() + .getCaseByCaseId({ + applicationContext, + caseId, + }); + + const caseEntity = new Case(caseSource, { applicationContext }).validate(); + + const getDocumentInfo = documentData => { + const document = new Document(documentData, { + applicationContext, + }); + document.generateFiledBy(caseEntity); + return { + attachments: document.attachments, + certificateOfService: document.certificateOfService, + certificateOfServiceDate: document.certificateOfServiceDate, + documentTitle: document.documentTitle, + filedBy: document.filedBy, + objections: document.objections, + receivedAt: document.receivedAt, + }; + }; + + const documents = { + primaryDocument: getDocumentInfo(documentsFiled), + supportingDocuments: [], + }; + + if (documentsFiled.hasSupportingDocuments) { + documents.supportingDocuments = documentsFiled.supportingDocuments.map( + supportingDocument => getDocumentInfo(supportingDocument), + ); + } + + if (documentsFiled.secondaryDocumentFile) { + documents.secondaryDocument = getDocumentInfo( + documentsFiled.secondaryDocument, + ); + } + + if (documentsFiled.hasSecondarySupportingDocuments) { + documents.secondarySupportingDocuments = documentsFiled.secondarySupportingDocuments.map( + secondarySupportingDocument => + getDocumentInfo(secondarySupportingDocument), + ); + } + const { contentHtml, docketNumber } = await generateHtmlForFilingReceipt({ applicationContext, + caseEntity, documents, }); diff --git a/shared/src/business/useCases/generatePrintableFilingReceiptInteractor.test.js b/shared/src/business/useCases/generatePrintableFilingReceiptInteractor.test.js index ee413106447..0d565bd7e66 100644 --- a/shared/src/business/useCases/generatePrintableFilingReceiptInteractor.test.js +++ b/shared/src/business/useCases/generatePrintableFilingReceiptInteractor.test.js @@ -1,181 +1,152 @@ -import { - generateHtmlForFilingReceipt, +const { generatePrintableFilingReceiptInteractor, -} from './generatePrintableFilingReceiptInteractor'; +} = require('./generatePrintableFilingReceiptInteractor'); const { applicationContext } = require('../test/createTestApplicationContext'); - +const { MOCK_CASE } = require('../../test/mockCase'); const { MOCK_USERS } = require('../../test/mockUsers'); -let generatePdfFromHtmlInteractorMock; -let generatePrintableFilingReceiptTemplateMock; -let saveDocumentFromLambdaMock; -let getDownloadPolicyUrlMock; -let caseDetail; - describe('generatePrintableFilingReceiptInteractor', () => { - beforeEach(() => { - generatePdfFromHtmlInteractorMock = jest.fn(); - generatePrintableFilingReceiptTemplateMock = jest.fn(); - saveDocumentFromLambdaMock = jest.fn(); - getDownloadPolicyUrlMock = jest.fn().mockReturnValue({ - url: 'a-document-download-url', - }); - - caseDetail = { - caseCaption: 'Test Case Caption', - caseId: 'ca-123', - contactPrimary: { - address1: 'address 1', - city: 'City', - countryType: 'domestic', - name: 'Test Petitioner', - phone: '123-123-1234', - postalCode: '12345', - state: 'ST', - }, - docketNumber: '123-45', - docketNumberSuffix: 'S', - documents: [ - { - documentId: 'e631d81f-a579-4de5-b8a8-b3f10ef619fd', - }, - { - documentId: 'e631d81f-a579-4de5-b8a8-b3f10ef619fe', - }, - { - additionalInfo2: 'Additional Info 2', - documentId: 'e631d81f-a579-4de5-b8a8-b3f10ef619fe', - isStatusServed: true, - servedAtFormatted: '03/27/19', - }, - ], - irsPractitioners: [], - privatePractitioners: [], - }; - + beforeAll(() => { applicationContext.getCurrentUser.mockReturnValue( MOCK_USERS['a7d90c05-f6cd-442c-a168-202db587f16f'], ); applicationContext .getPersistenceGateway() - .getCaseByCaseId.mockReturnValue(caseDetail); + .getCaseByCaseId.mockReturnValue(MOCK_CASE); applicationContext .getPersistenceGateway() - .getDownloadPolicyUrl.mockImplementation(getDownloadPolicyUrlMock); - applicationContext - .getPersistenceGateway() - .saveDocumentFromLambda.mockImplementation(saveDocumentFromLambdaMock); - + .getDownloadPolicyUrl.mockReturnValue({ + url: 'example.com/download-this', + }); applicationContext .getTemplateGenerators() .generatePrintableFilingReceiptTemplate.mockImplementation( ({ content }) => { - generatePrintableFilingReceiptTemplateMock(); - return `${content.documentsFiledContent}`; + return `${content.documentsFiledContent}`; }, ); - applicationContext .getUseCases() .generatePdfFromHtmlInteractor.mockImplementation(({ contentHtml }) => { - generatePdfFromHtmlInteractorMock(); return contentHtml; }); }); - it('Calls generatePrintableFilingReceiptTemplate and generatePdfFromHtmlInteractor to build a PDF, then saveDocumentFromLambda and getDownloadPolicyUrl to store the PDF and return the link to it', async () => { + it('Calls generatePrintableFilingReceiptTemplate and generatePdfFromHtmlInteractor to build a PDF, then saveDocumentFromLambda and getDownloadPolicyUrl to store the PDF and return the link to it for a single primary document', async () => { await generatePrintableFilingReceiptInteractor({ applicationContext, - documents: { - primaryDocument: { - attachments: false, - certificateOfService: false, - documentTitle: 'Test Primary Document', - }, + caseId: MOCK_CASE.caseId, + documentsFiled: { + primaryDocumentFile: {}, }, }); - expect(generatePrintableFilingReceiptTemplateMock).toHaveBeenCalled(); - expect(generatePdfFromHtmlInteractorMock).toHaveBeenCalled(); - expect(saveDocumentFromLambdaMock).toHaveBeenCalled(); - expect(getDownloadPolicyUrlMock).toHaveBeenCalled(); + expect( + applicationContext.getTemplateGenerators() + .generatePrintableFilingReceiptTemplate, + ).toHaveBeenCalled(); + expect( + applicationContext.getUseCases().generatePdfFromHtmlInteractor, + ).toHaveBeenCalled(); + expect( + applicationContext.getPersistenceGateway().saveDocumentFromLambda, + ).toHaveBeenCalled(); + expect( + applicationContext.getPersistenceGateway().getDownloadPolicyUrl, + ).toHaveBeenCalled(); }); it('Displays `Attachment(s)` and Certificate of Service if present on a document', async () => { - const { contentHtml: result } = await generateHtmlForFilingReceipt({ + await generatePrintableFilingReceiptInteractor({ applicationContext, - documents: { - primaryDocument: { - attachments: true, - certificateOfService: true, - certificateOfServiceDate: '10-31-1983', - documentTitle: 'Test Primary Document', - }, + caseId: MOCK_CASE.caseId, + documentsFiled: { + attachments: true, + certificateOfService: true, + certificateOfServiceDate: '1983-10-31T09:38:18.614Z', + documentTitle: 'Test Primary Document', + primaryDocumentFile: {}, }, }); - expect(result.indexOf('')).toBe(0); - expect(result.indexOf('Document Includes')).toBeGreaterThan(-1); - expect(result.indexOf('Attachment(s)')).toBeGreaterThan(-1); - expect(result.indexOf('Certificate of Service')).toBeGreaterThan(-1); + const { + contentHtml, + } = applicationContext.getUseCases().generatePdfFromHtmlInteractor.mock.calls[0][0]; + + expect(contentHtml.indexOf('')).toBe(0); + expect(contentHtml.includes('Document Includes')).toBeTruthy(); + expect(contentHtml.includes('Attachment(s)')).toBeTruthy(); + expect(contentHtml.includes('Certificate of Service')).toBeTruthy(); }); it('Displays Objections status when there are objections', async () => { - const { contentHtml: result } = await generateHtmlForFilingReceipt({ + await generatePrintableFilingReceiptInteractor({ applicationContext, - documents: { - primaryDocument: { - documentTitle: 'Test Primary Document', - objections: 'Yes', - }, + caseId: MOCK_CASE.caseId, + documentsFiled: { + documentTitle: 'Test Primary Document', + objections: 'Yes', + primaryDocumentFile: {}, }, }); - expect(result.indexOf('Document Includes')).toEqual(-1); - expect(result.indexOf('Objections')).toBeGreaterThan(-1); + const { + contentHtml, + } = applicationContext.getUseCases().generatePdfFromHtmlInteractor.mock.calls[0][0]; + + expect(contentHtml.includes('Document Includes')).toBeFalsy(); + expect(contentHtml.includes('Objections')).toBeTruthy(); }); it('Displays No Objections status when there are no objections', async () => { - const { contentHtml: result } = await generateHtmlForFilingReceipt({ + await generatePrintableFilingReceiptInteractor({ applicationContext, - documents: { - primaryDocument: { - documentTitle: 'Test Primary Document', - objections: 'No', - }, + caseId: MOCK_CASE.caseId, + documentsFiled: { + documentTitle: 'Test Primary Document', + objections: 'No', + primaryDocumentFile: {}, }, }); - expect(result.indexOf('Document Includes')).toEqual(-1); - expect(result.indexOf('No Objections')).toBeGreaterThan(-1); + const { + contentHtml, + } = applicationContext.getUseCases().generatePdfFromHtmlInteractor.mock.calls[0][0]; + + expect(contentHtml.includes('Document Includes')).toBeFalsy(); + expect(contentHtml.includes('No Objections')).toBeTruthy(); }); it('Displays Unknown Objections status when there are no objections', async () => { - const { contentHtml: result } = await generateHtmlForFilingReceipt({ + await generatePrintableFilingReceiptInteractor({ applicationContext, - documents: { - primaryDocument: { - documentTitle: 'Test Primary Document', - objections: 'Unknown', - }, + caseId: MOCK_CASE.caseId, + documentsFiled: { + documentTitle: 'Test Primary Document', + objections: 'Unknown', + primaryDocumentFile: {}, }, }); - expect(result.indexOf('Document Includes')).toEqual(-1); - expect(result.indexOf('Unknown Objections')).toBeGreaterThan(-1); + const { + contentHtml, + } = applicationContext.getUseCases().generatePdfFromHtmlInteractor.mock.calls[0][0]; + + expect(contentHtml.includes('Document Includes')).toBeFalsy(); + expect(contentHtml.includes('Unknown Objections')).toBeTruthy(); }); it('Displays supporting documents if present in the filing', async () => { - const { contentHtml: result } = await generateHtmlForFilingReceipt({ + await generatePrintableFilingReceiptInteractor({ applicationContext, - documents: { + caseId: MOCK_CASE.caseId, + documentsFiled: { + attachments: true, + certificateOfService: true, + certificateOfServiceDate: '1983-10-31T09:38:18.614Z', + documentTitle: 'Test Primary Document', hasSupportingDocuments: true, - primaryDocument: { - attachments: true, - certificateOfService: true, - certificateOfServiceDate: '10-31-1983', - documentTitle: 'Test Primary Document', - }, + primaryDocumentFile: {}, supportingDocuments: [ { documentTitle: 'Test Supporting Document', @@ -184,42 +155,51 @@ describe('generatePrintableFilingReceiptInteractor', () => { }, }); - expect(result.indexOf('Test Primary Document')).toBeGreaterThan(-1); - expect(result.indexOf('Test Supporting Document')).toBeGreaterThan(-1); + const { + contentHtml, + } = applicationContext.getUseCases().generatePdfFromHtmlInteractor.mock.calls[0][0]; + + expect(contentHtml.includes('Test Primary Document')).toBeTruthy(); + expect(contentHtml.includes('Test Supporting Document')).toBeTruthy(); }); it('Displays secondary document if present in the filing', async () => { - const { contentHtml: result } = await generateHtmlForFilingReceipt({ + await generatePrintableFilingReceiptInteractor({ applicationContext, - documents: { - primaryDocument: { - attachments: true, - certificateOfService: true, - certificateOfServiceDate: '10-31-1983', - documentTitle: 'Test Primary Document', - }, + caseId: MOCK_CASE.caseId, + documentsFiled: { + attachments: true, + certificateOfService: true, + certificateOfServiceDate: '1983-10-31T09:38:18.614Z', + documentTitle: 'Test Primary Document', + primaryDocumentFile: {}, secondaryDocument: { documentTitle: 'Test Secondary Document', }, + secondaryDocumentFile: {}, }, }); - expect(result.indexOf('Test Primary Document')).toBeGreaterThan(-1); - expect(result.indexOf('Test Secondary Document')).toBeGreaterThan(-1); + const { + contentHtml, + } = applicationContext.getUseCases().generatePdfFromHtmlInteractor.mock.calls[0][0]; + + expect(contentHtml.includes('Test Primary Document')).toBeTruthy(); + expect(contentHtml.includes('Test Secondary Document')).toBeTruthy(); }); it('Displays secondary supporting documents if present in the filing', async () => { - const { contentHtml: result } = await generateHtmlForFilingReceipt({ + await generatePrintableFilingReceiptInteractor({ applicationContext, - documents: { + caseId: MOCK_CASE.caseId, + documentsFiled: { + attachments: true, + certificateOfService: true, + certificateOfServiceDate: '1983-10-31T09:38:18.614Z', + documentTitle: 'Test Primary Document', hasSecondarySupportingDocuments: true, hasSupportingDocuments: false, - primaryDocument: { - attachments: true, - certificateOfService: true, - certificateOfServiceDate: '10-31-1983', - documentTitle: 'Test Primary Document', - }, + primaryDocumentFile: {}, secondarySupportingDocuments: [ { documentTitle: 'Test Secondary Supporting Document', @@ -231,12 +211,62 @@ describe('generatePrintableFilingReceiptInteractor', () => { }, }); - expect(result.indexOf('Test Primary Document')).toBeGreaterThan(-1); + const { + contentHtml, + } = applicationContext.getUseCases().generatePdfFromHtmlInteractor.mock.calls[0][0]; + + expect(contentHtml.includes('Test Primary Document')).toBeTruthy(); + expect( + contentHtml.includes('Test Secondary Supporting Document'), + ).toBeTruthy(); + expect( + contentHtml.includes('Test Secondary Supporting Document 2'), + ).toBeTruthy(); + }); + + it('Displays primary and secondary supporting documents if present in the filing', async () => { + await generatePrintableFilingReceiptInteractor({ + applicationContext, + caseId: MOCK_CASE.caseId, + documentsFiled: { + attachments: true, + certificateOfService: true, + certificateOfServiceDate: '1983-10-31T09:38:18.614Z', + documentTitle: 'Test Primary Document', + hasSecondarySupportingDocuments: true, + hasSupportingDocuments: true, + primaryDocumentFile: {}, + secondarySupportingDocuments: [ + { + documentTitle: 'Test Secondary Supporting Document', + }, + { + documentTitle: 'Test Secondary Supporting Document 2', + }, + ], + supportingDocuments: [ + { + documentTitle: 'Test Supporting Document', + }, + { + documentTitle: 'Test Supporting Document 2', + }, + ], + }, + }); + + const { + contentHtml, + } = applicationContext.getUseCases().generatePdfFromHtmlInteractor.mock.calls[0][0]; + + expect(contentHtml.includes('Test Primary Document')).toBeTruthy(); + expect(contentHtml.includes('Test Supporting Document')).toBeTruthy(); + expect(contentHtml.includes('Test Supporting Document 2')).toBeTruthy(); expect( - result.indexOf('Test Secondary Supporting Document'), - ).toBeGreaterThan(-1); + contentHtml.includes('Test Secondary Supporting Document'), + ).toBeTruthy(); expect( - result.indexOf('Test Secondary Supporting Document 2'), - ).toBeGreaterThan(-1); + contentHtml.includes('Test Secondary Supporting Document 2'), + ).toBeTruthy(); }); }); diff --git a/shared/src/business/useCases/getCaseInteractor.js b/shared/src/business/useCases/getCaseInteractor.js index cd3ddd36a65..751180b106f 100644 --- a/shared/src/business/useCases/getCaseInteractor.js +++ b/shared/src/business/useCases/getCaseInteractor.js @@ -7,6 +7,34 @@ const { caseSealedFormatter } = require('../utilities/caseFilter'); const { NotFoundError, UnauthorizedError } = require('../../errors/errors'); const { PublicCase } = require('../entities/cases/PublicCase'); +const getDocumentContentsForDocuments = async ({ + applicationContext, + documents, +}) => { + for (const document of documents) { + if (document.documentContentsId) { + const documentContentsFile = await applicationContext + .getPersistenceGateway() + .getDocument({ + applicationContext, + documentId: document.documentContentsId, + protocol: 'S3', + useTempBucket: true, + }); + + const documentContentsData = JSON.parse(documentContentsFile.toString()); + document.documentContents = documentContentsData.documentContents; + document.draftState = { + ...document.draftState, + documentContents: documentContentsData.documentContents, + richText: documentContentsData.richText, + }; + } + } + + return documents; +}; + /** * getCaseInteractor * @@ -49,7 +77,7 @@ exports.getCaseInteractor = async ({ applicationContext, caseId }) => { throw new UnauthorizedError('Unauthorized'); } - let caseDetail; + let caseDetailRaw; if (caseRecord.sealedDate) { let isAuthorizedUser = @@ -63,19 +91,35 @@ exports.getCaseInteractor = async ({ applicationContext, caseId }) => { user: applicationContext.getCurrentUser(), }); if (isAuthorizedUser) { - caseDetail = new Case(caseRecord, { + caseDetailRaw = new Case(caseRecord, { applicationContext, + }) + .validate() + .toRawObject(); + + caseDetailRaw.documents = await getDocumentContentsForDocuments({ + applicationContext, + documents: caseDetailRaw.documents, }); } else { caseRecord = caseSealedFormatter(caseRecord); - caseDetail = new PublicCase(caseRecord, { + caseDetailRaw = new PublicCase(caseRecord, { applicationContext, - }); + }) + .validate() + .toRawObject(); } } else { - caseDetail = new Case(caseRecord, { + caseDetailRaw = new Case(caseRecord, { + applicationContext, + }) + .validate() + .toRawObject(); + + caseDetailRaw.documents = await getDocumentContentsForDocuments({ applicationContext, + documents: caseDetailRaw.documents, }); } - return caseDetail.validate().toRawObject(); + return caseDetailRaw; }; diff --git a/shared/src/business/useCases/getCaseInteractor.test.js b/shared/src/business/useCases/getCaseInteractor.test.js index 1c1f1c7e78d..2b7ff2a87ad 100644 --- a/shared/src/business/useCases/getCaseInteractor.test.js +++ b/shared/src/business/useCases/getCaseInteractor.test.js @@ -23,6 +23,56 @@ describe('Get case', () => { expect(caseRecord.caseId).toEqual('c54ba5a9-b37b-479d-9201-067ec6e335bb'); }); + it('successfully retrieves a case with documents that have documentContents', async () => { + const mockCaseWithDocumentContents = { + ...MOCK_CASE, + documents: [ + { + createdAt: '2018-11-21T20:49:28.192Z', + docketNumber: '101-18', + documentContentsId: '0098d177-78ef-4210-88aa-4bbb45c4f048', + documentId: 'c6b81f4d-1e47-423a-8caf-6d2fdc3d3859', + documentTitle: 'Petition', + documentType: 'Petition', + draftState: {}, + eventCode: 'P', + processingStatus: 'pending', + userId: 'petitioner', + workItems: [], + }, + ], + }; + applicationContext.getCurrentUser.mockReturnValue({ + role: User.ROLES.petitionsClerk, + userId: 'petitionsclerk', + }); + applicationContext + .getPersistenceGateway() + .getCaseByCaseId.mockReturnValue(mockCaseWithDocumentContents); + applicationContext.getPersistenceGateway().getDocument.mockReturnValue( + Buffer.from( + JSON.stringify({ + documentContents: 'the contents!', + richText: 'the contents!', + }), + ), + ); + + const caseRecord = await getCaseInteractor({ + applicationContext, + caseId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', + }); + + expect(applicationContext.getPersistenceGateway().getDocument).toBeCalled(); + expect(caseRecord.documents[0]).toMatchObject({ + documentContents: 'the contents!', + draftState: { + documentContents: 'the contents!', + richText: 'the contents!', + }, + }); + }); + it('failure case by case id', async () => { applicationContext.getCurrentUser.mockReturnValue({ role: User.ROLES.petitionsClerk, @@ -195,8 +245,6 @@ describe('Get case', () => { applicationContext, caseId: '00101-08', }), - ).rejects.toThrow( - 'The Case entity was invalid ValidationError: "docketNumber" is required', - ); + ).rejects.toThrow('The Case entity was invalid'); }); }); diff --git a/shared/src/business/useCases/getCasesByUserInteractor.test.js b/shared/src/business/useCases/getCasesByUserInteractor.test.js index 02f854d1bd4..c114682c76b 100644 --- a/shared/src/business/useCases/getCasesByUserInteractor.test.js +++ b/shared/src/business/useCases/getCasesByUserInteractor.test.js @@ -21,8 +21,6 @@ describe('Send petition to IRS', () => { error = err; } - expect(error.message).toContain( - 'The Case entity was invalid ValidationError: "docketNumber" is required', - ); + expect(error.message).toContain('The Case entity was invalid'); }); }); diff --git a/shared/src/business/useCases/getUserByIdInteractor.test.js b/shared/src/business/useCases/getUserByIdInteractor.test.js index 92617940776..5971f338381 100644 --- a/shared/src/business/useCases/getUserByIdInteractor.test.js +++ b/shared/src/business/useCases/getUserByIdInteractor.test.js @@ -65,9 +65,13 @@ describe('getUserByIdInteractor', () => { }); expect(user).toEqual({ + barNumber: undefined, + email: undefined, + entityName: 'User', name: 'Test Practitioner', role: User.ROLES.privatePractitioner, section: 'privatePractitioner', + token: undefined, userId: '4f67802c-1948-4749-b070-38f7316b15c5', }); }); diff --git a/shared/src/business/useCases/getUserInteractor.test.js b/shared/src/business/useCases/getUserInteractor.test.js index ff6070acfea..7a630be8eb3 100644 --- a/shared/src/business/useCases/getUserInteractor.test.js +++ b/shared/src/business/useCases/getUserInteractor.test.js @@ -18,23 +18,19 @@ describe('getUserInteractor', () => { userId: '6805d1ab-18d0-43ec-bafb-654e83405416', }); - let error; - let user; - - try { - user = await getUserInteractor({ - applicationContext, - caseId: '6805d1ab-18d0-43ec-bafb-654e83405416', - }); - } catch (e) { - error = e; - } + const user = await getUserInteractor({ + applicationContext, + caseId: '6805d1ab-18d0-43ec-bafb-654e83405416', + }); - expect(error).toBeUndefined(); expect(user).toEqual({ + barNumber: undefined, + email: undefined, + entityName: 'User', name: 'Test Petitionsclerk', role: User.ROLES.petitionsClerk, section: 'petitions', + token: undefined, userId: '6805d1ab-18d0-43ec-bafb-654e83405416', }); }); @@ -54,23 +50,19 @@ describe('getUserInteractor', () => { userId: '6805d1ab-18d0-43ec-bafb-654e83405416', }); - let error; - let user; - - try { - user = await getUserInteractor({ - applicationContext, - caseId: '6805d1ab-18d0-43ec-bafb-654e83405416', - }); - } catch (e) { - error = e; - } + const user = await getUserInteractor({ + applicationContext, + caseId: '6805d1ab-18d0-43ec-bafb-654e83405416', + }); - expect(error).toBeUndefined(); expect(user).toEqual({ + barNumber: undefined, + email: undefined, + entityName: 'User', name: 'Test Judge', role: User.ROLES.judge, section: 'judge', + token: undefined, userId: '6805d1ab-18d0-43ec-bafb-654e83405416', }); }); diff --git a/shared/src/business/useCases/manualAssociation/associateIrsPractitionerWithCaseInteractor.test.js b/shared/src/business/useCases/manualAssociation/associateIrsPractitionerWithCaseInteractor.test.js index b3c11c60155..003c6727f79 100644 --- a/shared/src/business/useCases/manualAssociation/associateIrsPractitionerWithCaseInteractor.test.js +++ b/shared/src/business/useCases/manualAssociation/associateIrsPractitionerWithCaseInteractor.test.js @@ -15,6 +15,16 @@ describe('associateIrsPractitionerWithCaseInteractor', () => { caseCaption: 'Caption', caseId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', caseType: 'Deficiency', + contactPrimary: { + address1: '123 Main St', + city: 'Somewhere', + countryType: 'domestic', + email: 'fieri@example.com', + name: 'Guy Fieri', + phone: '1234567890', + postalCode: '12345', + state: 'CA', + }, docketNumber: '123-19', docketRecord: MOCK_CASE.docketRecord, documents: MOCK_CASE.documents, diff --git a/shared/src/business/useCases/manualAssociation/associatePrivatePractitionerWithCaseInteractor.test.js b/shared/src/business/useCases/manualAssociation/associatePrivatePractitionerWithCaseInteractor.test.js index 30253fc6757..f7d92d2fda2 100644 --- a/shared/src/business/useCases/manualAssociation/associatePrivatePractitionerWithCaseInteractor.test.js +++ b/shared/src/business/useCases/manualAssociation/associatePrivatePractitionerWithCaseInteractor.test.js @@ -11,6 +11,16 @@ describe('associatePrivatePractitionerWithCaseInteractor', () => { caseCaption: 'Caption', caseId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', caseType: 'Deficiency', + contactPrimary: { + address1: '123 Main St', + city: 'Somewhere', + countryType: 'domestic', + email: 'fieri@example.com', + name: 'Guy Fieri', + phone: '1234567890', + postalCode: '12345', + state: 'CA', + }, docketNumber: '123-19', docketRecord: [ { diff --git a/shared/src/business/useCases/migrateCaseInteractor.test.js b/shared/src/business/useCases/migrateCaseInteractor.test.js index f63adbc7e06..8b60ed24dd5 100644 --- a/shared/src/business/useCases/migrateCaseInteractor.test.js +++ b/shared/src/business/useCases/migrateCaseInteractor.test.js @@ -55,7 +55,6 @@ describe('migrateCaseInteractor', () => { postalCode: '69580', state: 'AR', }, - contactSecondary: {}, docketNumber: '00101-00', docketRecord: MOCK_CASE.docketRecord, documents: MOCK_CASE.documents, @@ -112,21 +111,13 @@ describe('migrateCaseInteractor', () => { }); it('should create a case successfully', async () => { - let error; - let result; - expect(createdCases.length).toEqual(0); - try { - result = await migrateCaseInteractor({ - applicationContext, - caseMetadata, - }); - } catch (e) { - error = e; - } + const result = await migrateCaseInteractor({ + applicationContext, + caseMetadata, + }); - expect(error).toBeUndefined(); expect(result).toBeDefined(); expect( applicationContext.getPersistenceGateway().createCase, @@ -153,7 +144,7 @@ describe('migrateCaseInteractor', () => { docketRecord: [{}], }, }), - ).rejects.toThrow('The DocketRecord entity was invalid'); + ).rejects.toThrow('The Case entity was invalid'); }); }); }); diff --git a/shared/src/business/useCases/orderAdvancedSearchInteractor.js b/shared/src/business/useCases/orderAdvancedSearchInteractor.js index 108ca8c1420..2e1723f3ecd 100644 --- a/shared/src/business/useCases/orderAdvancedSearchInteractor.js +++ b/shared/src/business/useCases/orderAdvancedSearchInteractor.js @@ -2,8 +2,9 @@ const { isAuthorized, ROLE_PERMISSIONS, } = require('../../authorization/authorizationClientService'); +const { caseSearchFilter } = require('../utilities/caseFilter'); const { Document } = require('../../business/entities/Document'); -const { map } = require('lodash'); +const { OrderSearch } = require('../../business/entities/orders/OrderSearch'); const { UnauthorizedError } = require('../../errors/errors'); /** @@ -16,10 +17,14 @@ exports.orderAdvancedSearchInteractor = async ({ applicationContext, caseTitleOrPetitioner, docketNumber, - endDate, + endDateDay, + endDateMonth, + endDateYear, judge, orderKeyword, - startDate, + startDateDay, + startDateMonth, + startDateYear, }) => { const authorizedUser = applicationContext.getCurrentUser(); @@ -27,16 +32,30 @@ exports.orderAdvancedSearchInteractor = async ({ throw new UnauthorizedError('Unauthorized'); } - const orderEventCodes = map(Document.ORDER_DOCUMENT_TYPES, 'eventCode'); - - return await applicationContext.getPersistenceGateway().orderKeywordSearch({ - applicationContext, + const orderSearch = new OrderSearch({ caseTitleOrPetitioner, docketNumber, - endDate, + endDateDay, + endDateMonth, + endDateYear, judge, - orderEventCodes, orderKeyword, - startDate, + startDateDay, + startDateMonth, + startDateYear, }); + + const rawSearch = orderSearch.validate().toRawObject(); + + const results = await applicationContext + .getPersistenceGateway() + .orderKeywordSearch({ + applicationContext, + orderEventCodes: Document.ORDER_DOCUMENT_TYPES, + ...rawSearch, + }); + + const filteredResults = caseSearchFilter(results, authorizedUser); + + return filteredResults; }; diff --git a/shared/src/business/useCases/orderAdvancedSearchInteractor.test.js b/shared/src/business/useCases/orderAdvancedSearchInteractor.test.js index 794ae6a8d77..473b500adb5 100644 --- a/shared/src/business/useCases/orderAdvancedSearchInteractor.test.js +++ b/shared/src/business/useCases/orderAdvancedSearchInteractor.test.js @@ -3,7 +3,6 @@ const { } = require('./orderAdvancedSearchInteractor'); const { applicationContext } = require('../test/createTestApplicationContext'); const { Document } = require('../../business/entities/Document'); -const { map } = require('lodash'); describe('orderAdvancedSearchInteractor', () => { beforeEach(() => { @@ -53,6 +52,7 @@ describe('orderAdvancedSearchInteractor', () => { it('returns results with an authorized user role (petitionsclerk)', async () => { const result = await orderAdvancedSearchInteractor({ applicationContext, + orderKeyword: 'candy', }); expect(result).toMatchObject([ @@ -82,7 +82,6 @@ describe('orderAdvancedSearchInteractor', () => { it('searches for documents that are of type orders', async () => { const orderKeyword = 'keyword'; - const orderEventCodes = map(Document.ORDER_DOCUMENT_TYPES, 'eventCode'); await orderAdvancedSearchInteractor({ applicationContext, @@ -93,7 +92,7 @@ describe('orderAdvancedSearchInteractor', () => { applicationContext.getPersistenceGateway().orderKeywordSearch.mock .calls[0][0], ).toMatchObject({ - orderEventCodes, + orderEventCodes: Document.ORDER_DOCUMENT_TYPES, }); }); }); diff --git a/shared/src/business/useCases/practitioners/getPractitionerByBarNumberInteractor.test.js b/shared/src/business/useCases/practitioners/getPractitionerByBarNumberInteractor.test.js index 003c1ffee3c..4e9a8f6c153 100644 --- a/shared/src/business/useCases/practitioners/getPractitionerByBarNumberInteractor.test.js +++ b/shared/src/business/useCases/practitioners/getPractitionerByBarNumberInteractor.test.js @@ -57,19 +57,26 @@ describe('getPractitionerByBarNumberInteractor', () => { }); expect(practitioner).toEqual({ + additionalPhone: undefined, admissionsDate: '2019-03-01T21:42:29.073Z', admissionsStatus: 'Active', + alternateEmail: undefined, barNumber: 'PP1234', birthYear: '1983', + email: undefined, employer: 'Private', + entityName: 'Practitioner', // we return all practitioner search results as a Practitioner user. firmName: 'GW Law Offices', firstName: 'Private', lastName: 'Practitioner', + middleName: undefined, name: 'Private Practitioner', originalBarState: 'Oklahoma', practitionerType: 'Attorney', role: User.ROLES.privatePractitioner, section: 'privatePractitioner', + suffix: undefined, + token: undefined, userId: '6805d1ab-18d0-43ec-bafb-654e83405416', }); }); @@ -115,14 +122,17 @@ describe('getPractitionerByBarNumberInteractor', () => { birthYear: '1983', email: undefined, employer: 'Private', + entityName: 'Practitioner', firmName: 'GW Law Offices', firstName: 'IRS', lastName: 'Practitioner', + middleName: undefined, name: 'IRS Practitioner', originalBarState: 'Oklahoma', practitionerType: 'Attorney', role: 'privatePractitioner', section: 'privatePractitioner', + suffix: undefined, token: undefined, userId: '6805d1ab-18d0-43ec-bafb-654e83405416', }); diff --git a/shared/src/business/useCases/practitioners/validateAddPractitionerInteractor.js b/shared/src/business/useCases/practitioners/validateAddPractitionerInteractor.js index fea68147448..64b36070371 100644 --- a/shared/src/business/useCases/practitioners/validateAddPractitionerInteractor.js +++ b/shared/src/business/useCases/practitioners/validateAddPractitionerInteractor.js @@ -1,3 +1,5 @@ +const { NewPractitioner } = require('../../entities/NewPractitioner'); + /** * validatePractitionerInteractor * @@ -10,9 +12,9 @@ exports.validateAddPractitionerInteractor = ({ applicationContext, practitioner, }) => { - const errors = new (applicationContext.getEntityConstructors().NewPractitioner)( - practitioner, - ).getFormattedValidationErrors(); + const errors = new NewPractitioner(practitioner, { + applicationContext, + }).getFormattedValidationErrors(); if (!errors) return null; return errors; diff --git a/shared/src/business/useCases/practitioners/validateAddPractitionerInteractor.test.js b/shared/src/business/useCases/practitioners/validateAddPractitionerInteractor.test.js index 45ebbb2f4d5..8bc46517544 100644 --- a/shared/src/business/useCases/practitioners/validateAddPractitionerInteractor.test.js +++ b/shared/src/business/useCases/practitioners/validateAddPractitionerInteractor.test.js @@ -1,16 +1,14 @@ +const { + applicationContext, +} = require('../../test/createTestApplicationContext'); const { validateAddPractitionerInteractor, } = require('./validateAddPractitionerInteractor'); -const { NewPractitioner } = require('../../entities/NewPractitioner'); describe('validateAddPractitionerInteractor', () => { it('returns the expected errors object on an empty practitioner', () => { const errors = validateAddPractitionerInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - NewPractitioner, - }), - }, + applicationContext, practitioner: {}, }); @@ -29,11 +27,7 @@ describe('validateAddPractitionerInteractor', () => { it('returns null on no errors', () => { const errors = validateAddPractitionerInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - NewPractitioner, - }), - }, + applicationContext, practitioner: { admissionsDate: '2019-03-01T21:40:46.415Z', admissionsStatus: 'Active', diff --git a/shared/src/business/useCases/processStreamRecordsInteractor.js b/shared/src/business/useCases/processStreamRecordsInteractor.js index 9bd7d13d7c1..869e23dbfc5 100644 --- a/shared/src/business/useCases/processStreamRecordsInteractor.js +++ b/shared/src/business/useCases/processStreamRecordsInteractor.js @@ -88,33 +88,48 @@ const filterRecords = async ({ applicationContext, records }) => { }, eventName: 'MODIFY', }); - } - if (caseRecord.dynamodb.Keys.sk.S.includes('document|')) { - const documentWithCaseInfo = { - ...AWS.DynamoDB.Converter.marshall(fullCase), - ...caseRecord.dynamodb.NewImage, - docketRecord: undefined, - documents: undefined, - entityName: undefined, - irsPractitioners: undefined, - privatePractitioners: undefined, - }; + //also reindex all of the documents on the case + const { documents } = fullCase; + for (const document of documents) { + if (document.documentContentsId) { + const buffer = await applicationContext + .getPersistenceGateway() + .getDocument({ + applicationContext, + documentId: document.documentContentsId, + protocol: 'S3', + useTempBucket: true, + }); - filteredRecords.push({ - dynamodb: { - Keys: { - pk: { - S: caseRecord.dynamodb.Keys.pk.S, - }, - sk: { - S: caseRecord.dynamodb.Keys.sk.S, + const { documentContents } = JSON.parse(buffer.toString()); + document.documentContents = documentContents; + } + + const documentWithCaseInfo = { + ...AWS.DynamoDB.Converter.marshall(fullCase), + ...AWS.DynamoDB.Converter.marshall(document), + docketRecord: undefined, + documents: undefined, + entityName: { S: 'Document' }, + sk: { S: `document|${document.documentId}` }, + }; + + filteredRecords.push({ + dynamodb: { + Keys: { + pk: { + S: caseRecord.dynamodb.Keys.pk.S, + }, + sk: { + S: `document|${document.documentId}`, + }, }, + NewImage: documentWithCaseInfo, }, - NewImage: documentWithCaseInfo, - }, - eventName: 'MODIFY', - }); + eventName: 'MODIFY', + }); + } } } @@ -132,8 +147,6 @@ exports.processStreamRecordsInteractor = async ({ recordsToProcess, }) => { applicationContext.logger.info('Time', createISODateString()); - const searchClient = applicationContext.getSearchClient(); - const honeybadger = applicationContext.initHoneybadger(); const filteredRecords = await filterRecords({ applicationContext, @@ -152,10 +165,14 @@ exports.processStreamRecordsInteractor = async ({ if (failedRecords.length) { for (const failedRecord of failedRecords) { try { - await searchClient.index({ - body: { ...failedRecord }, - id: `${failedRecord.pk.S}_${failedRecord.sk.S}`, - index: 'efcms', + await applicationContext.getPersistenceGateway().indexRecord({ + applicationContext, + fullRecord: { ...failedRecord }, + isAlreadyMarshalled: true, + record: { + recordPk: failedRecord.pk.S, + recordSk: failedRecord.sk.S, + }, }); } catch (e) { await applicationContext @@ -167,7 +184,7 @@ exports.processStreamRecordsInteractor = async ({ }); applicationContext.logger.info('Error', e); - honeybadger && honeybadger.notify(e); + await applicationContext.notifyHoneybadger(e); } } } @@ -202,7 +219,7 @@ exports.processStreamRecordsInteractor = async ({ }); applicationContext.logger.info('Error', e); - honeybadger && honeybadger.notify(e); + await applicationContext.notifyHoneybadger(e); } } } diff --git a/shared/src/business/useCases/processStreamRecordsInteractor.test.js b/shared/src/business/useCases/processStreamRecordsInteractor.test.js index 9fe7da20a29..6d7e6e59075 100644 --- a/shared/src/business/useCases/processStreamRecordsInteractor.test.js +++ b/shared/src/business/useCases/processStreamRecordsInteractor.test.js @@ -40,7 +40,7 @@ describe('processStreamRecordsInteractor', () => { expect(applicationContext.getSearchClient().bulk).not.toHaveBeenCalled(); }); - it('calls bulk function with correct params only for records with eventName "INSERT" or "MODIFY" and filters out workitem and user records', async () => { + it('calls bulk function with correct params only for records with eventName "INSERT" or "MODIFY" and filters out items that are not cases, documents, or useres', async () => { await processStreamRecordsInteractor({ applicationContext, recordsToProcess: [ @@ -94,6 +94,7 @@ describe('processStreamRecordsInteractor', () => { dynamodb: { Keys: { pk: { S: 'user|5' } }, NewImage: { + entityName: { S: 'User' }, pk: { S: 'user|5' }, sk: { S: 'user|5' }, userId: { S: '5' }, @@ -124,29 +125,24 @@ describe('processStreamRecordsInteractor', () => { expect(applicationContext.getSearchClient().bulk).toHaveBeenCalled(); expect( applicationContext.getSearchClient().bulk.mock.calls[0][0].body.length, - ).toEqual(10); + ).toEqual(4); expect( applicationContext.getSearchClient().bulk.mock.calls[0][0].body, ).toEqual([ - { index: { _id: '1_1', _index: 'efcms' } }, - { caseId: { S: '1' }, pk: { S: '1' }, sk: { S: '1' } }, - { index: { _id: '3_3', _index: 'efcms' } }, - { caseId: { S: '3' }, pk: { S: '3' }, sk: { S: '3' } }, - { index: { _id: '4_4', _index: 'efcms' } }, + { index: { _id: '4_4', _index: 'efcms-case' } }, { caseId: { S: '4' }, entityName: { S: 'Case' }, pk: { S: '4' }, sk: { S: '4' }, }, - { index: { _id: 'user|5_user|5', _index: 'efcms' } }, + { index: { _id: 'user|5_user|5', _index: 'efcms-user' } }, { + entityName: { S: 'User' }, pk: { S: 'user|5' }, sk: { S: 'user|5' }, userId: { S: '5' }, }, - { index: { _id: '6_6', _index: 'efcms' } }, - { documentId: { S: '6' }, pk: { S: '6' }, sk: { S: '6' } }, ]); }); @@ -161,14 +157,24 @@ describe('processStreamRecordsInteractor', () => { { dynamodb: { Keys: { pk: { S: '1' }, sk: { S: '2' } }, - NewImage: { caseId: { S: '1' }, pk: { S: '1' }, sk: { S: '1' } }, + NewImage: { + caseId: { S: '1' }, + entityName: { S: 'Case' }, + pk: { S: '1' }, + sk: { S: '1' }, + }, }, eventName: 'INSERT', }, { dynamodb: { Keys: { pk: { S: '3' }, sk: { S: '4' } }, - NewImage: { caseId: { S: '3' }, pk: { S: '3' }, sk: { S: '3' } }, + NewImage: { + caseId: { S: '3' }, + entityName: { S: 'Case' }, + pk: { S: '3' }, + sk: { S: '3' }, + }, }, eventName: 'DELETE', }, @@ -197,7 +203,12 @@ describe('processStreamRecordsInteractor', () => { { dynamodb: { Keys: { pk: { S: '1' }, sk: { S: '2' } }, - NewImage: { caseId: { S: '1' }, pk: { S: '1' }, sk: { S: '1' } }, + NewImage: { + caseId: { S: '1' }, + entityName: { S: 'Case' }, + pk: { S: '1' }, + sk: { S: '1' }, + }, }, eventName: 'INSERT', }, @@ -238,14 +249,24 @@ describe('processStreamRecordsInteractor', () => { { dynamodb: { Keys: { pk: { S: '1' }, sk: { S: '2' } }, - NewImage: { caseId: { S: '1' }, pk: { S: '1' }, sk: { S: '1' } }, + NewImage: { + caseId: { S: '1' }, + entityName: { S: 'Case' }, + pk: { S: '1' }, + sk: { S: '1' }, + }, }, eventName: 'INSERT', }, { dynamodb: { Keys: { pk: { S: '2' }, sk: { S: '3' } }, - NewImage: { caseId: { S: '2' }, pk: { S: '2' }, sk: { S: '2' } }, + NewImage: { + caseId: { S: '2' }, + entityName: { S: 'Case' }, + pk: { S: '2' }, + sk: { S: '2' }, + }, }, eventName: 'INSERT', }, @@ -284,14 +305,24 @@ describe('processStreamRecordsInteractor', () => { { dynamodb: { Keys: { pk: { S: '1' }, sk: { S: '2' } }, - NewImage: { caseId: { S: '1' }, pk: { S: '1' }, sk: { S: '2' } }, + NewImage: { + caseId: { S: '1' }, + entityName: { S: 'Case' }, + pk: { S: '1' }, + sk: { S: '2' }, + }, }, eventName: 'INSERT', }, { dynamodb: { Keys: { pk: { S: '2' }, sk: { S: '3' } }, - NewImage: { caseId: { S: '2' }, pk: { S: '2' }, sk: { S: '3' } }, + NewImage: { + caseId: { S: '2' }, + entityName: { S: 'Case' }, + pk: { S: '2' }, + sk: { S: '3' }, + }, }, eventName: 'INSERT', }, @@ -330,6 +361,7 @@ describe('processStreamRecordsInteractor', () => { .getCaseByCaseId.mockImplementation(({ caseId }) => ({ caseId, documents: [{ documentId: '1' }], + entityName: 'Case', pk: `case|${caseId}`, sk: `case|${caseId}`, })); @@ -342,6 +374,7 @@ describe('processStreamRecordsInteractor', () => { Keys: { pk: { S: 'case|1' }, sk: { S: 'document|1' } }, NewImage: { caseId: { S: '1' }, + entityName: { S: 'Document' }, pk: { S: 'case|1' }, sk: { S: 'document|1' }, }, @@ -350,9 +383,10 @@ describe('processStreamRecordsInteractor', () => { }, { dynamodb: { - Keys: { pk: { S: 'case|4' }, sk: { S: 'case|1' } }, + Keys: { pk: { S: 'case|4' }, sk: { S: 'case|4' } }, NewImage: { caseId: { S: '4' }, + entityName: { S: 'Case' }, pk: { S: 'case|4' }, sk: { S: 'case|4' }, }, @@ -371,31 +405,150 @@ describe('processStreamRecordsInteractor', () => { ).toMatchObject([[{ caseId: '1' }], [{ caseId: '4' }]]); expect( applicationContext.getSearchClient().bulk.mock.calls[0][0].body.length, - ).toEqual(10); + ).toEqual(12); expect( applicationContext.getSearchClient().bulk.mock.calls[0][0].body, ).toEqual([ - { index: { _id: 'case|1_document|1', _index: 'efcms' } }, - { caseId: { S: '1' }, pk: { S: 'case|1' }, sk: { S: 'document|1' } }, - { index: { _id: 'case|4_case|4', _index: 'efcms' } }, - { caseId: { S: '4' }, pk: { S: 'case|4' }, sk: { S: 'case|4' } }, - { index: { _id: 'case|1_case|1', _index: 'efcms' } }, + { index: { _id: 'case|1_document|1', _index: 'efcms-document' } }, + { + caseId: { S: '1' }, + entityName: { S: 'Document' }, + pk: { S: 'case|1' }, + sk: { S: 'document|1' }, + }, + { index: { _id: 'case|4_case|4', _index: 'efcms-case' } }, + { + caseId: { S: '4' }, + entityName: { S: 'Case' }, + pk: { S: 'case|4' }, + sk: { S: 'case|4' }, + }, + { index: { _id: 'case|1_case|1', _index: 'efcms-case' } }, { caseId: { S: '1' }, documents: { L: [{ M: { documentId: { S: '1' } } }] }, + entityName: { S: 'Case' }, pk: { S: 'case|1' }, sk: { S: 'case|1' }, }, // calls documents again because they are indexed again after the case - { index: { _id: 'case|1_document|1', _index: 'efcms' } }, - { caseId: { S: '1' }, pk: { S: 'case|1' }, sk: { S: 'document|1' } }, - { index: { _id: 'case|4_case|4', _index: 'efcms' } }, + { index: { _id: 'case|1_document|1', _index: 'efcms-document' } }, + { + caseId: { S: '1' }, + docketRecord: undefined, + documentId: { S: '1' }, + documents: undefined, + entityName: { S: 'Document' }, + irsPractitioners: undefined, + pk: { S: 'case|1' }, + privatePractitioners: undefined, + sk: { S: 'document|1' }, + }, + { + index: { _id: 'case|4_case|4', _index: 'efcms-case' }, + }, { caseId: { S: '4' }, documents: { L: [{ M: { documentId: { S: '1' } } }] }, + entityName: { S: 'Case' }, pk: { S: 'case|4' }, sk: { S: 'case|4' }, }, + { index: { _id: 'case|4_document|1', _index: 'efcms-document' } }, + { + caseId: { S: '4' }, + docketRecord: undefined, + documentId: { S: '1' }, + documents: undefined, + entityName: { S: 'Document' }, + irsPractitioners: undefined, + pk: { S: 'case|4' }, + privatePractitioners: undefined, + sk: { S: 'document|1' }, + }, + ]); + }); + + it('calls getDocument to get documentContents if a document contains documentContentsId', async () => { + applicationContext + .getPersistenceGateway() + .getCaseByCaseId.mockImplementation(({ caseId }) => ({ + caseId, + documents: [{ documentContentsId: '5', documentId: '1' }], + entityName: 'Case', + pk: `case|${caseId}`, + sk: `case|${caseId}`, + })); + applicationContext + .getPersistenceGateway() + .getDocument.mockReturnValue( + Buffer.from( + JSON.stringify({ documentContents: 'I am some document contents' }), + ), + ); + + await processStreamRecordsInteractor({ + applicationContext, + recordsToProcess: [ + { + dynamodb: { + Keys: { pk: { S: 'case|1' }, sk: { S: 'document|1' } }, + NewImage: { + caseId: { S: '1' }, + documentContentsId: { S: '5' }, + entityName: { S: 'Document' }, + pk: { S: 'case|1' }, + sk: { S: 'document|1' }, + }, + }, + eventName: 'INSERT', + }, + ], + }); + + expect( + applicationContext.getPersistenceGateway().getDocument, + ).toHaveBeenCalled(); + expect( + applicationContext.getSearchClient().bulk.mock.calls[0][0].body, + ).toEqual([ + { index: { _id: 'case|1_document|1', _index: 'efcms-document' } }, + { + caseId: { S: '1' }, + documentContentsId: { S: '5' }, + entityName: { S: 'Document' }, + pk: { S: 'case|1' }, + sk: { S: 'document|1' }, + }, + { index: { _id: 'case|1_case|1', _index: 'efcms-case' } }, + { + caseId: { S: '1' }, + documents: { + L: [ + { M: { documentContentsId: { S: '5' }, documentId: { S: '1' } } }, + ], + }, + entityName: { S: 'Case' }, + pk: { S: 'case|1' }, + sk: { S: 'case|1' }, + }, + // calls documents again because they are indexed again after the case + { index: { _id: 'case|1_document|1', _index: 'efcms-document' } }, + { + caseId: { S: '1' }, + docketRecord: undefined, + documentContents: { + S: 'I am some document contents', + }, + documentContentsId: { S: '5' }, + documentId: { S: '1' }, + documents: undefined, + entityName: { S: 'Document' }, + irsPractitioners: undefined, + pk: { S: 'case|1' }, + privatePractitioners: undefined, + sk: { S: 'document|1' }, + }, ]); }); @@ -412,6 +565,7 @@ describe('processStreamRecordsInteractor', () => { Keys: { pk: { S: 'case|1' }, sk: { S: 'document|1' } }, NewImage: { caseId: { S: '1' }, + entityName: { S: 'Document' }, pk: { S: 'case|1' }, sk: { S: 'document|1' }, }, @@ -424,15 +578,17 @@ describe('processStreamRecordsInteractor', () => { expect(applicationContext.getSearchClient().bulk).toHaveBeenCalled(); expect( applicationContext.getSearchClient().bulk.mock.calls[0][0].body.length, - ).toEqual(4); // calls 4 times because documents are indexed again after the case + ).toEqual(2); expect( applicationContext.getSearchClient().bulk.mock.calls[0][0].body, ).toEqual([ - // calls multiple times because documents are indexed after the case is indexed - { index: { _id: 'case|1_document|1', _index: 'efcms' } }, - { caseId: { S: '1' }, pk: { S: 'case|1' }, sk: { S: 'document|1' } }, - { index: { _id: 'case|1_document|1', _index: 'efcms' } }, - { caseId: { S: '1' }, pk: { S: 'case|1' }, sk: { S: 'document|1' } }, + { index: { _id: 'case|1_document|1', _index: 'efcms-document' } }, + { + caseId: { S: '1' }, + entityName: { S: 'Document' }, + pk: { S: 'case|1' }, + sk: { S: 'document|1' }, + }, ]); }); @@ -444,6 +600,7 @@ describe('processStreamRecordsInteractor', () => { dynamodb: { Keys: { pk: { S: 'user|1' }, sk: { S: 'user|1' } }, NewImage: { + entityName: { S: 'User' }, pk: { S: 'user|1' }, sk: { S: 'user|1' }, userId: { S: '1' }, @@ -464,8 +621,13 @@ describe('processStreamRecordsInteractor', () => { expect( applicationContext.getSearchClient().bulk.mock.calls[0][0].body, ).toEqual([ - { index: { _id: 'user|1_user|1', _index: 'efcms' } }, - { pk: { S: 'user|1' }, sk: { S: 'user|1' }, userId: { S: '1' } }, + { index: { _id: 'user|1_user|1', _index: 'efcms-user' } }, + { + entityName: { S: 'User' }, + pk: { S: 'user|1' }, + sk: { S: 'user|1' }, + userId: { S: '1' }, + }, ]); }); }); diff --git a/shared/src/business/useCases/public/getPublicDownloadPolicyUrlInteractor.js b/shared/src/business/useCases/public/getPublicDownloadPolicyUrlInteractor.js index 4af47131a09..2e374ebd04a 100644 --- a/shared/src/business/useCases/public/getPublicDownloadPolicyUrlInteractor.js +++ b/shared/src/business/useCases/public/getPublicDownloadPolicyUrlInteractor.js @@ -25,6 +25,12 @@ exports.getPublicDownloadPolicyUrlInteractor = async ({ const caseEntity = new Case(caseToCheck, { applicationContext }); + if (caseEntity.isSealed) { + throw new UnauthorizedError( + 'Unauthorized to access documents in a sealed case', + ); + } + const documentEntity = caseEntity.getDocumentById({ documentId }); const isPrivate = isPrivateDocument(documentEntity, caseEntity.docketRecord); diff --git a/shared/src/business/useCases/public/getPublicDownloadPolicyUrlInteractor.test.js b/shared/src/business/useCases/public/getPublicDownloadPolicyUrlInteractor.test.js index a4e37fd195e..21bb27d86cc 100644 --- a/shared/src/business/useCases/public/getPublicDownloadPolicyUrlInteractor.test.js +++ b/shared/src/business/useCases/public/getPublicDownloadPolicyUrlInteractor.test.js @@ -31,7 +31,30 @@ describe('getPublicDownloadPolicyUrlInteractor', () => { caseId: '123', documentId: 'c6b81f4d-1e47-423a-8caf-6d2fdc3d3859', }), - ).rejects.toThrow(); + ).rejects.toThrow('Unauthorized'); + }); + + it('should throw an error for a document that is part of a sealed case', async () => { + applicationContext.getCurrentUser.mockReturnValue( + MOCK_USERS['a7d90c05-f6cd-442c-a168-202db587f16f'], + ); + applicationContext.getPersistenceGateway().getCaseByCaseId.mockReturnValue({ + ...MOCK_CASE, + sealedDate: '2019-03-01T21:40:46.415Z', + }); + applicationContext + .getPersistenceGateway() + .getPublicDownloadPolicyUrl.mockReturnValue( + 'http://example.com/document/c6b81f4d-1e47-423a-8caf-6d2fdc3d3859', + ); + + await expect( + getPublicDownloadPolicyUrlInteractor({ + applicationContext, + caseId: '123', + documentId: 'c6b81f4d-1e47-423a-8caf-6d2fdc3d3859', + }), + ).rejects.toThrow('Unauthorized to access documents in a sealed case'); }); it('should return a url for a document that is public accessible', async () => { diff --git a/shared/src/business/useCases/public/orderPublicSearchInteractor.js b/shared/src/business/useCases/public/orderPublicSearchInteractor.js index 94fbae9c341..54892ad992a 100644 --- a/shared/src/business/useCases/public/orderPublicSearchInteractor.js +++ b/shared/src/business/useCases/public/orderPublicSearchInteractor.js @@ -1,32 +1,50 @@ -const { map } = require('lodash'); -const { Order } = require('../../entities/orders/Order'); +const { Document } = require('../../entities/Document'); +const { OrderSearch } = require('../../entities/orders/OrderSearch'); /** * orderPublicSearchInteractor * - * @param {object} providers object containing applicationContext and other necessary parameters needed for the interactor + * @param {object} providers the providers object containing applicationContext, orderKeyword, caseTitleOrPetitioner, docketNumber, judge, startDate, endDate * @param {object} providers.applicationContext application context object - * @param {object} providers.orderKeyword the keyword to be used in the order search - * @returns {object} the case data + * @returns {object} the order search results */ exports.orderPublicSearchInteractor = async ({ applicationContext, caseTitleOrPetitioner, docketNumber, - endDate, + endDateDay, + endDateMonth, + endDateYear, judge, orderKeyword, - startDate, + startDateDay, + startDateMonth, + startDateYear, }) => { - const orderEventCodes = map(Order.ORDER_TYPES, 'eventCode'); - return await applicationContext.getPersistenceGateway().orderKeywordSearch({ - applicationContext, + const orderSearch = new OrderSearch({ caseTitleOrPetitioner, docketNumber, - endDate, + endDateDay, + endDateMonth, + endDateYear, judge, - orderEventCodes, orderKeyword, - startDate, + startDateDay, + startDateMonth, + startDateYear, }); + + const rawSearch = orderSearch.validate().toRawObject(); + + const results = await applicationContext + .getPersistenceGateway() + .orderKeywordSearch({ + applicationContext, + orderEventCodes: Document.ORDER_DOCUMENT_TYPES, + ...rawSearch, + }); + + const filteredResults = results.filter(item => !item.isSealed); + + return filteredResults; }; diff --git a/shared/src/business/useCases/public/orderPublicSearchInteractor.test.js b/shared/src/business/useCases/public/orderPublicSearchInteractor.test.js index b4ec97bff11..876fc8e9025 100644 --- a/shared/src/business/useCases/public/orderPublicSearchInteractor.test.js +++ b/shared/src/business/useCases/public/orderPublicSearchInteractor.test.js @@ -4,6 +4,7 @@ const { const { orderPublicSearchInteractor, } = require('./orderPublicSearchInteractor'); +const { Document } = require('../../entities/Document'); describe('orderPublicSearchInteractor', () => { beforeEach(() => { @@ -31,12 +32,38 @@ describe('orderPublicSearchInteractor', () => { eventCode: 'ODD', signedJudgeName: 'Guy Fieri', }, + { + caseCaption: 'Gal Fieri, Petitioner', + caseId: '3', + docketNumber: '104-19', + docketNumberSuffix: 'AAA', + documentContents: 'Baby Ruth is gross', + documentTitle: 'Order for Baby Ruth', + eventCode: 'ODD', + isSealed: true, + signedJudgeName: 'Gal Fieri', + }, ]); }); - it('returns results with an authorized user role (petitionsclerk)', async () => { + it('should only search for order document types', async () => { + await orderPublicSearchInteractor({ + applicationContext, + orderKeyword: 'fish', + }); + + expect( + applicationContext.getPersistenceGateway().orderKeywordSearch.mock + .calls[0][0], + ).toMatchObject({ + orderEventCodes: Document.ORDER_DOCUMENT_TYPES, + }); + }); + + it('returns results with sealed cases filtered out', async () => { const result = await orderPublicSearchInteractor({ applicationContext, + orderKeyword: 'fish', }); expect(result).toMatchObject([ diff --git a/shared/src/business/useCases/reprocessFailedRecordsInteractor.js b/shared/src/business/useCases/reprocessFailedRecordsInteractor.js index 04df4b8af4a..5533db8487c 100644 --- a/shared/src/business/useCases/reprocessFailedRecordsInteractor.js +++ b/shared/src/business/useCases/reprocessFailedRecordsInteractor.js @@ -1,5 +1,75 @@ const { createISODateString } = require('../utilities/DateHandler'); +const checkSearchClientMappings = async ({ applicationContext, index }) => { + /** + * recursively searches the provided object for the provided key + * and returns the count of instances of that key + * + * @param {object} object the object to search + * @param {string} key the key to search for + * @returns {number} the total number of key matches + */ + function countValues(object, key) { + let count = 0; + Object.keys(object).forEach(k => { + if (k === key) { + count++; + } + if (object[k] && typeof object[k] === 'object') { + const countToAdd = countValues(object[k], key); + count = count + countToAdd; + } + }); + return count; + } + + const fields = await applicationContext + .getPersistenceGateway() + .getIndexMappingFields({ + applicationContext, + index, + }); + + const mappingLimit = await applicationContext + .getPersistenceGateway() + .getIndexMappingLimit({ + applicationContext, + index, + }); + + let totalTypes = 0; + let fieldText = ''; + + for (let field of Object.keys(fields)) { + const typeMatches = countValues(fields[field], 'type'); + + if (typeMatches > 50) { + fieldText += `${field}: ${typeMatches}, `; + } + totalTypes += typeMatches; + } + + if (fieldText !== '') { + await applicationContext.notifyHoneybadger( + `Warning: Search Client creating greater than 50 indexes for ${index} on the following fields: ${fieldText.substring( + 0, + fieldText.length - 2, + )}`, + ); + } + + const currentPercent = (totalTypes / mappingLimit) * 100; + if (currentPercent >= 75) { + await applicationContext.notifyHoneybadger( + `Warning: Search Client Mappings have reached the 75% threshold for ${index} - currently ${currentPercent}%`, + ); + } else if (currentPercent >= 50) { + await applicationContext.notifyHoneybadger( + `Warning: Search Client Mappings have reached the 50% threshold for ${index} - currently ${currentPercent}%`, + ); + } +}; + /** * @param {object} providers the providers object * @param {object} providers.applicationContext the application context @@ -7,7 +77,14 @@ const { createISODateString } = require('../utilities/DateHandler'); */ exports.reprocessFailedRecordsInteractor = async ({ applicationContext }) => { applicationContext.logger.info('Time', createISODateString()); - const honeybadger = applicationContext.initHoneybadger(); + + // Check mapping counts + const elasticsearchIndexes = applicationContext.getElasticsearchIndexes(); + await Promise.all( + elasticsearchIndexes.map(index => + checkSearchClientMappings({ applicationContext, index }), + ), + ); const recordsToProcess = await applicationContext .getPersistenceGateway() @@ -63,7 +140,7 @@ exports.reprocessFailedRecordsInteractor = async ({ applicationContext }) => { }); } catch (e) { applicationContext.logger.info('Error', e); - honeybadger && honeybadger.notify(e); + await applicationContext.notifyHoneybadger(e); } } diff --git a/shared/src/business/useCases/reprocessFailedRecordsInteractor.test.js b/shared/src/business/useCases/reprocessFailedRecordsInteractor.test.js index 333f5f5ca90..e167ee114f4 100644 --- a/shared/src/business/useCases/reprocessFailedRecordsInteractor.test.js +++ b/shared/src/business/useCases/reprocessFailedRecordsInteractor.test.js @@ -4,6 +4,8 @@ const { const { applicationContext } = require('../test/createTestApplicationContext'); describe('reprocessFailedRecordsInteractor', () => { + const notifySpy = jest.fn(); + beforeEach(() => { applicationContext.environment.stage = 'local'; @@ -24,9 +26,104 @@ describe('reprocessFailedRecordsInteractor', () => { pk: 'abc|123', sk: 'abc', }); + applicationContext .getPersistenceGateway() .indexRecord.mockReturnValue(null); + + applicationContext + .getPersistenceGateway() + .getIndexMappingLimit.mockReturnValue(20); + + applicationContext + .getPersistenceGateway() + .getIndexMappingFields.mockReturnValue({ + field1: { + properties: { + S: { + type: 'text', + }, + }, + }, + field2: { + properties: { + S: { + type: 'text', + }, + }, + }, + field3: { + properties: { + S: { + type: 'text', + }, + }, + }, + field4: { + properties: { + S: { + type: 'text', + }, + }, + }, + field5: { + properties: { + S: { + type: 'text', + }, + }, + }, + }); + applicationContext.notifyHoneybadger.mockImplementation(notifySpy); + }); + + it('checks the current mapping count and notifies if it is at 50% of the limit', async () => { + applicationContext + .getPersistenceGateway() + .getIndexMappingLimit.mockReturnValue(10); + + await reprocessFailedRecordsInteractor({ + applicationContext, + }); + + expect(notifySpy).toHaveBeenCalled(); + expect(notifySpy.mock.calls[0][0]).toContain('50% threshold'); + }); + + it('checks the current mapping count and notifies if it is at 75% of the limit', async () => { + applicationContext + .getPersistenceGateway() + .getIndexMappingLimit.mockReturnValue(6); + + await reprocessFailedRecordsInteractor({ + applicationContext, + }); + + expect(notifySpy).toHaveBeenCalled(); + expect(notifySpy.mock.calls[0][0]).toContain('75% threshold'); + }); + + it('checks the current mapping count and notifies for fields over 50 matches', async () => { + applicationContext + .getPersistenceGateway() + .getIndexMappingFields.mockReturnValue({ + field1: { + properties: (() => { + const fiftyOneProperties = {}; + for (let i = 0; i < 51; i++) { + fiftyOneProperties[`prop_${i}`] = { type: 'text' }; + } + return fiftyOneProperties; + })(), + }, + }); + + await reprocessFailedRecordsInteractor({ + applicationContext, + }); + + expect(notifySpy).toHaveBeenCalled(); + expect(notifySpy.mock.calls[0][0]).toContain('greater than 50 indexes'); }); it('does not call index function if there are no records to process', async () => { diff --git a/shared/src/business/useCases/saveCaseDetailInternalEditInteractor.js b/shared/src/business/useCases/saveCaseDetailInternalEditInteractor.js index 519c1237394..7a1ef43af0c 100644 --- a/shared/src/business/useCases/saveCaseDetailInternalEditInteractor.js +++ b/shared/src/business/useCases/saveCaseDetailInternalEditInteractor.js @@ -34,22 +34,61 @@ exports.saveCaseDetailInternalEditInteractor = async ({ throw new UnprocessableEntityError(); } - if (!isEmpty(caseToUpdate.contactPrimary)) { - caseToUpdate.contactPrimary = ContactFactory.createContacts({ - contactInfo: { primary: caseToUpdate.contactPrimary }, - partyType: caseToUpdate.partyType, + const editableFields = { + caseCaption: caseToUpdate.caseCaption, + caseType: caseToUpdate.caseType, + contactPrimary: caseToUpdate.contactPrimary, + contactSecondary: caseToUpdate.contactSecondary, + docketNumber: caseToUpdate.docketNumber, + docketNumberSuffix: caseToUpdate.docketNumberSuffix, + filingType: caseToUpdate.filingType, + hasIrsNotice: caseToUpdate.hasIrsNotice, + hasVerifiedIrsNotice: caseToUpdate.hasVerifiedIrsNotice, + irsNoticeDate: caseToUpdate.irsNoticeDate, + noticeOfAttachments: caseToUpdate.noticeOfAttachments, + orderForAmendedPetition: caseToUpdate.orderForAmendedPetition, + orderForAmendedPetitionAndFilingFee: + caseToUpdate.orderForAmendedPetitionAndFilingFee, + orderForFilingFee: caseToUpdate.orderForFilingFee, + orderForOds: caseToUpdate.orderForOds, + orderForRatification: caseToUpdate.orderForRatification, + orderToShowCause: caseToUpdate.orderToShowCause, + partyType: caseToUpdate.partyType, + petitionPaymentDate: caseToUpdate.petitionPaymentDate, + petitionPaymentMethod: caseToUpdate.petitionPaymentMethod, + petitionPaymentStatus: caseToUpdate.petitionPaymentStatus, + petitionPaymentWaivedDate: caseToUpdate.petitionPaymentWaivedDate, + procedureType: caseToUpdate.procedureType, + }; + + const theCase = await applicationContext + .getPersistenceGateway() + .getCaseByCaseId({ + applicationContext, + caseId, + }); + + const fullCase = { + ...theCase, + ...editableFields, + }; + + if (!isEmpty(fullCase.contactPrimary)) { + fullCase.contactPrimary = ContactFactory.createContacts({ + contactInfo: { primary: fullCase.contactPrimary }, + partyType: fullCase.partyType, }).primary.toRawObject(); } - if (!isEmpty(caseToUpdate.contactSecondary)) { - caseToUpdate.contactSecondary = ContactFactory.createContacts({ - contactInfo: { secondary: caseToUpdate.contactSecondary }, - partyType: caseToUpdate.partyType, + if (!isEmpty(fullCase.contactSecondary)) { + fullCase.contactSecondary = ContactFactory.createContacts({ + contactInfo: { secondary: fullCase.contactSecondary }, + partyType: fullCase.partyType, }).secondary.toRawObject(); } - const updatedCase = new Case(caseToUpdate, { applicationContext }) - .setRequestForTrialDocketRecord(caseToUpdate.preferredTrialCity, { + const updatedCase = new Case(fullCase, { applicationContext }) + .setRequestForTrialDocketRecord(fullCase.preferredTrialCity, { applicationContext, }) .validate() diff --git a/shared/src/business/useCases/saveCaseDetailInternalEditInteractor.test.js b/shared/src/business/useCases/saveCaseDetailInternalEditInteractor.test.js index cdf3aa2adfd..7fcbec3490c 100644 --- a/shared/src/business/useCases/saveCaseDetailInternalEditInteractor.test.js +++ b/shared/src/business/useCases/saveCaseDetailInternalEditInteractor.test.js @@ -12,6 +12,16 @@ const MOCK_CASE = { caseCaption: 'Caption', caseId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', caseType: 'Other', + contactPrimary: { + address1: '123 Main St', + city: 'Somewhere', + countryType: 'domestic', + email: 'fieri@example.com', + name: 'Guy Fieri', + phone: '1234567890', + postalCode: '12345', + state: 'CA', + }, createdAt: new Date().toISOString(), docketNumber: '56789-18', documents: [ @@ -49,53 +59,40 @@ beforeAll(() => { role: User.ROLES.petitionsClerk, userId: 'petitionsclerk', }); + + applicationContext + .getPersistenceGateway() + .getCaseByCaseId.mockReturnValue(MOCK_CASE); }); describe('updateCase', () => { it('should throw an error if the caseToUpdate passed in is an invalid case', async () => { - let error; - try { - await saveCaseDetailInternalEditInteractor({ + await expect( + saveCaseDetailInternalEditInteractor({ applicationContext, caseId: MOCK_CASE.caseId, caseToUpdate: omit(MOCK_CASE, 'docketNumber'), - petitioners: [{ name: 'Test Petitioner' }], - }); - } catch (err) { - error = err; - } - expect(error).not.toBeNull(); - expect(error.message).toContain( - 'The Case entity was invalid ValidationError: "docketNumber" is required', - ); + }), + ).rejects.toThrow('The Case entity was invalid'); }); it('should throw an error if caseToUpdate is not passed in', async () => { - let error; - try { - await saveCaseDetailInternalEditInteractor({ + await expect( + saveCaseDetailInternalEditInteractor({ applicationContext, caseId: MOCK_CASE.caseId, - petitioners: [{ name: 'Test Petitioner' }], - }); - } catch (err) { - error = err; - } - expect(error).not.toBeNull(); - expect(error.message).toContain('cannot process'); + }), + ).rejects.toThrow('cannot process'); }); it('should update a case', async () => { const caseToUpdate = Object.assign(MOCK_CASE); caseToUpdate.documents = MOCK_DOCUMENTS; - let updatedCase; - - updatedCase = await saveCaseDetailInternalEditInteractor({ + const updatedCase = await saveCaseDetailInternalEditInteractor({ applicationContext, caseId: caseToUpdate.caseId, caseToUpdate: caseToUpdate, - petitioners: [{ name: 'Test Petitioner' }], }); const returnedDocument = omit(updatedCase.documents[0], [ @@ -158,13 +155,12 @@ describe('updateCase', () => { expect(returnedDocument).toMatchObject(documentToMatch); }); - it('should not fail even if the primary or secondary contact is empty', async () => { + it('should fail if the primary or secondary contact is empty', async () => { const caseToUpdate = Object.assign(MOCK_CASE); caseToUpdate.documents = MOCK_DOCUMENTS; - let error = null; - try { - await saveCaseDetailInternalEditInteractor({ + await expect( + saveCaseDetailInternalEditInteractor({ applicationContext, caseId: caseToUpdate.caseId, caseToUpdate: { @@ -172,12 +168,8 @@ describe('updateCase', () => { contactPrimary: null, contactSecondary: {}, }, - petitioners: [{ name: 'Test Petitioner' }], - }); - } catch (err) { - error = err; - } - expect(error).toBeNull(); + }), + ).rejects.toThrow('The Case entity was invalid'); }); it('should throw an error if the user is unauthorized to update a case', async () => { @@ -186,19 +178,13 @@ describe('updateCase', () => { userId: 'nope', }); - let error; - try { - await saveCaseDetailInternalEditInteractor({ + await expect( + saveCaseDetailInternalEditInteractor({ applicationContext, caseId: MOCK_CASE.caseId, caseToUpdate: MOCK_CASE, - petitioners: [{ name: 'Test Petitioner' }], - }); - } catch (err) { - error = err; - } - expect(error).not.toBeNull(); - expect(error.message).toContain('Unauthorized for update case'); + }), + ).rejects.toThrow('Unauthorized for update case'); }); it('should throw an error if the user is unauthorized to update a case part deux', async () => { @@ -207,17 +193,12 @@ describe('updateCase', () => { userId: 'nope', }); - let error; - try { - await saveCaseDetailInternalEditInteractor({ + await expect( + saveCaseDetailInternalEditInteractor({ applicationContext, caseId: '123', caseToUpdate: MOCK_CASE, - }); - } catch (err) { - error = err; - } - expect(error).not.toBeNull(); - expect(error.message).toContain('Unauthorized for update case'); + }), + ).rejects.toThrow('Unauthorized for update case'); }); }); diff --git a/shared/src/business/useCases/serveCaseToIrs/serveCaseToIrsInteractor.js b/shared/src/business/useCases/serveCaseToIrs/serveCaseToIrsInteractor.js index c0abac97f3b..275eea42d49 100644 --- a/shared/src/business/useCases/serveCaseToIrs/serveCaseToIrsInteractor.js +++ b/shared/src/business/useCases/serveCaseToIrs/serveCaseToIrsInteractor.js @@ -6,7 +6,9 @@ const { isAuthorized, ROLE_PERMISSIONS, } = require('../../../authorization/authorizationClientService'); +const { Case } = require('../../entities/cases/Case'); const { createISODateString } = require('../../utilities/DateHandler'); +const { DocketRecord } = require('../../entities/DocketRecord'); const { Document } = require('../../entities/Document'); const { PDFDocument } = require('pdf-lib'); const { PETITIONS_SECTION } = require('../../entities/WorkQueue'); @@ -16,8 +18,6 @@ exports.addDocketEntryForPaymentStatus = ({ applicationContext, caseEntity, }) => { - const { Case, DocketRecord } = applicationContext.getEntityConstructors(); - if (caseEntity.petitionPaymentStatus === Case.PAYMENT_STATUS.PAID) { caseEntity.addDocketRecord( new DocketRecord( @@ -107,7 +107,6 @@ exports.serveCaseToIrsInteractor = async ({ applicationContext, caseId }) => { caseId: caseId, }); - const { Case } = applicationContext.getEntityConstructors(); const caseEntity = new Case(caseToBatch, { applicationContext }); const servedParties = aggregatePartiesForService(caseEntity); diff --git a/shared/src/business/useCases/startCase/validateStartCaseWizardInteractor.js b/shared/src/business/useCases/startCase/validateStartCaseWizardInteractor.js index 2e110d90651..f79e4d0b432 100644 --- a/shared/src/business/useCases/startCase/validateStartCaseWizardInteractor.js +++ b/shared/src/business/useCases/startCase/validateStartCaseWizardInteractor.js @@ -1,3 +1,7 @@ +const { + CaseExternalInformationFactory, +} = require('../../entities/cases/CaseExternalInformationFactory'); + /** * validateStartCaseWizardInteractor * @@ -10,8 +14,8 @@ exports.validateStartCaseWizardInteractor = ({ applicationContext, petition, }) => { - const errors = new (applicationContext.getEntityConstructors().CaseExternalInformationFactory)( - petition, - ).getFormattedValidationErrors(); + const errors = new CaseExternalInformationFactory(petition, { + applicationContext, + }).getFormattedValidationErrors(); return errors || null; }; diff --git a/shared/src/business/useCases/startCase/validateStartCaseWizardInteractor.test.js b/shared/src/business/useCases/startCase/validateStartCaseWizardInteractor.test.js index 95ba19bced1..d2f766286fd 100644 --- a/shared/src/business/useCases/startCase/validateStartCaseWizardInteractor.test.js +++ b/shared/src/business/useCases/startCase/validateStartCaseWizardInteractor.test.js @@ -1,6 +1,6 @@ const { - CaseExternalInformationFactory, -} = require('../../entities/cases/CaseExternalInformationFactory'); + applicationContext, +} = require('../../test/createTestApplicationContext'); const { validateStartCaseWizardInteractor, } = require('./validateStartCaseWizardInteractor'); @@ -9,11 +9,7 @@ const { MOCK_CASE } = require('../../../test/mockCase'); describe('validateStartCaseWizardInteractor', () => { it('returns the expected errors object on an empty petition', () => { const errors = validateStartCaseWizardInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - CaseExternalInformationFactory, - }), - }, + applicationContext, petition: {}, }); @@ -31,11 +27,7 @@ describe('validateStartCaseWizardInteractor', () => { it('returns null for a valid petition', () => { const errors = validateStartCaseWizardInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - CaseExternalInformationFactory, - }), - }, + applicationContext, petition: { ...MOCK_CASE, contactPrimary: { diff --git a/shared/src/business/useCases/trialSessions/batchDownloadTrialSessionInteractor.js b/shared/src/business/useCases/trialSessions/batchDownloadTrialSessionInteractor.js index c394f4d3a42..d677c58c1ff 100644 --- a/shared/src/business/useCases/trialSessions/batchDownloadTrialSessionInteractor.js +++ b/shared/src/business/useCases/trialSessions/batchDownloadTrialSessionInteractor.js @@ -57,13 +57,13 @@ const batchDownloadTrialSessionInteractor = async ({ sessionCases = sessionCases .filter(caseToFilter => caseToFilter.status !== Case.STATUS_TYPES.closed) .map(caseToBatch => { - const caseName = Case.getCaseCaptionNames(caseToBatch.caseCaption); - const caseFolder = `${caseToBatch.docketNumber}, ${caseName}`; + const caseTitle = Case.getCaseTitle(caseToBatch.caseCaption); + const caseFolder = `${caseToBatch.docketNumber}, ${caseTitle}`; return { ...caseToBatch, caseFolder, - caseName, + caseTitle, }; }); @@ -117,25 +117,33 @@ const batchDownloadTrialSessionInteractor = async ({ await onDocketRecordCreation(); - for (let index = 0; index < sessionCases.length; index++) { - let { caseId } = sessionCases[index]; - extraFiles.push( - await applicationContext - .getUseCases() - .generateDocketRecordPdfInteractor({ - applicationContext, - caseId, - includePartyDetail: true, - }) - .then(async result => { - await onDocketRecordCreation(caseId); - return result; - }), - ); - extraFileNames.push( - `${sessionCases[index].caseFolder}/0_Docket Record.pdf`, - ); - } + const generateDocumentAndDocketRecordForCase = async sessionCase => { + const result = await applicationContext + .getUseCases() + .generateDocketRecordPdfInteractor({ + applicationContext, + caseId: sessionCase.caseId, + includePartyDetail: true, + }); + + const document = await applicationContext + .getPersistenceGateway() + .getDocument({ + applicationContext, + caseId: sessionCase.caseId, + documentId: result.fileId, + protocol: 'S3', + useTempBucket: true, + }); + + await onDocketRecordCreation({ caseId: sessionCase.caseId }); + + extraFiles.push(document); + + extraFileNames.push(`${sessionCase.caseFolder}/0_Docket Record.pdf`); + }; + + await Promise.all(sessionCases.map(generateDocumentAndDocketRecordForCase)); const onEntry = entryData => { applicationContext.getNotificationGateway().sendNotificationToUser({ diff --git a/shared/src/business/useCases/trialSessions/canSetTrialSessionAsCalendaredInteractor.js b/shared/src/business/useCases/trialSessions/canSetTrialSessionAsCalendaredInteractor.js index 55cdcb5df6f..2b8069af6d9 100644 --- a/shared/src/business/useCases/trialSessions/canSetTrialSessionAsCalendaredInteractor.js +++ b/shared/src/business/useCases/trialSessions/canSetTrialSessionAsCalendaredInteractor.js @@ -2,6 +2,7 @@ const { isAuthorized, ROLE_PERMISSIONS, } = require('../../../authorization/authorizationClientService'); +const { TrialSession } = require('../../entities/trialSessions/TrialSession'); const { UnauthorizedError } = require('../../../errors/errors'); /** @@ -22,10 +23,12 @@ exports.canSetTrialSessionAsCalendaredInteractor = ({ throw new UnauthorizedError('Unauthorized'); } - const { TrialSession } = applicationContext.getEntityConstructors(); const trialSessionEntity = new TrialSession(trialSession, { applicationContext, }); - return trialSessionEntity.canSetAsCalendared(); + const canSetAsCalendared = trialSessionEntity.canSetAsCalendared(); + const emptyFields = trialSessionEntity.getEmptyFields(); + + return { canSetAsCalendared, emptyFields }; }; diff --git a/shared/src/business/useCases/trialSessions/canSetTrialSessionAsCalendaredInteractor.test.js b/shared/src/business/useCases/trialSessions/canSetTrialSessionAsCalendaredInteractor.test.js index c59a7924805..5f230d796ec 100644 --- a/shared/src/business/useCases/trialSessions/canSetTrialSessionAsCalendaredInteractor.test.js +++ b/shared/src/business/useCases/trialSessions/canSetTrialSessionAsCalendaredInteractor.test.js @@ -19,7 +19,6 @@ let user; describe('canSetTrialSessionAsCalendaredInteractor', () => { beforeEach(() => { - applicationContext.environment.stage = 'local'; applicationContext.getCurrentUser.mockImplementation(() => user); }); @@ -57,6 +56,9 @@ describe('canSetTrialSessionAsCalendaredInteractor', () => { trialSession: MOCK_TRIAL, }); - expect(result).toEqual(false); + expect(result).toEqual({ + canSetAsCalendared: false, + emptyFields: ['address1', 'city', 'state', 'postalCode', 'judge'], + }); }); }); diff --git a/shared/src/business/useCases/trialSessions/generateStandingPretrialOrderInteractor.js b/shared/src/business/useCases/trialSessions/generateStandingPretrialOrderInteractor.js index 82a373dc942..45cec502f13 100644 --- a/shared/src/business/useCases/trialSessions/generateStandingPretrialOrderInteractor.js +++ b/shared/src/business/useCases/trialSessions/generateStandingPretrialOrderInteractor.js @@ -1,3 +1,6 @@ +const { formatDateString, formatNow } = require('../../utilities/DateHandler'); +const { getCaseCaptionMeta } = require('../../utilities/getCaseCaptionMeta'); + /** * generateStandingPretrialOrderInteractor * @@ -26,32 +29,26 @@ exports.generateStandingPretrialOrderInteractor = async ({ docketNumber, }); - const { city, judge, startDate, startTime, state } = trialSession; + const { startDate } = trialSession; + const { docketNumberWithSuffix } = caseDetail; + const { caseCaptionExtension, caseTitle } = getCaseCaptionMeta(caseDetail); - const { caseCaption, docketNumberSuffix } = caseDetail; + const fullStartDate = formatDateString(startDate, 'dddd, MMMM D, YYYY'); + const footerDate = formatNow('MMDDYYYY'); - const contentHtml = await applicationContext - .getTemplateGenerators() - .generateStandingPretrialOrderTemplate({ + return await applicationContext + .getDocumentGenerators() + .standingPretrialOrder({ applicationContext, - content: { - caseCaption, - docketNumberWithSuffix: docketNumber + (docketNumberSuffix || ''), + data: { + caseCaptionExtension, + caseTitle, + docketNumberWithSuffix, + footerDate, trialInfo: { - city, - judge, - startDate, - startTime, - state, + ...trialSession, + fullStartDate, }, }, }); - - return await applicationContext.getUseCases().generatePdfFromHtmlInteractor({ - applicationContext, - contentHtml, - headerHtml: - '
', - overwriteHeader: true, - }); }; diff --git a/shared/src/business/useCases/trialSessions/generateStandingPretrialOrderInteractor.test.js b/shared/src/business/useCases/trialSessions/generateStandingPretrialOrderInteractor.test.js index 364f1447051..c47f6dfeabe 100644 --- a/shared/src/business/useCases/trialSessions/generateStandingPretrialOrderInteractor.test.js +++ b/shared/src/business/useCases/trialSessions/generateStandingPretrialOrderInteractor.test.js @@ -7,18 +7,6 @@ const { describe('generateStandingPretrialOrderInteractor', () => { beforeEach(() => { - applicationContext - .getUseCases() - .generatePdfFromHtmlInteractor.mockImplementation( - ({ contentHtml }) => contentHtml, - ); - - applicationContext - .getTemplateGenerators() - .generateStandingPretrialOrderTemplate.mockImplementation( - ({ content }) => `${content.docketNumberWithSuffix}`, - ); - applicationContext .getPersistenceGateway() .getCaseByDocketNumber.mockImplementation(({ docketNumber }) => { @@ -51,8 +39,8 @@ describe('generateStandingPretrialOrderInteractor', () => { })); }); - it('should generate a template with the case and trial information and call the pdf generator', async () => { - const result = await generateStandingPretrialOrderInteractor({ + it('get the case detail and trial session detail', async () => { + await generateStandingPretrialOrderInteractor({ applicationContext, docketNumber: '123-45', trialSessionId: '959c4338-0fac-42eb-b0eb-d53b8d0195cc', @@ -64,36 +52,16 @@ describe('generateStandingPretrialOrderInteractor', () => { expect( applicationContext.getPersistenceGateway().getCaseByDocketNumber, ).toHaveBeenCalled(); - expect( - applicationContext.getTemplateGenerators() - .generateStandingPretrialOrderTemplate, - ).toHaveBeenCalled(); - expect( - applicationContext.getUseCases().generatePdfFromHtmlInteractor, - ).toHaveBeenCalled(); - expect(result.indexOf('123-45')).toBeGreaterThan(-1); }); - it('should append the docket number suffix if present on the caseDetail', async () => { - const result = await generateStandingPretrialOrderInteractor({ + it('should call the Standing Pretrial Order document generator', async () => { + await generateStandingPretrialOrderInteractor({ applicationContext, docketNumber: '234-56', trialSessionId: '959c4338-0fac-42eb-b0eb-d53b8d0195cc', }); - - expect( - applicationContext.getPersistenceGateway().getTrialSessionById, - ).toHaveBeenCalled(); - expect( - applicationContext.getPersistenceGateway().getCaseByDocketNumber, - ).toHaveBeenCalled(); - expect( - applicationContext.getTemplateGenerators() - .generateStandingPretrialOrderTemplate, - ).toHaveBeenCalled(); expect( - applicationContext.getUseCases().generatePdfFromHtmlInteractor, + applicationContext.getDocumentGenerators().standingPretrialOrder, ).toHaveBeenCalled(); - expect(result.indexOf('234-56S')).toBeGreaterThan(-1); }); }); diff --git a/shared/src/business/useCases/trialSessions/generateTrialCalendarPdfInteractor.js b/shared/src/business/useCases/trialSessions/generateTrialCalendarPdfInteractor.js index bb17674180f..d6d6e6798de 100644 --- a/shared/src/business/useCases/trialSessions/generateTrialCalendarPdfInteractor.js +++ b/shared/src/business/useCases/trialSessions/generateTrialCalendarPdfInteractor.js @@ -1,10 +1,14 @@ +const { + saveFileAndGenerateUrl, +} = require('../../useCaseHelper/saveFileAndGenerateUrl'); + /** * generateTrialCalendarPdfInteractor * * @param {object} providers the providers object * @param {object} providers.applicationContext the application context * @param {string} providers.trialSessionId the id for the trial session - * @returns {Uint8Array} docket record pdf + * @returns {string} trial session calendar pdf url */ exports.generateTrialCalendarPdfInteractor = async ({ applicationContext, @@ -48,8 +52,12 @@ exports.generateTrialCalendarPdfInteractor = async ({ }, }); - return await applicationContext.getUseCases().generatePdfFromHtmlInteractor({ - applicationContext, - contentHtml, - }); + const file = await applicationContext + .getUseCases() + .generatePdfFromHtmlInteractor({ + applicationContext, + contentHtml, + }); + + return await saveFileAndGenerateUrl({ applicationContext, file }); }; diff --git a/shared/src/business/useCases/trialSessions/generateTrialCalendarPdfInteractor.test.js b/shared/src/business/useCases/trialSessions/generateTrialCalendarPdfInteractor.test.js index 7011999142f..665cc607c24 100644 --- a/shared/src/business/useCases/trialSessions/generateTrialCalendarPdfInteractor.test.js +++ b/shared/src/business/useCases/trialSessions/generateTrialCalendarPdfInteractor.test.js @@ -7,6 +7,8 @@ const { const { MOCK_CASE } = require('../../../test/mockCase'); describe('generateTrialCalendarPdfInteractor', () => { + const mockPdfUrl = { url: 'www.example.com' }; + beforeAll(() => { applicationContext .getPersistenceGateway() @@ -19,6 +21,10 @@ describe('generateTrialCalendarPdfInteractor', () => { applicationContext .getTemplateGenerators() .generateTrialCalendarTemplate.mockReturnValue(true); + + applicationContext + .getPersistenceGateway() + .getDownloadPolicyUrl.mockReturnValue(mockPdfUrl); }); it('should find the cases for a trial session successfully', async () => { @@ -52,4 +58,15 @@ describe('generateTrialCalendarPdfInteractor', () => { .length, ).toBe(1); }); + + it('should return the trial session calendar pdf url', async () => { + const result = await generateTrialCalendarPdfInteractor({ + applicationContext, + content: { + trialSessionId: '6805d1ab-18d0-43ec-bafb-654e83405416', + }, + }); + + expect(result.url).toBe(mockPdfUrl.url); + }); }); diff --git a/shared/src/business/useCases/trialSessions/getTrialSessionDetailsInteractor.test.js b/shared/src/business/useCases/trialSessions/getTrialSessionDetailsInteractor.test.js index 8b35cdce97b..e30c337c75d 100644 --- a/shared/src/business/useCases/trialSessions/getTrialSessionDetailsInteractor.test.js +++ b/shared/src/business/useCases/trialSessions/getTrialSessionDetailsInteractor.test.js @@ -52,9 +52,7 @@ describe('Get trial session details', () => { applicationContext, trialSessionId: MOCK_TRIAL_SESSION.trialSessionId, }), - ).rejects.toThrow( - 'The TrialSession entity was invalid ValidationError: "maxCases" is required', - ); + ).rejects.toThrow('The TrialSession entity was invalid'); }); it('throws a not found error if persistence does not return any results', async () => { diff --git a/shared/src/business/useCases/trialSessions/getTrialSessionWorkingCopyInteractor.test.js b/shared/src/business/useCases/trialSessions/getTrialSessionWorkingCopyInteractor.test.js index ad4251d5c66..bc89b6e8677 100644 --- a/shared/src/business/useCases/trialSessions/getTrialSessionWorkingCopyInteractor.test.js +++ b/shared/src/business/useCases/trialSessions/getTrialSessionWorkingCopyInteractor.test.js @@ -64,9 +64,7 @@ describe('Get trial session working copy', () => { applicationContext, trialSessionId: MOCK_WORKING_COPY.trialSessionId, }), - ).rejects.toThrow( - 'The TrialSessionWorkingCopy entity was invalid ValidationError: "userId" is required', - ); + ).rejects.toThrow('The TrialSessionWorkingCopy entity was invalid'); }); it('correctly returns data from persistence for a judge user (default user for test)', async () => { diff --git a/shared/src/business/useCases/trialSessions/getTrialSessionsInteractor.test.js b/shared/src/business/useCases/trialSessions/getTrialSessionsInteractor.test.js index aec17612050..f992e8400fa 100644 --- a/shared/src/business/useCases/trialSessions/getTrialSessionsInteractor.test.js +++ b/shared/src/business/useCases/trialSessions/getTrialSessionsInteractor.test.js @@ -48,8 +48,6 @@ describe('Get trial sessions', () => { error = err; } - expect(error.message).toContain( - 'The TrialSession entity was invalid ValidationError: "maxCases" is required', - ); + expect(error.message).toContain('The TrialSession entity was invalid'); }); }); diff --git a/shared/src/business/useCases/trialSessions/runTrialSessionPlanningReportInteractor.js b/shared/src/business/useCases/trialSessions/runTrialSessionPlanningReportInteractor.js index 1d0015ce0bd..512bcb5838b 100644 --- a/shared/src/business/useCases/trialSessions/runTrialSessionPlanningReportInteractor.js +++ b/shared/src/business/useCases/trialSessions/runTrialSessionPlanningReportInteractor.js @@ -174,7 +174,24 @@ exports.runTrialSessionPlanningReportInteractor = async ({ headerHtml: ' ', }); - return pdf; + const trialSessionPlanningReportPdfId = applicationContext.getUniqueId(); + + await applicationContext.getPersistenceGateway().saveDocumentFromLambda({ + applicationContext, + document: pdf, + documentId: trialSessionPlanningReportPdfId, + useTempBucket: true, + }); + + const trialSessionPlanningReportPdfUrl = await applicationContext + .getPersistenceGateway() + .getDownloadPolicyUrl({ + applicationContext, + documentId: trialSessionPlanningReportPdfId, + useTempBucket: true, + }); + + return trialSessionPlanningReportPdfUrl; }; exports.getPreviousTerm = getPreviousTerm; diff --git a/shared/src/business/useCases/trialSessions/runTrialSessionPlanningReportInteractor.test.js b/shared/src/business/useCases/trialSessions/runTrialSessionPlanningReportInteractor.test.js index 388f88165f7..b8a2347b65f 100644 --- a/shared/src/business/useCases/trialSessions/runTrialSessionPlanningReportInteractor.test.js +++ b/shared/src/business/useCases/trialSessions/runTrialSessionPlanningReportInteractor.test.js @@ -10,10 +10,14 @@ const { TrialSession } = require('../../entities/trialSessions/TrialSession'); const { User } = require('../../entities/User'); describe('run trial session planning report', () => { + const mockPdfUrl = 'www.example.com'; let user; beforeEach(() => { applicationContext.getCurrentUser.mockImplementation(() => user); + applicationContext + .getPersistenceGateway() + .getDownloadPolicyUrl.mockReturnValue(mockPdfUrl); }); it('throws error if user is unauthorized', async () => { @@ -81,6 +85,7 @@ describe('run trial session planning report', () => { year: '2020', }); + expect(result).toBe(mockPdfUrl); expect( applicationContext.getTemplateGenerators() .generateTrialSessionPlanningReportTemplate, @@ -88,7 +93,13 @@ describe('run trial session planning report', () => { expect( applicationContext.getUseCases().generatePdfFromHtmlInteractor, ).toBeCalled(); - expect(result.indexOf('')).toBe(0); + expect(applicationContext.getUniqueId).toBeCalled(); + expect( + applicationContext.getPersistenceGateway().saveDocumentFromLambda, + ).toBeCalled(); + expect( + applicationContext.getPersistenceGateway().getDownloadPolicyUrl, + ).toBeCalled(); }); describe('getTrialSessionPlanningReportData', () => { diff --git a/shared/src/business/useCases/trialSessions/setNoticesForCalendaredTrialSessionInteractor.test.js b/shared/src/business/useCases/trialSessions/setNoticesForCalendaredTrialSessionInteractor.test.js index 2893997e4fa..624b6b55f6d 100644 --- a/shared/src/business/useCases/trialSessions/setNoticesForCalendaredTrialSessionInteractor.test.js +++ b/shared/src/business/useCases/trialSessions/setNoticesForCalendaredTrialSessionInteractor.test.js @@ -243,8 +243,8 @@ describe('setNoticesForCalendaredTrialSessionInteractor', () => { applicationContext.getPersistenceGateway().saveDocumentFromLambda, ).toHaveBeenCalled(); - expect(findNoticeOfTrial(calendaredCases[0]).status).toEqual('served'); - expect(findNoticeOfTrial(calendaredCases[1]).status).toEqual('served'); + expect(findNoticeOfTrial(calendaredCases[0]).servedAt).toBeDefined(); + expect(findNoticeOfTrial(calendaredCases[1]).servedAt).toBeDefined(); }); it('Should set the servedAt field for the Notice of Trial for each case', async () => { @@ -385,7 +385,7 @@ describe('setNoticesForCalendaredTrialSessionInteractor', () => { ).toHaveBeenCalled(); expect(findNoticeOfTrial(calendaredCases[0])).toBeFalsy(); // Document should not exist on this case - expect(findNoticeOfTrial(calendaredCases[1]).status).toEqual('served'); + expect(findNoticeOfTrial(calendaredCases[1]).servedAt).toBeDefined(); }); it('Should generate a Standing Pretrial Order for REGULAR cases', async () => { @@ -425,12 +425,12 @@ describe('setNoticesForCalendaredTrialSessionInteractor', () => { applicationContext.getPersistenceGateway().saveDocumentFromLambda, ).toHaveBeenCalled(); - expect(findStandingPretrialDocument(calendaredCases[0]).status).toEqual( - 'served', - ); - expect(findStandingPretrialDocument(calendaredCases[1]).status).toEqual( - 'served', - ); + expect( + findStandingPretrialDocument(calendaredCases[0]).servedAt, + ).toBeDefined(); + expect( + findStandingPretrialDocument(calendaredCases[1]).servedAt, + ).toBeDefined(); }); it('Should set the servedAt field for the Standing Pretrial Document for each case', async () => { diff --git a/shared/src/business/useCases/trialSessions/updateTrialSessionInteractor.js b/shared/src/business/useCases/trialSessions/updateTrialSessionInteractor.js index 86e60bdd5bf..c7a5b3b354d 100644 --- a/shared/src/business/useCases/trialSessions/updateTrialSessionInteractor.js +++ b/shared/src/business/useCases/trialSessions/updateTrialSessionInteractor.js @@ -41,8 +41,31 @@ exports.updateTrialSessionInteractor = async ({ throw new Error('Trial session cannot be updated after its start date'); } + const editableFields = { + address1: trialSession.address1, + address2: trialSession.address2, + city: trialSession.city, + courtReporter: trialSession.courtReporter, + courthouseName: trialSession.courthouseName, + irsCalendarAdministrator: trialSession.irsCalendarAdministrator, + judge: trialSession.judge, + maxCases: trialSession.maxCases, + notes: trialSession.notes, + postalCode: trialSession.postalCode, + sessionType: trialSession.sessionType, + startDate: trialSession.startDate, + startTime: trialSession.startTime, + state: trialSession.state, + swingSession: trialSession.swingSession, + swingSessionId: trialSession.swingSessionId, + term: trialSession.term, + termYear: trialSession.termYear, + trialClerk: trialSession.trialClerk, + trialLocation: trialSession.trialLocation, + }; + const newTrialSessionEntity = new TrialSession( - { ...currentTrialSession, ...trialSession }, + { ...currentTrialSession, ...editableFields }, { applicationContext, }, diff --git a/shared/src/business/useCases/trialSessions/updateTrialSessionInteractor.test.js b/shared/src/business/useCases/trialSessions/updateTrialSessionInteractor.test.js index eedbb5d95f0..5a155661b57 100644 --- a/shared/src/business/useCases/trialSessions/updateTrialSessionInteractor.test.js +++ b/shared/src/business/useCases/trialSessions/updateTrialSessionInteractor.test.js @@ -26,6 +26,7 @@ describe('updateTrialSessionInteractor', () => { const MOCK_TRIAL_ID_3 = '76cfdfee-795a-4056-a383-8622e5d527d1'; const MOCK_TRIAL_ID_4 = '195bd58c-e81e-44b5-90e2-b9f0a39575d6'; const MOCK_TRIAL_ID_5 = '5674b900-517d-4ffc-81c0-140302c10010'; + const MOCK_TRIAL_ID_6 = 'd0293e71-155d-4cdd-9f3d-b21a72b64e51'; beforeEach(() => { mockTrialsById = { @@ -53,6 +54,12 @@ describe('updateTrialSessionInteractor', () => { judge: { userId: 'd7d90c05-f6cd-442c-a168-202db587f16f' }, trialSessionId: MOCK_TRIAL_ID_5, }, + [MOCK_TRIAL_ID_6]: { + ...MOCK_TRIAL, + isCalendared: false, + judge: { userId: 'd7d90c05-f6cd-442c-a168-202db587f16f' }, + trialSessionId: MOCK_TRIAL_ID_6, + }, }; applicationContext.environment.stage = 'local'; @@ -255,4 +262,22 @@ describe('updateTrialSessionInteractor', () => { trialDate: '2025-12-02T00:00:00.000Z', }); }); + + it('does not update non-editable fields', async () => { + await updateTrialSessionInteractor({ + applicationContext, + trialSession: { + ...mockTrialsById[MOCK_TRIAL_ID_6], + isCalendared: true, + }, + }); + + expect( + applicationContext.getPersistenceGateway().updateTrialSession, + ).toHaveBeenCalled(); + expect( + applicationContext.getPersistenceGateway().updateTrialSession.mock + .calls[0][0].trialSessionToUpdate.isCalendared, + ).toEqual(false); + }); }); diff --git a/shared/src/business/useCases/trialSessions/updateTrialSessionWorkingCopyInteractor.js b/shared/src/business/useCases/trialSessions/updateTrialSessionWorkingCopyInteractor.js index cfd50ee5803..6dddfb7d0fa 100644 --- a/shared/src/business/useCases/trialSessions/updateTrialSessionWorkingCopyInteractor.js +++ b/shared/src/business/useCases/trialSessions/updateTrialSessionWorkingCopyInteractor.js @@ -24,15 +24,35 @@ exports.updateTrialSessionWorkingCopyInteractor = async ({ throw new UnauthorizedError('Unauthorized'); } - const updatedTrialSessionWorkingCopy = await applicationContext + const oldWorkingCopy = await applicationContext + .getPersistenceGateway() + .getTrialSessionWorkingCopy({ + applicationContext, + trialSessionId: trialSessionWorkingCopyToUpdate.trialSessionId, + userId: trialSessionWorkingCopyToUpdate.userId, + }); + + const editableFields = { + caseMetadata: trialSessionWorkingCopyToUpdate.caseMetadata, + filters: trialSessionWorkingCopyToUpdate.filters, + sessionNotes: trialSessionWorkingCopyToUpdate.sessionNotes, + sort: trialSessionWorkingCopyToUpdate.sort, + sortOrder: trialSessionWorkingCopyToUpdate.sortOrder, + }; + + const updatedTrialSessionWorkingCopy = new TrialSessionWorkingCopy({ + ...oldWorkingCopy, + ...editableFields, + }) + .validate() + .toRawObject(); + + await applicationContext .getPersistenceGateway() .updateTrialSessionWorkingCopy({ applicationContext, - trialSessionWorkingCopyToUpdate, + trialSessionWorkingCopyToUpdate: updatedTrialSessionWorkingCopy, }); - const trialSessionWorkingCopyEntity = new TrialSessionWorkingCopy( - updatedTrialSessionWorkingCopy, - ).validate(); - return trialSessionWorkingCopyEntity.toRawObject(); + return updatedTrialSessionWorkingCopy; }; diff --git a/shared/src/business/useCases/trialSessions/updateTrialSessionWorkingCopyInteractor.test.js b/shared/src/business/useCases/trialSessions/updateTrialSessionWorkingCopyInteractor.test.js index e96c2a5c5aa..6baa46516bb 100644 --- a/shared/src/business/useCases/trialSessions/updateTrialSessionWorkingCopyInteractor.test.js +++ b/shared/src/business/useCases/trialSessions/updateTrialSessionWorkingCopyInteractor.test.js @@ -24,6 +24,9 @@ describe('Update trial session working copy', () => { beforeEach(() => { applicationContext.environment.stage = 'local'; applicationContext.getCurrentUser.mockImplementation(() => user); + applicationContext + .getPersistenceGateway() + .getTrialSessionWorkingCopy.mockReturnValue(MOCK_WORKING_COPY); }); it('throws error if user is unauthorized', async () => { @@ -52,7 +55,7 @@ describe('Update trial session working copy', () => { applicationContext .getPersistenceGateway() - .updateTrialSessionWorkingCopy.mockResolvedValue( + .getTrialSessionWorkingCopy.mockResolvedValue( omit(MOCK_WORKING_COPY, 'userId'), ); @@ -61,9 +64,7 @@ describe('Update trial session working copy', () => { applicationContext, trialSessionWorkingCopyToUpdate: MOCK_WORKING_COPY, }), - ).rejects.toThrow( - 'The TrialSessionWorkingCopy entity was invalid ValidationError: "userId" is required', - ); + ).rejects.toThrow('The TrialSessionWorkingCopy entity was invalid'); }); it('correctly returns data from persistence', async () => { diff --git a/shared/src/business/useCases/trialSessions/validateTrialSessionInteractor.js b/shared/src/business/useCases/trialSessions/validateTrialSessionInteractor.js index 6d755e8b848..1bf6599944a 100644 --- a/shared/src/business/useCases/trialSessions/validateTrialSessionInteractor.js +++ b/shared/src/business/useCases/trialSessions/validateTrialSessionInteractor.js @@ -1,3 +1,7 @@ +const { + NewTrialSession, +} = require('../../entities/trialSessions/NewTrialSession'); + /** * validateTrialSessionInteractor * @@ -10,9 +14,8 @@ exports.validateTrialSessionInteractor = ({ applicationContext, trialSession, }) => { - const errors = new (applicationContext.getEntityConstructors().NewTrialSession)( - trialSession, - { applicationContext }, - ).getFormattedValidationErrors(); + const errors = new NewTrialSession(trialSession, { + applicationContext, + }).getFormattedValidationErrors(); return errors || null; }; diff --git a/shared/src/business/useCases/trialSessions/validateTrialSessionInteractor.test.js b/shared/src/business/useCases/trialSessions/validateTrialSessionInteractor.test.js index 526e2ae3066..6cdf951072f 100644 --- a/shared/src/business/useCases/trialSessions/validateTrialSessionInteractor.test.js +++ b/shared/src/business/useCases/trialSessions/validateTrialSessionInteractor.test.js @@ -1,3 +1,6 @@ +const { + applicationContext, +} = require('../../test/createTestApplicationContext'); const { NewTrialSession, } = require('../../entities/trialSessions/NewTrialSession'); @@ -11,12 +14,7 @@ const { formatNow } = require('../../utilities/DateHandler'); describe('validateTrialSessionInteractor', () => { it('returns the expected errors object on an empty trial session', () => { const errors = validateTrialSessionInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - NewTrialSession, - }), - getUniqueId: () => 'c54ba5a9-b37b-479d-9201-067ec6e335bb', - }, + applicationContext, trialSession: {}, }); @@ -43,12 +41,7 @@ describe('validateTrialSessionInteractor', () => { }; const errors = validateTrialSessionInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - NewTrialSession, - }), - getUniqueId: () => 'c54ba5a9-b37b-479d-9201-067ec6e335bb', - }, + applicationContext, trialSession: { ...MOCK_TRIAL }, }); diff --git a/shared/src/business/useCases/updateCaseTrialSortTagsInteractor.test.js b/shared/src/business/useCases/updateCaseTrialSortTagsInteractor.test.js index 5c01a00c4e7..868ccc482d1 100644 --- a/shared/src/business/useCases/updateCaseTrialSortTagsInteractor.test.js +++ b/shared/src/business/useCases/updateCaseTrialSortTagsInteractor.test.js @@ -95,8 +95,6 @@ describe('Update case trial sort tags', () => { caseId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', userId: 'petitionsclerk', }), - ).rejects.toThrow( - 'The Case entity was invalid ValidationError: "docketNumber" is required', - ); + ).rejects.toThrow('The Case entity was invalid'); }); }); diff --git a/shared/src/business/useCases/updatePetitionDetailsInteractor.test.js b/shared/src/business/useCases/updatePetitionDetailsInteractor.test.js index 63beb4e16ef..3f8f2d2b1e8 100644 --- a/shared/src/business/useCases/updatePetitionDetailsInteractor.test.js +++ b/shared/src/business/useCases/updatePetitionDetailsInteractor.test.js @@ -118,6 +118,7 @@ describe('updatePetitionDetailsInteractor', () => { docketRecordId: 'unique-id-1', documentId: undefined, editState: undefined, + entityName: 'DocketRecord', eventCode: 'FEEW', filedBy: undefined, filingDate: '2019-11-30T09:10:11.000Z', @@ -148,6 +149,7 @@ describe('updatePetitionDetailsInteractor', () => { docketRecordId: 'unique-id-1', documentId: undefined, editState: undefined, + entityName: 'DocketRecord', eventCode: 'FEE', filedBy: undefined, filingDate: '2019-11-30T09:10:11.000Z', diff --git a/shared/src/business/useCases/updatePetitionerInformationInteractor.js b/shared/src/business/useCases/updatePetitionerInformationInteractor.js index 4d84dd93918..d5b4a5c4e05 100644 --- a/shared/src/business/useCases/updatePetitionerInformationInteractor.js +++ b/shared/src/business/useCases/updatePetitionerInformationInteractor.js @@ -12,6 +12,7 @@ const { const { addCoverToPdf } = require('./addCoversheetInteractor'); const { Case } = require('../entities/cases/Case'); const { Document } = require('../entities/Document'); +const { getCaseCaptionMeta } = require('../utilities/getCaseCaptionMeta'); const { PDFDocument } = require('pdf-lib'); const { UnauthorizedError } = require('../../errors/errors'); @@ -57,7 +58,7 @@ exports.updatePetitionerInformationInteractor = async ({ oldCase.contactSecondary.name ? applicationContext.getUtilities().getDocumentTypeForAddressChange({ newData: contactSecondary, - oldData: oldCase.contactSecondary || {}, + oldData: oldCase.contactSecondary, }) : undefined; @@ -83,12 +84,15 @@ exports.updatePetitionerInformationInteractor = async ({ newData, oldData, }) => { + const { caseCaptionExtension, caseTitle } = getCaseCaptionMeta(caseDetail); + const pdfContentHtml = await applicationContext .getTemplateGenerators() .generateChangeOfAddressTemplate({ applicationContext, content: { - caption: caseDetail.caseCaption, + caseCaptionExtension, + caseTitle, docketNumberWithSuffix: `${caseDetail.docketNumber}${ caseDetail.docketNumberSuffix || '' }`, @@ -224,7 +228,7 @@ exports.updatePetitionerInformationInteractor = async ({ }); return { - paperServiceParties: servedParties && servedParties.paper, + paperServiceParties: servedParties.paper, paperServicePdfUrl, updatedCase, }; diff --git a/shared/src/business/useCases/updatePetitionerInformationInteractor.test.js b/shared/src/business/useCases/updatePetitionerInformationInteractor.test.js index c86e9562388..c2de3a412af 100644 --- a/shared/src/business/useCases/updatePetitionerInformationInteractor.test.js +++ b/shared/src/business/useCases/updatePetitionerInformationInteractor.test.js @@ -69,7 +69,7 @@ const userData = { let userObj = userData; const applicationContext = { environment: { stage: 'local' }, - getCaseCaptionNames: Case.getCaseCaptionNames, + getCaseTitle: Case.getCaseTitle, getChromiumBrowser: () => ({ close: () => null, newPage: () => ({ @@ -137,17 +137,19 @@ describe('update petitioner contact information on a case', () => { expect(updateCaseStub).toHaveBeenCalled(); }); - it('updates case but does not generate a notice if contactSecondary does not contain a name', async () => { - await updatePetitionerInformationInteractor({ - applicationContext, - caseId: 'a805d1ab-18d0-43ec-bafb-654e83405416', - contactPrimary: MOCK_CASE.contactPrimary, - contactSecondary: { countryType: 'domestic' }, - partyType: ContactFactory.PARTY_TYPES.petitionerSpouse, - }); + it('throws an error if contactSecondary is required for the party type and is not valid', async () => { + await expect( + updatePetitionerInformationInteractor({ + applicationContext, + caseId: 'a805d1ab-18d0-43ec-bafb-654e83405416', + contactPrimary: MOCK_CASE.contactPrimary, + contactSecondary: { countryType: 'domestic' }, + partyType: ContactFactory.PARTY_TYPES.petitionerSpouse, + }), + ).rejects.toThrow(); expect(generateChangeOfAddressTemplateStub).not.toHaveBeenCalled(); expect(generatePdfFromHtmlInteractorStub).not.toHaveBeenCalled(); - expect(updateCaseStub).toHaveBeenCalled(); + expect(updateCaseStub).not.toHaveBeenCalled(); }); it('updates petitioner contact when primary contact info changes and serves the notice created', async () => { @@ -160,6 +162,7 @@ describe('update petitioner contact information on a case', () => { countryType: 'domestic', email: 'test@example.com', name: 'Test Petitioner', + phone: '1234567', postalCode: '12345', state: 'TN', title: 'Executor', @@ -182,6 +185,7 @@ describe('update petitioner contact information on a case', () => { city: 'Somewhere', countryType: 'domestic', name: 'Test Petitioner', + phone: '1234567', postalCode: '12345', state: 'TN', title: 'Executor', @@ -202,6 +206,7 @@ describe('update petitioner contact information on a case', () => { city: 'Somewhere', countryType: 'domestic', name: 'Test Petitioner', + phone: '1234567', postalCode: '12345', state: 'TN', title: 'Executor', @@ -218,6 +223,7 @@ describe('update petitioner contact information on a case', () => { city: 'Somewhere', countryType: 'domestic', name: 'Test Petitioner', + phone: '1234567', postalCode: '12345', state: 'TN', title: 'Executor', diff --git a/shared/src/business/useCases/updatePrimaryContactInteractor.js b/shared/src/business/useCases/updatePrimaryContactInteractor.js index 92331a82a0b..207f434448c 100644 --- a/shared/src/business/useCases/updatePrimaryContactInteractor.js +++ b/shared/src/business/useCases/updatePrimaryContactInteractor.js @@ -6,6 +6,7 @@ const { capitalize } = require('lodash'); const { Case } = require('../entities/cases/Case'); const { DOCKET_SECTION } = require('../entities/WorkQueue'); const { Document } = require('../entities/Document'); +const { getCaseCaptionMeta } = require('../utilities/getCaseCaptionMeta'); const { Message } = require('../entities/Message'); const { NotFoundError, UnauthorizedError } = require('../../errors/errors'); const { WorkItem } = require('../entities/WorkItem'); @@ -26,6 +27,18 @@ exports.updatePrimaryContactInteractor = async ({ }) => { const user = applicationContext.getCurrentUser(); + const editableFields = { + address1: contactInfo.address1, + address2: contactInfo.address2, + address3: contactInfo.address3, + city: contactInfo.city, + country: contactInfo.country, + countryType: contactInfo.countryType, + phone: contactInfo.phone, + postalCode: contactInfo.postalCode, + state: contactInfo.state, + }; + const caseToUpdate = await applicationContext .getPersistenceGateway() .getCaseByCaseId({ @@ -38,7 +51,10 @@ exports.updatePrimaryContactInteractor = async ({ } const caseEntity = new Case( - { ...caseToUpdate, contactPrimary: contactInfo }, + { + ...caseToUpdate, + contactPrimary: { ...caseToUpdate.contactPrimary, ...editableFields }, + }, { applicationContext }, ); @@ -53,17 +69,21 @@ exports.updatePrimaryContactInteractor = async ({ const documentType = applicationContext .getUtilities() .getDocumentTypeForAddressChange({ - newData: contactInfo, + newData: editableFields, oldData: caseToUpdate.contactPrimary, }); if (documentType) { - const pdfContentHtml = await applicationContext - .getTemplateGenerators() - .generateChangeOfAddressTemplate({ + const { caseCaptionExtension, caseTitle } = getCaseCaptionMeta(caseEntity); + + const changeOfAddressPdf = await applicationContext + .getDocumentGenerators() + .changeOfAddress({ applicationContext, content: { - caption: caseEntity.caseCaption, + caseCaptionExtension, + caseTitle, + docketNumber: caseEntity.docketNumber, docketNumberWithSuffix: `${caseEntity.docketNumber}${ caseEntity.docketNumberSuffix || '' }`, @@ -74,22 +94,12 @@ exports.updatePrimaryContactInteractor = async ({ }, }); - const docketRecordPdf = await applicationContext - .getUseCases() - .generatePdfFromHtmlInteractor({ - applicationContext, - contentHtml: pdfContentHtml, - displayHeaderFooter: false, - docketNumber: caseEntity.docketNumber, - headerHtml: null, - }); - const newDocumentId = applicationContext.getUniqueId(); const changeOfAddressDocument = new Document( { addToCoversheet: true, - additionalInfo: `for ${contactInfo.name}`, + additionalInfo: `for ${caseToUpdate.contactPrimary.name}`, caseId, documentId: newDocumentId, documentTitle: documentType.title, @@ -121,12 +131,10 @@ exports.updatePrimaryContactInteractor = async ({ assigneeId: null, assigneeName: null, associatedJudge: caseEntity.associatedJudge, - caseCaptionNames: Case.getCaseCaptionNames( - Case.getCaseCaption(caseEntity), - ), caseId, caseIsInProgress: caseEntity.inProgress, caseStatus: caseEntity.status, + caseTitle: Case.getCaseTitle(Case.getCaseCaption(caseEntity)), docketNumber: caseEntity.docketNumber, docketNumberSuffix: caseEntity.docketNumberSuffix, document: { @@ -156,16 +164,16 @@ exports.updatePrimaryContactInteractor = async ({ caseEntity.addDocument(changeOfAddressDocument, { applicationContext }); - const docketRecordPdfWithCover = await addCoverToPdf({ + const changeOfAddressPdfWithCover = await addCoverToPdf({ applicationContext, caseEntity, documentEntity: changeOfAddressDocument, - pdfData: docketRecordPdf, + pdfData: changeOfAddressPdf, }); await applicationContext.getPersistenceGateway().saveDocumentFromLambda({ applicationContext, - document: docketRecordPdfWithCover, + document: changeOfAddressPdfWithCover, documentId: newDocumentId, }); diff --git a/shared/src/business/useCases/updatePrimaryContactInteractor.test.js b/shared/src/business/useCases/updatePrimaryContactInteractor.test.js index a5b58acfb1c..ab62d19b28e 100644 --- a/shared/src/business/useCases/updatePrimaryContactInteractor.test.js +++ b/shared/src/business/useCases/updatePrimaryContactInteractor.test.js @@ -51,7 +51,7 @@ describe('update primary contact on a case', () => { }); }); - it('updates contactPrimary', async () => { + it('should update contactPrimary editable fields', async () => { const caseDetail = await updatePrimaryContactInteractor({ applicationContext, caseId: 'a805d1ab-18d0-43ec-bafb-654e83405416', @@ -63,27 +63,29 @@ describe('update primary contact on a case', () => { name: 'Bill Burr', phone: '1234567890', postalCode: '99999', - serviceIndicator: 'Electronic', state: 'PA', }, }); expect( - applicationContext.getPersistenceGateway().updateCase, - ).toHaveBeenCalled(); + applicationContext.getPersistenceGateway().updateCase.mock.calls[0][0] + .caseToUpdate.contactPrimary, + ).toMatchObject({ + address1: '453 Electric Ave', + city: 'Philadelphia', + countryType: 'domestic', + email: MOCK_CASE.contactPrimary.email, + name: MOCK_CASE.contactPrimary.name, + phone: '1234567890', + postalCode: '99999', + state: 'PA', + }); expect( - applicationContext.getTemplateGenerators() - .generateChangeOfAddressTemplate, + applicationContext.getDocumentGenerators().changeOfAddress, ).toHaveBeenCalled(); expect( applicationContext.getUseCaseHelpers().sendServedPartiesEmails, ).toHaveBeenCalled(); - expect( - applicationContext.getUseCases().generatePdfFromHtmlInteractor, - ).toHaveBeenCalled(); expect(caseDetail.documents[4].servedAt).toBeDefined(); - expect(caseDetail.documents[4].servedParties).toEqual([ - { email: 'petitioner', name: 'Bill Burr' }, - ]); }); it('throws an error if the case was not found', async () => { @@ -154,4 +156,34 @@ describe('update primary contact on a case', () => { applicationContext.getUseCases().generatePdfFromHtmlInteractor, ).not.toHaveBeenCalled(); }); + + it('does not update the contact primary email or name', async () => { + const getUtilities = applicationContext.getUtilities(); + applicationContext.getUtilities = () => ({ + ...getUtilities, + getDocumentTypeForAddressChange: () => undefined, // returns undefined when there is no diff + }); + + const caseDetail = await updatePrimaryContactInteractor({ + applicationContext, + caseId: 'a805d1ab-18d0-43ec-bafb-654e83405416', + contactInfo: { + address1: 'nothing', + city: 'Somewhere', + countryType: 'domestic', + email: 'hello123@example.com', + name: 'Secondary Party Name Changed', + phone: '9876543210', + postalCode: '12345', + state: 'TN', + }, + }); + + expect(caseDetail.contactPrimary.name).not.toBe( + 'Secondary Party Name Changed', + ); + expect(caseDetail.contactPrimary.name).toBe('Test Petitioner'); + expect(caseDetail.contactPrimary.email).not.toBe('hello123@example.com'); + expect(caseDetail.contactPrimary.email).toBe('petitioner@example.com'); + }); }); diff --git a/shared/src/business/useCases/updateSecondaryContactInteractor.js b/shared/src/business/useCases/updateSecondaryContactInteractor.js index dd176ef77cd..2bbbad10763 100644 --- a/shared/src/business/useCases/updateSecondaryContactInteractor.js +++ b/shared/src/business/useCases/updateSecondaryContactInteractor.js @@ -6,6 +6,7 @@ const { capitalize } = require('lodash'); const { Case } = require('../entities/cases/Case'); const { DOCKET_SECTION } = require('../entities/WorkQueue'); const { Document } = require('../entities/Document'); +const { getCaseCaptionMeta } = require('../utilities/getCaseCaptionMeta'); const { Message } = require('../entities/Message'); const { NotFoundError, UnauthorizedError } = require('../../errors/errors'); const { WorkItem } = require('../entities/WorkItem'); @@ -26,6 +27,18 @@ exports.updateSecondaryContactInteractor = async ({ }) => { const user = applicationContext.getCurrentUser(); + const editableFields = { + address1: contactInfo.address1, + address2: contactInfo.address2, + address3: contactInfo.address3, + city: contactInfo.city, + country: contactInfo.country, + countryType: contactInfo.countryType, + phone: contactInfo.phone, + postalCode: contactInfo.postalCode, + state: contactInfo.state, + }; + const caseToUpdate = await applicationContext .getPersistenceGateway() .getCaseByCaseId({ @@ -38,7 +51,10 @@ exports.updateSecondaryContactInteractor = async ({ } const caseEntity = new Case( - { ...caseToUpdate, contactSecondary: contactInfo }, + { + ...caseToUpdate, + contactSecondary: { ...caseToUpdate.contactSecondary, ...editableFields }, + }, { applicationContext }, ); @@ -53,23 +69,26 @@ exports.updateSecondaryContactInteractor = async ({ const documentType = applicationContext .getUtilities() .getDocumentTypeForAddressChange({ - newData: contactInfo, + newData: editableFields, oldData: caseToUpdate.contactSecondary, }); if (documentType) { + const { caseCaptionExtension, caseTitle } = getCaseCaptionMeta(caseEntity); + const pdfContentHtml = await applicationContext .getTemplateGenerators() .generateChangeOfAddressTemplate({ applicationContext, content: { - caption: caseEntity.caseCaption, + caseCaptionExtension, + caseTitle, docketNumberWithSuffix: `${caseEntity.docketNumber}${ caseEntity.docketNumberSuffix || '' }`, documentTitle: documentType.title, - name: contactInfo.name, - newData: contactInfo, + name: caseToUpdate.contactSecondary.name, + newData: editableFields, oldData: caseToUpdate.contactSecondary, }, }); @@ -89,7 +108,7 @@ exports.updateSecondaryContactInteractor = async ({ const changeOfAddressDocument = new Document( { addToCoversheet: true, - additionalInfo: `for ${contactInfo.name}`, + additionalInfo: `for ${caseToUpdate.contactSecondary.name}`, caseId, documentId: newDocumentId, documentTitle: documentType.title, @@ -121,12 +140,10 @@ exports.updateSecondaryContactInteractor = async ({ assigneeId: null, assigneeName: null, associatedJudge: caseEntity.associatedJudge, - caseCaptionNames: Case.getCaseCaptionNames( - Case.getCaseCaption(caseEntity), - ), caseId, caseIsInProgress: caseEntity.inProgress, caseStatus: caseEntity.status, + caseTitle: Case.getCaseTitle(Case.getCaseCaption(caseEntity)), docketNumber: caseEntity.docketNumber, docketNumberSuffix: caseEntity.docketNumberSuffix, document: { diff --git a/shared/src/business/useCases/updateSecondaryContactInteractor.test.js b/shared/src/business/useCases/updateSecondaryContactInteractor.test.js index 11058ce9e65..51aff7d5ef9 100644 --- a/shared/src/business/useCases/updateSecondaryContactInteractor.test.js +++ b/shared/src/business/useCases/updateSecondaryContactInteractor.test.js @@ -1,137 +1,71 @@ -const { - createISODateString, - formatDateString, -} = require('../../../../shared/src/business/utilities/DateHandler'); const { updateSecondaryContactInteractor, } = require('./updateSecondaryContactInteractor'); -const { Case } = require('../entities/cases/Case'); +const { applicationContext } = require('../test/createTestApplicationContext'); const { MOCK_CASE } = require('../../test/mockCase'); const { User } = require('../entities/User'); -const fakeData = - 'JVBERi0xLjEKJcKlwrHDqwoKMSAwIG9iagogIDw8IC9UeXBlIC9DYXRhbG9nCiAgICAgL1BhZ2VzIDIgMCBSCiAgPj4KZW5kb2JqCgoyIDAgb2JqCiAgPDwgL1R5cGUgL1BhZ2VzCiAgICAgL0tpZHMgWzMgMCBSXQogICAgIC9Db3VudCAxCiAgICAgL01lZGlhQm94IFswIDAgMzAwIDE0NF0KICA+PgplbmRvYmoKCjMgMCBvYmoKICA8PCAgL1R5cGUgL1BhZ2UKICAgICAgL1BhcmVudCAyIDAgUgogICAgICAvUmVzb3VyY2VzCiAgICAgICA8PCAvRm9udAogICAgICAgICAgIDw8IC9GMQogICAgICAgICAgICAgICA8PCAvVHlwZSAvRm9udAogICAgICAgICAgICAgICAgICAvU3VidHlwZSAvVHlwZTEKICAgICAgICAgICAgICAgICAgL0Jhc2VGb250IC9UaW1lcy1Sb21hbgogICAgICAgICAgICAgICA+PgogICAgICAgICAgID4+CiAgICAgICA+PgogICAgICAvQ29udGVudHMgNCAwIFIKICA+PgplbmRvYmoKCjQgMCBvYmoKICA8PCAvTGVuZ3RoIDg0ID4+CnN0cmVhbQogIEJUCiAgICAvRjEgMTggVGYKICAgIDUgODAgVGQKICAgIChDb25ncmF0aW9ucywgeW91IGZvdW5kIHRoZSBFYXN0ZXIgRWdnLikgVGoKICBFVAplbmRzdHJlYW0KZW5kb2JqCgp4cmVmCjAgNQowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAwMTggMDAwMDAgbiAKMDAwMDAwMDA3NyAwMDAwMCBuIAowMDAwMDAwMTc4IDAwMDAwIG4gCjAwMDAwMDA0NTcgMDAwMDAgbiAKdHJhaWxlcgogIDw8ICAvUm9vdCAxIDAgUgogICAgICAvU2l6ZSA1CiAgPj4Kc3RhcnR4cmVmCjU2NQolJUVPRgo='; - -const fakeFile = Buffer.from(fakeData, 'base64'); -fakeFile.name = 'fakeFile.pdf'; +describe('updateSecondaryContactInteractor', () => { + const mockContactSecondary = { + address1: 'nothing', + city: 'Somewhere', + countryType: 'domestic', + email: 'secondary@example.com', + name: 'Secondary Party', + phone: '9876543210', + postalCode: '12345', + state: 'TN', + }; + let mockCase = { + ...MOCK_CASE, + contactSecondary: mockContactSecondary, + partyType: 'Petitioner & spouse', + }; + const fakeData = + 'JVBERi0xLjEKJcKlwrHDqwoKMSAwIG9iagogIDw8IC9UeXBlIC9DYXRhbG9nCiAgICAgL1BhZ2VzIDIgMCBSCiAgPj4KZW5kb2JqCgoyIDAgb2JqCiAgPDwgL1R5cGUgL1BhZ2VzCiAgICAgL0tpZHMgWzMgMCBSXQogICAgIC9Db3VudCAxCiAgICAgL01lZGlhQm94IFswIDAgMzAwIDE0NF0KICA+PgplbmRvYmoKCjMgMCBvYmoKICA8PCAgL1R5cGUgL1BhZ2UKICAgICAgL1BhcmVudCAyIDAgUgogICAgICAvUmVzb3VyY2VzCiAgICAgICA8PCAvRm9udAogICAgICAgICAgIDw8IC9GMQogICAgICAgICAgICAgICA8PCAvVHlwZSAvRm9udAogICAgICAgICAgICAgICAgICAvU3VidHlwZSAvVHlwZTEKICAgICAgICAgICAgICAgICAgL0Jhc2VGb250IC9UaW1lcy1Sb21hbgogICAgICAgICAgICAgICA+PgogICAgICAgICAgID4+CiAgICAgICA+PgogICAgICAvQ29udGVudHMgNCAwIFIKICA+PgplbmRvYmoKCjQgMCBvYmoKICA8PCAvTGVuZ3RoIDg0ID4+CnN0cmVhbQogIEJUCiAgICAvRjEgMTggVGYKICAgIDUgODAgVGQKICAgIChDb25ncmF0aW9ucywgeW91IGZvdW5kIHRoZSBFYXN0ZXIgRWdnLikgVGoKICBFVAplbmRzdHJlYW0KZW5kb2JqCgp4cmVmCjAgNQowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAwMTggMDAwMDAgbiAKMDAwMDAwMDA3NyAwMDAwMCBuIAowMDAwMDAwMTc4IDAwMDAwIG4gCjAwMDAwMDA0NTcgMDAwMDAgbiAKdHJhaWxlcgogIDw8ICAvUm9vdCAxIDAgUgogICAgICAvU2l6ZSA1CiAgPj4Kc3RhcnR4cmVmCjU2NQolJUVPRgo='; -let updateCaseStub; -let generateChangeOfAddressTemplateStub; -let generatePdfFromHtmlInteractorStub; -let getAddressPhoneDiffStub; -let getDocumentTypeForAddressChangeStub; -let saveDocumentFromLambdaStub; -let sendServedPartiesEmailsStub; + const fakeFile = Buffer.from(fakeData, 'base64'); + fakeFile.name = 'fakeFile.pdf'; -let persistenceGateway; -let useCases; -let applicationContext; + let mockUser = new User({ + name: 'bob', + role: User.ROLES.petitioner, + userId: '6805d1ab-18d0-43ec-bafb-654e83405416', + }); -describe('update secondary contact on a case', () => { beforeEach(() => { - updateCaseStub = jest.fn(); - generateChangeOfAddressTemplateStub = jest.fn(); - generatePdfFromHtmlInteractorStub = jest.fn(); - getAddressPhoneDiffStub = jest.fn(); - getDocumentTypeForAddressChangeStub = jest.fn(); - saveDocumentFromLambdaStub = jest.fn(); - sendServedPartiesEmailsStub = jest.fn(); - - persistenceGateway = { - getCaseByCaseId: () => ({ - ...MOCK_CASE, - contactSecondary: { - address1: 'nothing', - city: 'Somewhere', - countryType: 'domestic', - email: 'secondary@example.com', - name: 'Secondary Party', - phone: '9876543210', - postalCode: '12345', - state: 'TN', - }, - partyType: 'Petitioner & spouse', - }), - saveDocumentFromLambda: saveDocumentFromLambdaStub, - saveWorkItemForNonPaper: () => null, - updateCase: updateCaseStub, - }; + applicationContext + .getPersistenceGateway() + .getCaseByCaseId.mockImplementation(() => mockCase); - useCases = { - generatePdfFromHtmlInteractor: () => { - generatePdfFromHtmlInteractorStub(); - return fakeFile; - }, - userIsAssociated: () => true, - }; + applicationContext + .getChromiumBrowser() + .newPage() + .pdf.mockReturnValue(fakeData); - applicationContext = { - environment: { stage: 'local' }, - getCaseCaptionNames: Case.getCaseCaptionNames, - getChromiumBrowser: () => ({ - close: () => null, - newPage: () => ({ - pdf: () => fakeData, - setContent: () => null, - }), - }), - getCurrentUser: () => { - return new User({ - name: 'bob', - role: User.ROLES.petitioner, - userId: '6805d1ab-18d0-43ec-bafb-654e83405416', - }); - }, - getDispatchers: () => ({ - sendBulkTemplatedEmail: () => null, - }), - getPersistenceGateway: () => { - return persistenceGateway; - }, - getTemplateGenerators: () => { - return { - generateChangeOfAddressTemplate: async () => { - generateChangeOfAddressTemplateStub(); - return ''; - }, - }; - }, - getUniqueId: () => 'c6b81f4d-1e47-423a-8caf-6d2fdc3d3859', - getUseCaseHelpers: () => ({ - sendServedPartiesEmails: sendServedPartiesEmailsStub, - }), - getUseCases: () => useCases, - getUtilities: () => { - return { - createISODateString, - formatDateString, - getAddressPhoneDiff: () => { - getAddressPhoneDiffStub(); - return { - address1: { - newData: 'new test', - oldData: 'test', - }, - }; - }, - getDocumentTypeForAddressChange: () => { - getDocumentTypeForAddressChangeStub(); - return { - eventCode: 'NCA', - title: 'Notice of Change of Address', - }; - }, - }; - }, - logger: { - error: e => console.log(e), - time: () => null, - timeEnd: () => null, + applicationContext + .getUseCases() + .generatePdfFromHtmlInteractor.mockReturnValue(fakeFile); + applicationContext.getUseCases().userIsAssociated.mockReturnValue(true); + + applicationContext.getCurrentUser.mockReturnValue(mockUser); + + applicationContext.getUtilities().getAddressPhoneDiff.mockReturnValue({ + address1: { + newData: 'new test', + oldData: 'test', }, - }; + }); + + applicationContext + .getUtilities() + .getDocumentTypeForAddressChange.mockReturnValue({ + eventCode: 'NCA', + title: 'Notice of Change of Address', + }); }); - it('updates contactSecondary', async () => { + it('should update contactSecondary editable fields', async () => { const caseDetail = await updateSecondaryContactInteractor({ applicationContext, caseId: 'a805d1ab-18d0-43ec-bafb-654e83405416', @@ -143,63 +77,68 @@ describe('update secondary contact on a case', () => { name: 'New Secondary', phone: '1234567890', postalCode: '99999', - serviceIndicator: 'Electronic', state: 'PA', }, }); - expect(updateCaseStub).toHaveBeenCalled(); - expect(generateChangeOfAddressTemplateStub).toHaveBeenCalled(); - expect(generatePdfFromHtmlInteractorStub).toHaveBeenCalled(); + expect( + applicationContext.getPersistenceGateway().updateCase.mock.calls[0][0] + .caseToUpdate.contactSecondary, + ).toMatchObject({ + address1: '453 Electric Ave', + city: 'Philadelphia', + countryType: 'domestic', + email: mockContactSecondary.email, + name: mockContactSecondary.name, + phone: '1234567890', + postalCode: '99999', + state: 'PA', + }); + expect( + applicationContext.getTemplateGenerators() + .generateChangeOfAddressTemplate, + ).toHaveBeenCalled(); + expect( + applicationContext.getUseCases().generatePdfFromHtmlInteractor, + ).toHaveBeenCalled(); expect(caseDetail.documents[4].servedAt).toBeDefined(); - expect(caseDetail.documents[4].servedParties).toEqual([ - { email: 'petitioner@example.com', name: 'Test Petitioner' }, - { email: 'secondary@example.com', name: 'New Secondary' }, - ]); }); it('throws an error if the case was not found', async () => { - persistenceGateway.getCaseByCaseId = async () => null; - let error = null; - try { - await updateSecondaryContactInteractor({ + mockCase = null; + + await expect( + updateSecondaryContactInteractor({ applicationContext, caseId: 'a805d1ab-18d0-43ec-bafb-654e83405416', contactInfo: {}, - }); - } catch (err) { - error = err; - } - expect(error.message).toEqual( + }), + ).rejects.toThrow( 'Case a805d1ab-18d0-43ec-bafb-654e83405416 was not found.', ); }); it('throws an error if the user making the request is not associated with the case', async () => { - persistenceGateway.getCaseByCaseId = async () => ({ + mockCase = { ...MOCK_CASE, userId: '123', - }); - useCases.userIsAssociated = () => false; - let error = null; - try { - await updateSecondaryContactInteractor({ + }; + applicationContext.getUseCases().userIsAssociated.mockReturnValue(false); + + await expect( + updateSecondaryContactInteractor({ applicationContext, caseId: 'a805d1ab-18d0-43ec-bafb-654e83405416', contactInfo: {}, - }); - } catch (err) { - error = err; - } - expect(error.message).toEqual('Unauthorized for update case contact'); + }), + ).rejects.toThrow('Unauthorized for update case contact'); }); it('does not update the case if the contact information does not change', async () => { - const getUtilities = applicationContext.getUtilities(); - applicationContext.getUtilities = () => ({ - ...getUtilities, - getDocumentTypeForAddressChange: () => undefined, // returns undefined when there is no diff - }); + applicationContext + .getUtilities() + .getDocumentTypeForAddressChange.mockReturnValue(undefined); + await updateSecondaryContactInteractor({ applicationContext, caseId: 'a805d1ab-18d0-43ec-bafb-654e83405416', @@ -216,8 +155,48 @@ describe('update secondary contact on a case', () => { }, }); - expect(updateCaseStub).not.toHaveBeenCalled(); - expect(generateChangeOfAddressTemplateStub).not.toHaveBeenCalled(); - expect(generatePdfFromHtmlInteractorStub).not.toHaveBeenCalled(); + expect( + applicationContext.getPersistenceGateway().updateCase, + ).not.toHaveBeenCalled(); + expect( + applicationContext.getTemplateGenerators() + .generateChangeOfAddressTemplate, + ).not.toHaveBeenCalled(); + expect( + applicationContext.getUseCases().generatePdfFromHtmlInteractor, + ).not.toHaveBeenCalled(); + }); + + it('does not update the contact secondary email or name', async () => { + mockCase = { + ...MOCK_CASE, + contactSecondary: mockContactSecondary, + partyType: 'Petitioner & spouse', + }; + applicationContext + .getUtilities() + .getDocumentTypeForAddressChange.mockReturnValue(undefined); + + const caseDetail = await updateSecondaryContactInteractor({ + applicationContext, + caseId: 'a805d1ab-18d0-43ec-bafb-654e83405416', + contactInfo: { + address1: 'nothing', + city: 'Somewhere', + countryType: 'domestic', + email: 'hello123@example.com', + name: 'Secondary Party Name Changed', + phone: '9876543210', + postalCode: '12345', + state: 'TN', + }, + }); + + expect(caseDetail.contactSecondary.name).not.toBe( + 'Secondary Party Name Changed', + ); + expect(caseDetail.contactSecondary.name).toBe(mockContactSecondary.name); + expect(caseDetail.contactSecondary.email).not.toBe('hello123@example.com'); + expect(caseDetail.contactSecondary.email).toBe(mockContactSecondary.email); }); }); diff --git a/shared/src/business/useCases/users/generateChangeOfAddress.js b/shared/src/business/useCases/users/generateChangeOfAddress.js index db5932a17a3..75a5c1c131d 100644 --- a/shared/src/business/useCases/users/generateChangeOfAddress.js +++ b/shared/src/business/useCases/users/generateChangeOfAddress.js @@ -10,6 +10,7 @@ const { capitalize, clone } = require('lodash'); const { Case } = require('../../entities/cases/Case'); const { DOCKET_SECTION } = require('../../entities/WorkQueue'); const { Document } = require('../../entities/Document'); +const { getCaseCaptionMeta } = require('../../utilities/getCaseCaptionMeta'); const { Message } = require('../../entities/Message'); const { User } = require('../../entities/User'); const { WorkItem } = require('../../entities/WorkItem'); @@ -86,12 +87,17 @@ exports.generateChangeOfAddress = async ({ if (!documentType) return; + const { caseCaptionExtension, caseTitle } = getCaseCaptionMeta( + caseDetail, + ); + const pdfContentHtml = await applicationContext .getTemplateGenerators() .generateChangeOfAddressTemplate({ applicationContext, content: { - caption: caseDetail.caseCaption, + caseCaptionExtension, + caseTitle, docketNumberWithSuffix: `${caseDetail.docketNumber}${ caseDetail.docketNumberSuffix || '' }`, @@ -156,12 +162,10 @@ exports.generateChangeOfAddress = async ({ assigneeId: null, assigneeName: null, associatedJudge: caseEntity.associatedJudge, - caseCaptionNames: Case.getCaseCaptionNames( - Case.getCaseCaption(caseEntity), - ), caseId: caseEntity.caseId, caseIsInProgress: caseEntity.inProgress, caseStatus: caseEntity.status, + caseTitle: Case.getCaseTitle(Case.getCaseCaption(caseEntity)), docketNumber: caseEntity.docketNumber, docketNumberSuffix: caseEntity.docketNumberSuffix, document: { diff --git a/shared/src/business/useCases/users/generateChangeOfAddress.test.js b/shared/src/business/useCases/users/generateChangeOfAddress.test.js index 256d2eb65b6..190363a0c52 100644 --- a/shared/src/business/useCases/users/generateChangeOfAddress.test.js +++ b/shared/src/business/useCases/users/generateChangeOfAddress.test.js @@ -5,7 +5,7 @@ const { generateChangeOfAddress } = require('./generateChangeOfAddress'); const { MOCK_CASE } = require('../../../test/mockCase'); describe('generateChangeOfAddress', () => { - beforeEach(() => { + beforeAll(() => { applicationContext.getCurrentUser.mockReturnValue({ role: 'docketclerk', userId: 'docketclerk', diff --git a/shared/src/business/useCases/users/updateUserContactInformationInteractor.js b/shared/src/business/useCases/users/updateUserContactInformationInteractor.js index 9eca6fa85a9..d969551d07d 100644 --- a/shared/src/business/useCases/users/updateUserContactInformationInteractor.js +++ b/shared/src/business/useCases/users/updateUserContactInformationInteractor.js @@ -5,6 +5,7 @@ const { const { generateChangeOfAddress } = require('./generateChangeOfAddress'); const { isEqual } = require('lodash'); const { UnauthorizedError } = require('../../../errors/errors'); +const { User } = require('../../entities/User'); /** * updateUserContactInformationInteractor @@ -38,12 +39,14 @@ exports.updateUserContactInformationInteractor = async ({ throw new Error('there were no changes found needing to be updated'); } + const userEntity = new User({ + ...user, + contact: { ...contactInfo }, + }); + await applicationContext.getPersistenceGateway().updateUser({ applicationContext, - user: { - ...user, - contact: { ...contactInfo }, - }, + user: userEntity.validate().toRawObject(), }); const updatedCases = await generateChangeOfAddress({ diff --git a/shared/src/business/useCases/users/validateUserContactInteractor.js b/shared/src/business/useCases/users/validateUserContactInteractor.js index d6f97efa80d..2874f10e444 100644 --- a/shared/src/business/useCases/users/validateUserContactInteractor.js +++ b/shared/src/business/useCases/users/validateUserContactInteractor.js @@ -1,3 +1,5 @@ +const { User } = require('../../entities/User'); + /** * validateUserContactInteractor * @@ -7,8 +9,8 @@ * @returns {object} errors (null if no errors) */ exports.validateUserContactInteractor = ({ applicationContext, user }) => { - const errors = new (applicationContext.getEntityConstructors().User)( - user, - ).getFormattedValidationErrors(); + const errors = new User(user, { + applicationContext, + }).getFormattedValidationErrors(); return errors || null; }; diff --git a/shared/src/business/useCases/users/validateUserContactInteractor.test.js b/shared/src/business/useCases/users/validateUserContactInteractor.test.js index 8de063b5638..72b85e9e275 100644 --- a/shared/src/business/useCases/users/validateUserContactInteractor.test.js +++ b/shared/src/business/useCases/users/validateUserContactInteractor.test.js @@ -1,16 +1,14 @@ +const { + applicationContext, +} = require('../../test/createTestApplicationContext'); const { validateUserContactInteractor, } = require('./validateUserContactInteractor'); -const { User } = require('../../entities/User'); describe('validateUserContactInteractor', () => { it('returns the expected errors object on an empty message', () => { const errors = validateUserContactInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - User, - }), - }, + applicationContext, user: {}, }); @@ -19,11 +17,7 @@ describe('validateUserContactInteractor', () => { it('returns no errors when all fields are defined', () => { const errors = validateUserContactInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - User, - }), - }, + applicationContext, user: { userId: '8675309b-18d0-43ec-bafb-654e83405411', }, diff --git a/shared/src/business/useCases/validateDocketRecordInteractor.js b/shared/src/business/useCases/validateDocketRecordInteractor.js index afb9286cf6e..d0a0c23d915 100644 --- a/shared/src/business/useCases/validateDocketRecordInteractor.js +++ b/shared/src/business/useCases/validateDocketRecordInteractor.js @@ -1,3 +1,5 @@ +const { DocketRecord } = require('../entities/DocketRecord'); + /** * validateDocketRecordInteractor * @@ -10,10 +12,9 @@ exports.validateDocketRecordInteractor = ({ applicationContext, docketRecord, }) => { - const errors = new (applicationContext.getEntityConstructors().DocketRecord)( - docketRecord, - { applicationContext }, - ).getFormattedValidationErrors(); + const errors = new DocketRecord(docketRecord, { + applicationContext, + }).getFormattedValidationErrors(); return errors || null; }; diff --git a/shared/src/business/useCases/validateDocketRecordInteractor.test.js b/shared/src/business/useCases/validateDocketRecordInteractor.test.js index 10dd185824e..9a0099fd371 100644 --- a/shared/src/business/useCases/validateDocketRecordInteractor.test.js +++ b/shared/src/business/useCases/validateDocketRecordInteractor.test.js @@ -1,20 +1,13 @@ const { validateDocketRecordInteractor, } = require('./validateDocketRecordInteractor'); +const { applicationContext } = require('../test/createTestApplicationContext'); const { DocketRecord } = require('../entities/DocketRecord'); -const { MOCK_USERS } = require('../../test/mockUsers'); describe('validateDocketRecordInteractor', () => { it('returns the expected errors object on an empty docket record', () => { const errors = validateDocketRecordInteractor({ - applicationContext: { - getCurrentUser: () => - MOCK_USERS['a7d90c05-f6cd-442c-a168-202db587f16f'], - getEntityConstructors: () => ({ - DocketRecord, - }), - getUniqueId: () => 'unique-id-1', - }, + applicationContext, docketRecord: {}, }); @@ -25,18 +18,11 @@ describe('validateDocketRecordInteractor', () => { it('returns null when there are no errors', () => { const result = validateDocketRecordInteractor({ - applicationContext: { - getCurrentUser: () => - MOCK_USERS['a7d90c05-f6cd-442c-a168-202db587f16f'], - getEntityConstructors: () => ({ - DocketRecord, - }), - getUniqueId: () => 'unique-id-1', - }, + applicationContext, docketRecord: { description: 'Test Description', eventCode: 'O', - filingDate: '2020-01-01', + filingDate: '2020-01-01T02:04:06.007Z', index: '1', }, }); diff --git a/shared/src/business/useCases/validateOrderAdvancedSearchInteractor.test.js b/shared/src/business/useCases/validateOrderAdvancedSearchInteractor.test.js index 15f219dd13d..aac22f18320 100644 --- a/shared/src/business/useCases/validateOrderAdvancedSearchInteractor.test.js +++ b/shared/src/business/useCases/validateOrderAdvancedSearchInteractor.test.js @@ -1,16 +1,12 @@ const { validateOrderAdvancedSearchInteractor, } = require('./validateOrderAdvancedSearchInteractor'); -const { OrderSearch } = require('../entities/orders/OrderSearch'); +const { applicationContext } = require('../test/createTestApplicationContext'); describe('validateOrderAdvancedSearchInteractor', () => { it('returns null when no errors exist in the orderSearch', () => { const errors = validateOrderAdvancedSearchInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - OrderSearch, - }), - }, + applicationContext, orderSearch: { orderKeyword: 'Joe Exotic', }, @@ -21,11 +17,7 @@ describe('validateOrderAdvancedSearchInteractor', () => { it('returns an error when a search term is not provided', () => { const errors = validateOrderAdvancedSearchInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - OrderSearch, - }), - }, + applicationContext, orderSearch: { orderKeyword: '', }, diff --git a/shared/src/business/useCases/validatePetitionFromPaperInteractor.js b/shared/src/business/useCases/validatePetitionFromPaperInteractor.js index 9be6919ccb8..c970db529f8 100644 --- a/shared/src/business/useCases/validatePetitionFromPaperInteractor.js +++ b/shared/src/business/useCases/validatePetitionFromPaperInteractor.js @@ -1,5 +1,7 @@ +const { CaseInternal } = require('../entities/cases/CaseInternal'); + /** - * validatePetition + * validatePetitionFromPaper * * @param {object} providers the providers object * @param {object} providers.applicationContext the application context @@ -10,8 +12,8 @@ exports.validatePetitionFromPaperInteractor = ({ applicationContext, petition, }) => { - const errors = new (applicationContext.getEntityConstructors().CaseInternal)( - petition, - ).getFormattedValidationErrors(); + const errors = new CaseInternal(petition, { + applicationContext, + }).getFormattedValidationErrors(); return errors || null; }; diff --git a/shared/src/business/useCases/validatePetitionFromPaperInteractor.test.js b/shared/src/business/useCases/validatePetitionFromPaperInteractor.test.js index 1646830c2c3..de3bef12bf7 100644 --- a/shared/src/business/useCases/validatePetitionFromPaperInteractor.test.js +++ b/shared/src/business/useCases/validatePetitionFromPaperInteractor.test.js @@ -1,17 +1,13 @@ const { validatePetitionFromPaperInteractor, } = require('./validatePetitionFromPaperInteractor'); +const { applicationContext } = require('../test/createTestApplicationContext'); const { Case } = require('../entities/cases/Case'); -const { CaseInternal } = require('../entities/cases/CaseInternal'); describe('validate petition from paper', () => { it('returns the expected errors object on an empty petition', () => { const errors = validatePetitionFromPaperInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - CaseInternal, - }), - }, + applicationContext, petition: {}, }); @@ -24,18 +20,13 @@ describe('validate petition from paper', () => { 'petitionPaymentStatus', 'procedureType', 'receivedAt', - 'stinFile', 'chooseAtLeastOneValue', ]); }); it('returns null if no errors exist', () => { const errors = validatePetitionFromPaperInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - CaseInternal, - }), - }, + applicationContext, petition: { caseCaption: 'testing', caseType: 'testing', @@ -47,8 +38,6 @@ describe('validate petition from paper', () => { petitionPaymentStatus: Case.PAYMENT_STATUS.UNPAID, procedureType: 'testing', receivedAt: new Date().toISOString(), - stinFile: {}, - stinFileSize: 100, }, }); diff --git a/shared/src/business/useCases/validatePetitionInteractor.js b/shared/src/business/useCases/validatePetitionInteractor.js index 10a4a987c16..7aea3f59b27 100644 --- a/shared/src/business/useCases/validatePetitionInteractor.js +++ b/shared/src/business/useCases/validatePetitionInteractor.js @@ -1,3 +1,5 @@ +const { CaseExternal } = require('../entities/cases/CaseExternal'); + /** * validatePetitionInteractor * @@ -7,8 +9,8 @@ * @returns {object} errors (null if no errors) */ exports.validatePetitionInteractor = ({ applicationContext, petition }) => { - const errors = new (applicationContext.getEntityConstructors().CaseExternal)( - petition, - ).getFormattedValidationErrors(); + const errors = new CaseExternal(petition, { + applicationContext, + }).getFormattedValidationErrors(); return errors || null; }; diff --git a/shared/src/business/useCases/validatePetitionInteractor.test.js b/shared/src/business/useCases/validatePetitionInteractor.test.js index 28dccdafdd0..6e21587c28c 100644 --- a/shared/src/business/useCases/validatePetitionInteractor.test.js +++ b/shared/src/business/useCases/validatePetitionInteractor.test.js @@ -1,14 +1,10 @@ -const { CaseExternal } = require('../entities/cases/CaseExternal'); +const { applicationContext } = require('../test/createTestApplicationContext'); const { validatePetitionInteractor } = require('./validatePetitionInteractor'); describe('validatePetitionInteractor', () => { it('returns the expected errors object on an empty petition', () => { const errors = validatePetitionInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - CaseExternal, - }), - }, + applicationContext, petition: {}, }); @@ -25,11 +21,7 @@ describe('validatePetitionInteractor', () => { it('returns the expected errors object when caseType is defined', () => { const errors = validatePetitionInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - CaseExternal, - }), - }, + applicationContext, petition: { caseType: 'defined', hasIrsNotice: true, @@ -49,11 +41,7 @@ describe('validatePetitionInteractor', () => { it('returns the expected errors object', () => { const errors = validatePetitionInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - CaseExternal, - }), - }, + applicationContext, petition: { caseType: 'defined', filingType: 'defined', diff --git a/shared/src/business/useCases/workitems/createWorkItemInteractor.js b/shared/src/business/useCases/workitems/createWorkItemInteractor.js index 58007c181bc..808ec5f2fe7 100644 --- a/shared/src/business/useCases/workitems/createWorkItemInteractor.js +++ b/shared/src/business/useCases/workitems/createWorkItemInteractor.js @@ -71,12 +71,10 @@ exports.createWorkItemInteractor = async ({ const newWorkItem = new WorkItem( { associatedJudge: theCase.associatedJudge, - caseCaptionNames: Case.getCaseCaptionNames( - Case.getCaseCaption(caseEntity), - ), caseId: caseId, caseIsInProgress: theCase.inProgress, caseStatus: theCase.status, + caseTitle: Case.getCaseTitle(Case.getCaseCaption(caseEntity)), docketNumber: theCase.docketNumber, docketNumberSuffix: theCase.docketNumberSuffix, document: { diff --git a/shared/src/business/useCases/workitems/forwardWorkItemInteractor.test.js b/shared/src/business/useCases/workitems/forwardWorkItemInteractor.test.js index 2de00e58384..5ed4ebbbd54 100644 --- a/shared/src/business/useCases/workitems/forwardWorkItemInteractor.test.js +++ b/shared/src/business/useCases/workitems/forwardWorkItemInteractor.test.js @@ -151,9 +151,9 @@ describe('forwardWorkItemInteractor', () => { expect(workItem).toMatchObject({ assigneeId: 'a7d90c05-f6cd-442c-a168-202db587f16f', assigneeName: 'Docketclerk', - caseCaptionNames: undefined, caseId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', caseStatus: undefined, + caseTitle: undefined, completedAt: undefined, completedBy: undefined, completedByUserId: undefined, diff --git a/shared/src/business/useCases/workitems/getInboxMessagesForSectionInteractor.js b/shared/src/business/useCases/workitems/getInboxMessagesForSectionInteractor.js index 3dfb0018a18..5ed29e2a51d 100644 --- a/shared/src/business/useCases/workitems/getInboxMessagesForSectionInteractor.js +++ b/shared/src/business/useCases/workitems/getInboxMessagesForSectionInteractor.js @@ -3,6 +3,7 @@ const { ROLE_PERMISSIONS, } = require('../../../authorization/authorizationClientService'); const { UnauthorizedError } = require('../../../errors/errors'); +const { WorkItem } = require('../../entities/WorkItem'); /** * getInboxMessagesForSectionInteractor @@ -22,8 +23,6 @@ exports.getInboxMessagesForSectionInteractor = async ({ throw new UnauthorizedError('Unauthorized'); } - const { WorkItem } = applicationContext.getEntityConstructors(); - const workItems = await applicationContext .getPersistenceGateway() .getInboxMessagesForSection({ diff --git a/shared/src/business/useCases/workitems/getInboxMessagesForSectionInteractor.test.js b/shared/src/business/useCases/workitems/getInboxMessagesForSectionInteractor.test.js index a7bccf0fa59..3df488f5a37 100644 --- a/shared/src/business/useCases/workitems/getInboxMessagesForSectionInteractor.test.js +++ b/shared/src/business/useCases/workitems/getInboxMessagesForSectionInteractor.test.js @@ -12,26 +12,26 @@ describe('getInboxMessagesForSectionInteractor', () => { userId: 'petitionsClerk', }; - let getInboxMessagesForSectionStub; - let validateRawCollectionStub; + let mockWorkItem = { + caseId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', + createdAt: '', + docketNumber: '101-18', + docketNumberSuffix: 'S', + document: { + sentBy: 'petitioner', + }, + isQC: false, + messages: [], + section: 'petitions', + sentBy: 'docketclerk', + }; beforeEach(() => { - getInboxMessagesForSectionStub = jest.fn(); - validateRawCollectionStub = jest.fn(); - applicationContext.getCurrentUser.mockReturnValue(mockPetitionsClerk); - applicationContext.getEntityConstructors = () => ({ - WorkItem: { - validateRawCollection: validateRawCollectionStub, - }, - }); - applicationContext .getPersistenceGateway() - .getInboxMessagesForSection.mockReturnValue( - getInboxMessagesForSectionStub, - ); + .getInboxMessagesForSection.mockReturnValue([mockWorkItem]); }); it('gets inbox messages for a section', async () => { @@ -43,7 +43,6 @@ describe('getInboxMessagesForSectionInteractor', () => { expect( applicationContext.getPersistenceGateway().getInboxMessagesForSection, ).toHaveBeenCalled(); - expect(validateRawCollectionStub).toHaveBeenCalled(); }); it('throws an error if the user does not have access to the work item', async () => { @@ -52,15 +51,11 @@ describe('getInboxMessagesForSectionInteractor', () => { userId: 'petitioner', }); - let error; - try { - await getInboxMessagesForSectionInteractor({ + await expect( + getInboxMessagesForSectionInteractor({ applicationContext, section: 'docket', - }); - } catch (e) { - error = e; - } - expect(error).toBeDefined(); + }), + ).rejects.toThrow('Unauthorized'); }); }); diff --git a/shared/src/business/useCases/workitems/validateForwardMessageInteractor.js b/shared/src/business/useCases/workitems/validateForwardMessageInteractor.js index fe934c948c1..cf0b2538e6e 100644 --- a/shared/src/business/useCases/workitems/validateForwardMessageInteractor.js +++ b/shared/src/business/useCases/workitems/validateForwardMessageInteractor.js @@ -1,3 +1,5 @@ +const { ForwardMessage } = require('../../entities/ForwardMessage'); + /** * validateForwardMessageInteractor * @@ -10,7 +12,7 @@ exports.validateForwardMessageInteractor = ({ applicationContext, message, }) => { - return new (applicationContext.getEntityConstructors().ForwardMessage)( - message, - ).getFormattedValidationErrors(); + return new ForwardMessage(message, { + applicationContext, + }).getFormattedValidationErrors(); }; diff --git a/shared/src/business/useCases/workitems/validateForwardMessageInteractor.test.js b/shared/src/business/useCases/workitems/validateForwardMessageInteractor.test.js index d26508d6989..f8948b06867 100644 --- a/shared/src/business/useCases/workitems/validateForwardMessageInteractor.test.js +++ b/shared/src/business/useCases/workitems/validateForwardMessageInteractor.test.js @@ -1,3 +1,6 @@ +const { + applicationContext, +} = require('../../test/createTestApplicationContext'); const { validateForwardMessageInteractor, } = require('./validateForwardMessageInteractor'); @@ -8,11 +11,7 @@ const { VALIDATION_ERROR_MESSAGES } = ForwardMessage; describe('validateForwardMessageInteractor', () => { it('returns the expected errors object on an empty message', () => { const errors = validateForwardMessageInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - ForwardMessage, - }), - }, + applicationContext, message: {}, }); @@ -25,11 +24,7 @@ describe('validateForwardMessageInteractor', () => { it('returns the expected errors object when only forwardMessage is defined', () => { const errors = validateForwardMessageInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - ForwardMessage, - }), - }, + applicationContext, message: { forwardMessage: 'test message' }, }); @@ -41,11 +36,7 @@ describe('validateForwardMessageInteractor', () => { it('returns the expected errors object when only section is defined', () => { const errors = validateForwardMessageInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - ForwardMessage, - }), - }, + applicationContext, message: { section: 'docket' }, }); @@ -57,11 +48,7 @@ describe('validateForwardMessageInteractor', () => { it('returns the expected errors object when only assigneeId is defined', () => { const errors = validateForwardMessageInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - ForwardMessage, - }), - }, + applicationContext, message: { assigneeId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', section: VALIDATION_ERROR_MESSAGES.section, @@ -75,11 +62,7 @@ describe('validateForwardMessageInteractor', () => { it('returns no errors when all fields are defined', () => { const errors = validateForwardMessageInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - ForwardMessage, - }), - }, + applicationContext, message: { assigneeId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', forwardMessage: 'test message', diff --git a/shared/src/business/useCases/workitems/validateInitialWorkItemMessageInteractor.js b/shared/src/business/useCases/workitems/validateInitialWorkItemMessageInteractor.js index f7cba2c4702..121ae24f0ff 100644 --- a/shared/src/business/useCases/workitems/validateInitialWorkItemMessageInteractor.js +++ b/shared/src/business/useCases/workitems/validateInitialWorkItemMessageInteractor.js @@ -1,3 +1,7 @@ +const { + InitialWorkItemMessage, +} = require('../../entities/InitialWorkItemMessage'); + /** * validateInitialWorkItemMessageInteractor * @@ -10,7 +14,7 @@ exports.validateInitialWorkItemMessageInteractor = ({ applicationContext, message, }) => { - return new (applicationContext.getEntityConstructors().InitialWorkItemMessage)( - message, - ).getFormattedValidationErrors(); + return new InitialWorkItemMessage(message, { + applicationContext, + }).getFormattedValidationErrors(); }; diff --git a/shared/src/business/useCases/workitems/validateInitialWorkItemMessageInteractor.test.js b/shared/src/business/useCases/workitems/validateInitialWorkItemMessageInteractor.test.js index 6f1db9a4137..dd66a25be12 100644 --- a/shared/src/business/useCases/workitems/validateInitialWorkItemMessageInteractor.test.js +++ b/shared/src/business/useCases/workitems/validateInitialWorkItemMessageInteractor.test.js @@ -1,3 +1,6 @@ +const { + applicationContext, +} = require('../../test/createTestApplicationContext'); const { InitialWorkItemMessage, } = require('../../entities/InitialWorkItemMessage'); @@ -10,11 +13,7 @@ const { VALIDATION_ERROR_MESSAGES } = InitialWorkItemMessage; describe('validateInitialWorkItemMessageInteractor', () => { it('returns the expected errors object on an empty message', () => { const errors = validateInitialWorkItemMessageInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - InitialWorkItemMessage, - }), - }, + applicationContext, message: {}, }); @@ -27,11 +26,7 @@ describe('validateInitialWorkItemMessageInteractor', () => { it('returns no errors when all properties are defined', () => { const errors = validateInitialWorkItemMessageInteractor({ - applicationContext: { - getEntityConstructors: () => ({ - InitialWorkItemMessage, - }), - }, + applicationContext, message: { assigneeId: '6805d1ab-18d0-43ec-bafb-654e83405416', message: 'hello world', diff --git a/shared/src/business/utilities/DateHandler.js b/shared/src/business/utilities/DateHandler.js index 963caf52a29..d3d62f8262a 100644 --- a/shared/src/business/utilities/DateHandler.js +++ b/shared/src/business/utilities/DateHandler.js @@ -7,9 +7,11 @@ const FORMATS = { MMDDYY: 'MM/DD/YY', MMDDYYYY: 'MM/DD/YYYY', MONTH_DAY_YEAR: 'MMMM D, YYYY', + SORTABLE_CALENDAR: 'YYYY/MM/DD', TIME: 'hh:mm a', TIME_TZ: 'h:mm a [ET]', YEAR: 'YYYY', + YYYYMMDD: 'YYYY-MM-DD', }; const USTC_TZ = 'America/New_York'; @@ -31,7 +33,7 @@ const prepareDateFromString = (dateString, inputFormat) => { const calculateISODate = ({ dateString, howMuch = 0, units = 'days' }) => { if (!howMuch) return dateString; - return prepareDateFromString(dateString, FORMATS.ISO) + return prepareDateFromString(dateString || createISODateString(), FORMATS.ISO) .add(howMuch, units) .toISOString(); }; @@ -52,6 +54,18 @@ const createISODateString = (dateString, inputFormat) => { return result.toISOString(); }; +const createEndOfDayISO = ({ day, month, year }) => { + const composedDate = `${year}-${month}-${day}T23:59:59.999`; + const composedFormat = 'YYYY-M-DTHH:mm:ss.SSS'; + return prepareDateFromString(composedDate, composedFormat).toISOString(); +}; + +const createStartOfDayISO = ({ day, month, year }) => { + const composedDate = `${year}-${month}-${day}T00:00:00.000`; + const composedFormat = 'YYYY-M-DTHH:mm:ss.SSS'; + return prepareDateFromString(composedDate, composedFormat).toISOString(); +}; + /** * @param {object} options the date options containing year, month, day * @returns {string} a formatted ISO date string @@ -112,6 +126,24 @@ const dateStringsCompared = (a, b) => { return aDate - bDate; }; +/** + * @param {string} a the first date to be compared + * @param {string} b the second date to be compared + * @returns {number} -1 if date a is larger, 1 if date b is larger, 0 if dates are equal + */ +const calendarDatesCompared = (a, b) => { + const aFormatEst = formatDateString(a, FORMATS.SORTABLE_CALENDAR); + const bFormatEst = formatDateString(b, FORMATS.SORTABLE_CALENDAR); + + if (aFormatEst < bFormatEst) { + return -1; + } else if (aFormatEst > bFormatEst) { + return 1; + } else { + return 0; + } +}; + /** * @param {string} dateString date to be deconstructed * @returns {object} deconstructed date object @@ -163,8 +195,11 @@ module.exports = { FORMATS, calculateDifferenceInDays, calculateISODate, + calendarDatesCompared, + createEndOfDayISO, createISODateString, createISODateStringFromObject, + createStartOfDayISO, dateStringsCompared, deconstructDate, formatDateString, diff --git a/shared/src/business/utilities/DateHandler.test.js b/shared/src/business/utilities/DateHandler.test.js index 6f629319c45..a4eb896d408 100644 --- a/shared/src/business/utilities/DateHandler.test.js +++ b/shared/src/business/utilities/DateHandler.test.js @@ -1,4 +1,6 @@ const DateHandler = require('./DateHandler'); +const { getTimestampSchema } = require('../../utilities/dateSchema'); +const joiStrictTimestamp = getTimestampSchema(); describe('DateHandler', () => { describe('prepareDateFromString', () => { @@ -114,6 +116,43 @@ describe('DateHandler', () => { expect(result).toEqual('2000-01-01T00:00:00.000Z'); }); }); + + describe('createStartOfDayISO', () => { + it('creates a timestamp exactly at midnight, the first moment of the day according to Eastern Timezone', () => { + const startOfDay = DateHandler.createStartOfDayISO({ + day: '7', + month: '4', + year: '2020', + }); + expect(startOfDay).toBe('2020-04-07T04:00:00.000Z'); + + // now confirm it converts "back" to originally desired time + const formattedInEastern = DateHandler.formatDateString( + startOfDay, + DateHandler.FORMATS.DATE_TIME, + ); + expect(formattedInEastern).toEqual('04/07/20 12:00 am'); // the stroke of midnight + }); + }); + + describe('createEndOfDayISO', () => { + it('creates a timestamp one millisecond before midnight, the last moment of the day according to Eastern Timezone', () => { + const endOfDay = DateHandler.createEndOfDayISO({ + day: '7', + month: '4', + year: '2020', + }); + expect(endOfDay).toEqual('2020-04-08T03:59:59.999Z'); + + // now confirm it converts "back" to originally desired time + const formattedInEastern = DateHandler.formatDateString( + endOfDay, + DateHandler.FORMATS.DATE_TIME, + ); + expect(formattedInEastern).toEqual('04/07/20 11:59 pm'); // the moment before midnight the next day + }); + }); + describe('createISODateString', () => { it('creates a date anew', () => { const myDate = DateHandler.createISODateString(); @@ -141,6 +180,11 @@ describe('DateHandler', () => { ); // Jan 1, 2001 at the stroke of midnight, GMT expect(myDate).toBe('2001-01-01T00:00:00.000Z'); }); + + it('creates timestamps that strictly adhere to Joi formatting rules', () => { + const thisDate = DateHandler.createISODateString(); + expect(joiStrictTimestamp.validate(thisDate).error).toBeUndefined(); + }); }); describe('deconstructDate', () => { @@ -216,6 +260,29 @@ describe('DateHandler', () => { }); }); + describe('calendarDatesCompared', () => { + const pastDate = '2001-01-01'; + const futureDate = '2061-01-02'; + + it('should return -1 when the first date is occurs before the second', () => { + const result = DateHandler.calendarDatesCompared(pastDate, futureDate); + + expect(result).toEqual(-1); + }); + + it('should return 1 when the first date occurs after the second', () => { + const result = DateHandler.calendarDatesCompared(futureDate, pastDate); + + expect(result).toEqual(1); + }); + + it('should return 0 when the two dates are the same calendar date', () => { + const result = DateHandler.calendarDatesCompared(futureDate, futureDate); + + expect(result).toEqual(0); + }); + }); + describe('isValidDateString', () => { it('should return true on valid date strings', () => { ['01-01-2001', '1-1-2001', '01/01/2001', '1/1/2001'].forEach(date => { diff --git a/shared/src/business/utilities/documentGenerators.js b/shared/src/business/utilities/documentGenerators.js new file mode 100644 index 00000000000..66023ca89f4 --- /dev/null +++ b/shared/src/business/utilities/documentGenerators.js @@ -0,0 +1,128 @@ +const { + reactTemplateGenerator, +} = require('./generateHTMLTemplateForPDF/reactTemplateGenerator'); +const { generateHTMLTemplateForPDF } = require('./generateHTMLTemplateForPDF'); + +const { + generateChangeOfAddressTemplate, +} = require('./generateHTMLTemplateForPDF/generateChangeOfAddressTemplate'); +const { + generatePrintableDocketRecordTemplate, +} = require('./generateHTMLTemplateForPDF/generatePrintableDocketRecordTemplate'); + +const changeOfAddress = async ({ applicationContext, content }) => { + const pdfContentHtml = await generateChangeOfAddressTemplate({ + applicationContext, + content, + }); + + const { docketNumber } = content; + + const headerHtml = reactTemplateGenerator({ + componentName: 'PageMetaHeaderDocket', + data: { + docketNumber, + }, + }); + + const pdf = await applicationContext + .getUseCases() + .generatePdfFromHtmlInteractor({ + applicationContext, + contentHtml: pdfContentHtml, + displayHeaderFooter: true, + docketNumber, + headerHtml, + overwriteHeader: true, + }); + + return pdf; +}; + +const docketRecord = async ({ applicationContext, data }) => { + const pdfContentHtml = await generatePrintableDocketRecordTemplate({ + applicationContext, + data, + }); + + const docketNumber = data.caseDetail.docketNumberWithSuffix; + + const headerHtml = reactTemplateGenerator({ + componentName: 'PageMetaHeaderDocket', + data: { + docketNumber, + }, + }); + + const pdf = await applicationContext + .getUseCases() + .generatePdfFromHtmlInteractor({ + applicationContext, + contentHtml: pdfContentHtml, + displayHeaderFooter: true, + docketNumber, + headerHtml, + overwriteHeader: true, + }); + + return pdf; +}; + +const standingPretrialOrder = async ({ applicationContext, data }) => { + const { + caseCaptionExtension, + caseTitle, + docketNumberWithSuffix, + footerDate, + trialInfo, + } = data; + + const reactStandingPretrialOrderTemplate = reactTemplateGenerator({ + componentName: 'StandingPretrialOrder', + data: { + footerDate, + options: { + caseCaptionExtension, + caseTitle, + docketNumberWithSuffix, + }, + trialInfo, + }, + }); + + const pdfContentHtml = await generateHTMLTemplateForPDF({ + applicationContext, + // TODO: Remove main prop when index.pug can be refactored to remove header logic + content: { main: reactStandingPretrialOrderTemplate }, + options: { + overwriteMain: true, + title: 'Standing Pre-trial Order', + }, + }); + + const headerHtml = reactTemplateGenerator({ + componentName: 'PageMetaHeaderDocket', + data: { + docketNumber: docketNumberWithSuffix, + }, + }); + + const pdf = await applicationContext + .getUseCases() + .generatePdfFromHtmlInteractor({ + applicationContext, + contentHtml: pdfContentHtml, + displayHeaderFooter: true, + docketNumber: docketNumberWithSuffix, + headerHtml, + overwriteHeader: true, + }); + + return pdf; +}; + +module.exports = { + changeOfAddress, + docketRecord, + standingPretrialOrder, +}; diff --git a/shared/src/business/utilities/documentGenerators.test.js b/shared/src/business/utilities/documentGenerators.test.js new file mode 100644 index 00000000000..25eff5a6f29 --- /dev/null +++ b/shared/src/business/utilities/documentGenerators.test.js @@ -0,0 +1,220 @@ +const { applicationContext } = require('../test/createTestApplicationContext'); + +const fs = require('fs'); +const path = require('path'); +const { + generatePdfFromHtmlInteractor, +} = require('../useCases/generatePdfFromHtmlInteractor'); +const { getChromiumBrowser } = require('./getChromiumBrowser'); + +const { + changeOfAddress, + docketRecord, + standingPretrialOrder, +} = require('./documentGenerators'); + +describe('documentGenerators', () => { + const testOutputPath = path.resolve( + __dirname, + '../../../test-output/document-generation', + ); + + const writePdfFile = (name, data) => { + const path = `${testOutputPath}/${name}.pdf`; + fs.writeFileSync(path, data); + }; + + beforeAll(() => { + if (process.env.PDF_OUTPUT) { + applicationContext.getChromiumBrowser.mockImplementation( + getChromiumBrowser, + ); + + applicationContext.getNodeSass.mockImplementation(() => { + // eslint-disable-next-line security/detect-non-literal-require + return require('node-' + 'sass'); + }); + + applicationContext.getPug.mockImplementation(() => { + // eslint-disable-next-line security/detect-non-literal-require + return require('p' + 'ug'); + }); + + applicationContext + .getUseCases() + .generatePdfFromHtmlInteractor.mockImplementation( + generatePdfFromHtmlInteractor, + ); + } + }); + + describe('changeOfAddress', () => { + it('Generates a Change of Address document', async () => { + const contactInfo = { + address1: 'Address 1', + address2: 'Address 2', + address3: 'Address 3', + city: 'City', + country: 'USA', + inCareOf: 'Test Care Of', + phone: '123-124-1234', + postalCode: '12345', + state: 'ST', + }; + const pdf = await changeOfAddress({ + applicationContext, + content: { + caseCaptionExtension: 'Petitioner(s)', + caseTitle: 'Test Petitioner', + docketNumber: '123-45', + docketNumberWithSuffix: '123-45S', + documentTitle: 'Notice of Change of Address', + name: 'Test Person', + newData: { + ...contactInfo, + address1: 'Address One', + }, + oldData: contactInfo, + }, + }); + + // Do not write PDF when running on CircleCI + if (process.env.PDF_OUTPUT) { + writePdfFile('Change_Of_Address', pdf); + expect(applicationContext.getChromiumBrowser).toHaveBeenCalled(); + } + + expect( + applicationContext.getUseCases().generatePdfFromHtmlInteractor, + ).toHaveBeenCalled(); + expect(applicationContext.getNodeSass).toHaveBeenCalled(); + expect(applicationContext.getPug).toHaveBeenCalled(); + }); + }); + + describe('docketRecord', () => { + it('Generates a Printable Docket Record document', async () => { + const pdf = await docketRecord({ + applicationContext, + data: { + caseCaptionExtension: 'Petitioner(s)', + caseDetail: { + contactPrimary: { + address1: 'Address 1', + address2: 'Address 2', + address3: 'Address 3', + city: 'City', + country: 'USA', + name: 'Test Petitioner', + phone: '123-124-1234', + postalCode: '12345', + state: 'STATE', + }, + irsPractitioners: [ + { + barNumber: 'PT20002', + contact: { + address1: 'Address 1', + address2: 'Address 2', + address3: 'Address 3', + city: 'City', + country: 'USA', + phone: '234-123-4567', + postalCode: '12345', + state: 'STATE', + }, + name: 'Test IRS Practitioner', + }, + ], + partyType: 'Petitioner', + privatePractitioners: [ + { + barNumber: 'PT20001', + contact: { + address1: 'Address 1', + address2: 'Address 2', + address3: 'Address 3', + city: 'City', + country: 'USA', + phone: '234-123-4567', + postalCode: '12345', + state: 'STATE', + }, + formattedName: 'Test Private Practitioner (PT20001)', + name: 'Test Private Practitioner', + }, + ], + }, + caseTitle: 'Test Petitioner', + docketNumber: '123-45', + docketNumberWithSuffix: '123-45S', + entries: [ + { + document: { + filedBy: 'Test Filer', + isNotServedCourtIssuedDocument: false, + isStatusServed: true, + servedAtFormatted: '02/02/20', + servedPartiesCode: 'B', + }, + index: 1, + record: { + action: 'Axun', + createdAtFormatted: '01/01/20', + description: 'Test Description', + eventCode: 'T', + filingsAndProceedings: 'Test Filings And Proceedings', + }, + }, + ], + }, + }); + + // Do not write PDF when running on CircleCI + if (process.env.PDF_OUTPUT) { + writePdfFile('Docket_Record', pdf); + expect(applicationContext.getChromiumBrowser).toHaveBeenCalled(); + } + + expect( + applicationContext.getUseCases().generatePdfFromHtmlInteractor, + ).toHaveBeenCalled(); + expect(applicationContext.getNodeSass).toHaveBeenCalled(); + expect(applicationContext.getPug).toHaveBeenCalled(); + }); + }); + + describe('standingPretrialOrder', () => { + it('generates a Standing Pre-trial Order document', async () => { + const pdf = await standingPretrialOrder({ + applicationContext, + data: { + caseCaptionExtension: 'Petitioner(s)', + caseTitle: 'Test Petitioner', + docketNumberWithSuffix: '123-45S', + footerDate: '02/02/20', + trialInfo: { + city: 'Some City', + fullStartDate: 'Friday May 8, 2020', + judge: { + name: 'Test Judge', + }, + state: 'TEST STATE', + }, + }, + }); + + // Do not write PDF when running on CircleCI + if (process.env.PDF_OUTPUT) { + writePdfFile('Standing_Pretrial_Order', pdf); + expect(applicationContext.getChromiumBrowser).toHaveBeenCalled(); + } + + expect( + applicationContext.getUseCases().generatePdfFromHtmlInteractor, + ).toHaveBeenCalled(); + expect(applicationContext.getNodeSass).toHaveBeenCalled(); + expect(applicationContext.getPug).toHaveBeenCalled(); + }); + }); +}); diff --git a/shared/src/business/utilities/generateHTMLTemplateForPDF/generateChangeOfAddressTemplate.js b/shared/src/business/utilities/generateHTMLTemplateForPDF/generateChangeOfAddressTemplate.js index 5606c1d3e20..f8691976316 100644 --- a/shared/src/business/utilities/generateHTMLTemplateForPDF/generateChangeOfAddressTemplate.js +++ b/shared/src/business/utilities/generateHTMLTemplateForPDF/generateChangeOfAddressTemplate.js @@ -1,5 +1,5 @@ -const { Case } = require('../../entities/cases/Case'); const { generateHTMLTemplateForPDF } = require('./generateHTMLTemplateForPDF'); +const { reactTemplateGenerator } = require('./reactTemplateGenerator'); /** * HTML template generator for printable change of address/telephone PDF views @@ -14,7 +14,8 @@ const generateChangeOfAddressTemplate = async ({ content, }) => { const { - caption, + caseCaptionExtension, + caseTitle, docketNumberWithSuffix, documentTitle, name, @@ -22,50 +23,36 @@ const generateChangeOfAddressTemplate = async ({ oldData, } = content; - const templateData = { - name, - newData, - oldData, - showAddressAndPhoneChange: - documentTitle === 'Notice of Change of Address and Telephone Number', - showOnlyPhoneChange: - documentTitle === 'Notice of Change of Telephone Number', - }; - - const changeOfAddressTemplateContent = require('./changeOfAddress.pug_'); - - const pug = applicationContext.getPug(); - const compiledFunction = pug.compile(changeOfAddressTemplateContent); - const main = compiledFunction({ - ...templateData, - }); - - const changeOfAddressSassContent = require('./changeOfAddress.scss_'); - const sass = applicationContext.getNodeSass(); - - const { css } = await new Promise(resolve => { - sass.render({ data: changeOfAddressSassContent }, (err, result) => { - return resolve(result); - }); + const reactNoticeHTMLTemplate = reactTemplateGenerator({ + componentName: 'ChangeOfAddress', + data: { + name, + newData, + oldData, + options: { + caseCaptionExtension, + caseTitle, + docketNumberWithSuffix, + h3: documentTitle, + showAddressAndPhoneChange: + documentTitle === 'Notice of Change of Address and Telephone Number', + showOnlyPhoneChange: + documentTitle === 'Notice of Change of Telephone Number', + }, + }, }); - const templateContent = { - caseCaptionWithPostfix: `${caption} ${Case.CASE_CAPTION_POSTFIX}`, - docketNumberWithSuffix, - main, - }; - - const options = { - h3: documentTitle, - styles: css, - title: 'Change of Contact Information', - }; - - return await generateHTMLTemplateForPDF({ + const htmlTemplate = generateHTMLTemplateForPDF({ applicationContext, - content: templateContent, - options, + // TODO: Remove main prop when index.pug can be refactored to remove header logic + content: { main: reactNoticeHTMLTemplate }, + options: { + overwriteMain: true, + title: 'Change of Contact Information', + }, }); + + return htmlTemplate; }; module.exports = { diff --git a/shared/src/business/utilities/generateHTMLTemplateForPDF/generateChangeOfAddressTemplate.test.js b/shared/src/business/utilities/generateHTMLTemplateForPDF/generateChangeOfAddressTemplate.test.js index 52e3c6dcdbd..fbefb4c9280 100644 --- a/shared/src/business/utilities/generateHTMLTemplateForPDF/generateChangeOfAddressTemplate.test.js +++ b/shared/src/business/utilities/generateHTMLTemplateForPDF/generateChangeOfAddressTemplate.test.js @@ -3,18 +3,17 @@ const { generateChangeOfAddressTemplate, } = require('./generateChangeOfAddressTemplate'); const applicationContext = createApplicationContext({}); -const { Case } = require('../../entities/cases/Case'); describe('generateChangeOfAddressTemplate', () => { const caseDetail = { - caseCaption: 'Test Case Caption', + caseTitle: 'Test Case Title', contactPrimary: { address1: 'address 1', city: 'City', countryType: 'domestic', phone: '123-123-1234', postalCode: '12345', - state: 'ST', + state: 'STATE', }, docketNumber: '123-45', docketNumberSuffix: 'S', @@ -24,7 +23,8 @@ describe('generateChangeOfAddressTemplate', () => { const result = await generateChangeOfAddressTemplate({ applicationContext, content: { - caption: caseDetail.caseCaption, + caseCaptionExtension: 'Petitioner(s)', + caseTitle: caseDetail.caseTitle, docketNumberWithSuffix: caseDetail.docketNumber + (caseDetail.docketNumberSuffix || ''), documentTitle: 'Notice of Change of Address', @@ -37,13 +37,12 @@ describe('generateChangeOfAddressTemplate', () => { }); expect(result.indexOf('')).toBe(0); - expect(result.indexOf('Test Case Caption')).toBeGreaterThan(-1); - expect(result.indexOf(Case.CASE_CAPTION_POSTFIX)).toBeGreaterThan(-1); + expect(result.indexOf('Test Case Title')).toBeGreaterThan(-1); expect(result.indexOf('Notice of Change of Address')).toBeGreaterThan(-1); expect(result.indexOf('123-45S')).toBeGreaterThan(-1); expect(result.indexOf('address 1')).toBeGreaterThan(-1); expect(result.indexOf('City')).toBeGreaterThan(-1); - expect(result.indexOf('ST')).toBeGreaterThan(-1); + expect(result.indexOf('STATE')).toBeGreaterThan(-1); expect(result.indexOf('12345')).toBeGreaterThan(-1); expect(result.indexOf('Address One')).toBeGreaterThan(-1); }); @@ -52,7 +51,8 @@ describe('generateChangeOfAddressTemplate', () => { const result = await generateChangeOfAddressTemplate({ applicationContext, content: { - caption: caseDetail.caseCaption, + caseCaptionExtension: 'Petitioner(s)', + caseTitle: caseDetail.caseTitle, docketNumberWithSuffix: caseDetail.docketNumber + (caseDetail.docketNumberSuffix || ''), documentTitle: 'Test Document Title', @@ -71,7 +71,8 @@ describe('generateChangeOfAddressTemplate', () => { const result = await generateChangeOfAddressTemplate({ applicationContext, content: { - caption: caseDetail.caseCaption, + caseCaptionExtension: 'Petitioner(s)', + caseTitle: caseDetail.caseTitle, docketNumberWithSuffix: caseDetail.docketNumber + (caseDetail.docketNumberSuffix || ''), documentTitle: 'Notice of Change of Address', @@ -86,7 +87,7 @@ describe('generateChangeOfAddressTemplate', () => { expect(result.indexOf('Notice of Change of Address')).toBeGreaterThan(-1); expect(result.indexOf('address 1')).toBeGreaterThan(-1); expect(result.indexOf('City')).toBeGreaterThan(-1); - expect(result.indexOf('ST')).toBeGreaterThan(-1); + expect(result.indexOf('STATE')).toBeGreaterThan(-1); expect(result.indexOf('12345')).toBeGreaterThan(-1); expect(result.indexOf('Address One')).toBeGreaterThan(-1); expect(result.indexOf('123-123-1234')).toEqual(-1); @@ -96,7 +97,8 @@ describe('generateChangeOfAddressTemplate', () => { const result = await generateChangeOfAddressTemplate({ applicationContext, content: { - caption: caseDetail.caseCaption, + caseCaptionExtension: 'Petitioner(s)', + caseTitle: caseDetail.caseTitle, docketNumberWithSuffix: caseDetail.docketNumber + (caseDetail.docketNumberSuffix || ''), documentTitle: 'Notice of Change of Telephone Number', @@ -113,7 +115,7 @@ describe('generateChangeOfAddressTemplate', () => { ).toBeGreaterThan(-1); expect(result.indexOf('address 1')).toEqual(-1); expect(result.indexOf('City')).toEqual(-1); - expect(result.indexOf('ST')).toEqual(-1); + expect(result.indexOf('STATE')).toEqual(-1); expect(result.indexOf('12345')).toEqual(-1); expect(result.indexOf('Address One')).toEqual(-1); expect(result.indexOf('123-123-1234')).toBeGreaterThan(-1); @@ -123,7 +125,8 @@ describe('generateChangeOfAddressTemplate', () => { const result = await generateChangeOfAddressTemplate({ applicationContext, content: { - caption: caseDetail.caseCaption, + caseCaptionExtension: 'Petitioner(s)', + caseTitle: caseDetail.caseTitle, docketNumberWithSuffix: caseDetail.docketNumber + (caseDetail.docketNumberSuffix || ''), documentTitle: 'Notice of Change of Address and Telephone Number', @@ -141,7 +144,7 @@ describe('generateChangeOfAddressTemplate', () => { ).toBeGreaterThan(-1); expect(result.indexOf('address 1')).toBeGreaterThan(-1); expect(result.indexOf('City')).toBeGreaterThan(-1); - expect(result.indexOf('ST')).toBeGreaterThan(-1); + expect(result.indexOf('STATE')).toBeGreaterThan(-1); expect(result.indexOf('12345')).toBeGreaterThan(-1); expect(result.indexOf('Address One')).toBeGreaterThan(-1); expect(result.indexOf('321-321-4321')).toBeGreaterThan(-1); @@ -151,7 +154,8 @@ describe('generateChangeOfAddressTemplate', () => { const result = await generateChangeOfAddressTemplate({ applicationContext, content: { - caption: caseDetail.caseCaption, + caseCaptionExtension: 'Petitioner(s)', + caseTitle: caseDetail.caseTitle, docketNumberWithSuffix: caseDetail.docketNumber + (caseDetail.docketNumberSuffix || ''), documentTitle: 'Notice of Change of Address', @@ -172,7 +176,8 @@ describe('generateChangeOfAddressTemplate', () => { const result = await generateChangeOfAddressTemplate({ applicationContext, content: { - caption: caseDetail.caseCaption, + caseCaptionExtension: 'Petitioner(s)', + caseTitle: caseDetail.caseTitle, docketNumberWithSuffix: caseDetail.docketNumber + (caseDetail.docketNumberSuffix || ''), documentTitle: 'Notice of Change of Address', @@ -196,7 +201,8 @@ describe('generateChangeOfAddressTemplate', () => { const result = await generateChangeOfAddressTemplate({ applicationContext, content: { - caption: caseDetail.caseCaption, + caseCaptionExtension: 'Petitioner(s)', + caseTitle: caseDetail.caseTitle, docketNumberWithSuffix: caseDetail.docketNumber + (caseDetail.docketNumberSuffix || ''), documentTitle: 'Notice of Change of Address', @@ -221,7 +227,8 @@ describe('generateChangeOfAddressTemplate', () => { const result = await generateChangeOfAddressTemplate({ applicationContext, content: { - caption: caseDetail.caseCaption, + caseCaptionExtension: 'Petitioner(s)', + caseTitle: caseDetail.caseTitle, docketNumberWithSuffix: caseDetail.docketNumber + (caseDetail.docketNumberSuffix || ''), documentTitle: 'Notice of Change of Address', @@ -243,7 +250,8 @@ describe('generateChangeOfAddressTemplate', () => { const result = await generateChangeOfAddressTemplate({ applicationContext, content: { - caption: caseDetail.caseCaption, + caseCaptionExtension: 'Petitioner(s)', + caseTitle: caseDetail.caseTitle, docketNumberWithSuffix: caseDetail.docketNumber + (caseDetail.docketNumberSuffix || ''), documentTitle: 'Notice of Change of Address', @@ -266,7 +274,8 @@ describe('generateChangeOfAddressTemplate', () => { const result = await generateChangeOfAddressTemplate({ applicationContext, content: { - caption: caseDetail.caseCaption, + caseCaptionExtension: 'Petitioner(s)', + caseTitle: caseDetail.caseTitle, docketNumberWithSuffix: caseDetail.docketNumber + (caseDetail.docketNumberSuffix || ''), documentTitle: 'Notice of Change of Address', @@ -291,7 +300,8 @@ describe('generateChangeOfAddressTemplate', () => { const result = await generateChangeOfAddressTemplate({ applicationContext, content: { - caption: caseDetail.caseCaption, + caseCaptionExtension: 'Petitioner(s)', + caseTitle: caseDetail.caseTitle, docketNumberWithSuffix: caseDetail.docketNumber + (caseDetail.docketNumberSuffix || ''), documentTitle: 'Notice of Change of Address', @@ -309,7 +319,7 @@ describe('generateChangeOfAddressTemplate', () => { }, }); - expect(result.indexOf('c/o Guy Fieri')).toBeGreaterThan(-1); - expect(result.indexOf('c/o Rachel Ray')).toBeGreaterThan(-1); + expect(result.indexOf('Guy Fieri')).toBeGreaterThan(-1); + expect(result.indexOf('Rachel Ray')).toBeGreaterThan(-1); }); }); diff --git a/shared/src/business/utilities/generateHTMLTemplateForPDF/generateCoverPagePdf.js b/shared/src/business/utilities/generateHTMLTemplateForPDF/generateCoverPagePdf.js index 3379b9188a3..3204e0cbc79 100644 --- a/shared/src/business/utilities/generateHTMLTemplateForPDF/generateCoverPagePdf.js +++ b/shared/src/business/utilities/generateHTMLTemplateForPDF/generateCoverPagePdf.js @@ -74,7 +74,7 @@ exports.generateCoverPagePdf = async ({ applicationContext, content }) => {
- ${content.caseCaptionNames} + ${content.caseTitle}

${content.caseCaptionExtension} diff --git a/shared/src/business/utilities/generateHTMLTemplateForPDF/generateNoticeOfTrialIssuedTemplate.js b/shared/src/business/utilities/generateHTMLTemplateForPDF/generateNoticeOfTrialIssuedTemplate.js index 3cfdef04dd4..f2bea1dfd84 100644 --- a/shared/src/business/utilities/generateHTMLTemplateForPDF/generateNoticeOfTrialIssuedTemplate.js +++ b/shared/src/business/utilities/generateHTMLTemplateForPDF/generateNoticeOfTrialIssuedTemplate.js @@ -28,17 +28,17 @@ const generateNoticeOfTrialIssuedTemplate = async ({ trialInfo.startTime = formatDateString(trialStartTimeIso, 'hh:mm A'); trialInfo.startDate = formatDateString(trialInfo.startDate, 'MMDDYYYY'); - let caseName = Case.getCaseCaptionNames(caseCaption); + let caseTitle = Case.getCaseTitle(caseCaption); let caseCaptionExtension = ''; - if (caseName !== caseCaption) { - caseName += ', '; - caseCaptionExtension = caseCaption.replace(caseName, ''); + if (caseTitle !== caseCaption) { + caseTitle += ', '; + caseCaptionExtension = caseCaption.replace(caseTitle, ''); } const compiledFunction = pug.compile(template); const main = compiledFunction({ caseCaptionExtension, - caseName, + caseTitle, docketNumberWithSuffix, headerDate, trialInfo, diff --git a/shared/src/business/utilities/generateHTMLTemplateForPDF/generatePrintableDocketRecordTemplate.js b/shared/src/business/utilities/generateHTMLTemplateForPDF/generatePrintableDocketRecordTemplate.js index f2a86815a44..483a42e5a6b 100644 --- a/shared/src/business/utilities/generateHTMLTemplateForPDF/generatePrintableDocketRecordTemplate.js +++ b/shared/src/business/utilities/generateHTMLTemplateForPDF/generatePrintableDocketRecordTemplate.js @@ -1,5 +1,6 @@ -const { Case } = require('../../entities/cases/Case'); +const { ContactFactory } = require('../../entities/contacts/ContactFactory'); const { generateHTMLTemplateForPDF } = require('./generateHTMLTemplateForPDF'); +const { reactTemplateGenerator } = require('./reactTemplateGenerator'); /** * HTML template generator for printable docket record PDF views @@ -11,59 +12,41 @@ const { generateHTMLTemplateForPDF } = require('./generateHTMLTemplateForPDF'); */ const generatePrintableDocketRecordTemplate = async ({ applicationContext, - content, + data, }) => { - const { caption, docketNumberWithSuffix, docketRecord, partyInfo } = content; - - const styles = ` - .party-info { - border: 1px solid #ccc; - margin: 15px 0 30px 0; - } - - .party-info-header { - padding: 10px; - border-bottom: 1px solid #ccc; - background: #f0f0f0; - font-size: 10px; - font-weight: bold; - } - - .party-info-content { - display: flex; - flex-flow: row wrap; - align-items: flex-start; - padding: 0 10px 10px 10px; - } - - .party-details { - width: 25%; - } - - .docket-record-table { - margin-top: 30px; - } - `; - - const templateContent = { - caseCaptionWithPostfix: `${caption} ${Case.CASE_CAPTION_POSTFIX}`, + const { + caseCaptionExtension, + caseDetail, + caseTitle, docketNumberWithSuffix, - main: ` - ${partyInfo} -
${docketRecord}
- `, - }; - const options = { - h2: 'Docket Record', - styles, - title: 'Docket Record', - }; + entries, + } = data; + + const reactDocketRecordTemplate = reactTemplateGenerator({ + componentName: 'DocketRecord', + data: { + caseDetail, + countryTypes: ContactFactory.COUNTRY_TYPES, + entries, + options: { + caseCaptionExtension, + caseTitle, + docketNumberWithSuffix, + }, + }, + }); - return await generateHTMLTemplateForPDF({ + const htmlTemplate = await generateHTMLTemplateForPDF({ applicationContext, - content: templateContent, - options, + // TODO: Remove main prop when index.pug can be refactored to remove header logic + content: { main: reactDocketRecordTemplate }, + options: { + overwriteMain: true, + title: `Docket Record for Case ${docketNumberWithSuffix}`, + }, }); + + return htmlTemplate; }; module.exports = { generatePrintableDocketRecordTemplate }; diff --git a/shared/src/business/utilities/generateHTMLTemplateForPDF/generatePrintableDocketRecordTemplate.test.js b/shared/src/business/utilities/generateHTMLTemplateForPDF/generatePrintableDocketRecordTemplate.test.js index 8b688bf3d9e..f7b3998ff88 100644 --- a/shared/src/business/utilities/generateHTMLTemplateForPDF/generatePrintableDocketRecordTemplate.test.js +++ b/shared/src/business/utilities/generateHTMLTemplateForPDF/generatePrintableDocketRecordTemplate.test.js @@ -7,27 +7,31 @@ const { Case } = require('../../entities/cases/Case'); const applicationContext = createApplicationContext({}); describe('generatePrintableDocketRecordTemplate', () => { - const content = { - caption: 'Test Case Caption', + const data = { + caseCaptionExtension: 'Petitioner(s)', + caseDetail: { + contactPrimary: {}, + irsPractitioners: [], + partyType: 'Petitioner', + privatePractitioners: [], + }, + caseTitle: 'Test Case Title', docketNumberWithSuffix: '123-45S', - docketRecord: '
', - partyInfo: '
', + entries: [], }; it('Returns HTML with the given content', async () => { const result = await generatePrintableDocketRecordTemplate({ applicationContext, - content, + data, }); - expect(result.indexOf('Test Case Caption')).toBeGreaterThan(-1); + expect(result.indexOf('')).toBe(0); + expect(result.indexOf(data.caseTitle)).toBeGreaterThan(-1); + expect(result.indexOf(data.caseCaptionExtension)).toBeGreaterThan(-1); expect(result.indexOf(Case.CASE_CAPTION_POSTFIX)).toBeGreaterThan(-1); - expect(result.indexOf('123-45S')).toBeGreaterThan(-1); - expect( - result.indexOf('
'), - ).toBeGreaterThan(-1); - expect( - result.indexOf('
'), - ).toBeGreaterThan(-1); + expect(result.indexOf(data.docketNumberWithSuffix)).toBeGreaterThan(-1); + expect(result.indexOf('
')).toBeGreaterThan(-1); }); }); diff --git a/shared/src/business/utilities/generateHTMLTemplateForPDF/generateTrialCalendarTemplate.js b/shared/src/business/utilities/generateHTMLTemplateForPDF/generateTrialCalendarTemplate.js index 31bc5b423c0..9bee62d5463 100644 --- a/shared/src/business/utilities/generateHTMLTemplateForPDF/generateTrialCalendarTemplate.js +++ b/shared/src/business/utilities/generateHTMLTemplateForPDF/generateTrialCalendarTemplate.js @@ -19,7 +19,7 @@ const generateTrialCalendarTemplate = async ({ ${item.docketNumberWithSuffix} - ${item.caseName} + ${item.caseTitle} ${item.privatePractitioners .map(practitioner => practitioner.name) diff --git a/shared/src/business/utilities/generateHTMLTemplateForPDF/noticeOfTrialIssued.pug b/shared/src/business/utilities/generateHTMLTemplateForPDF/noticeOfTrialIssued.pug index 9c8460f9da2..b2eee60bce4 100644 --- a/shared/src/business/utilities/generateHTMLTemplateForPDF/noticeOfTrialIssued.pug +++ b/shared/src/business/utilities/generateHTMLTemplateForPDF/noticeOfTrialIssued.pug @@ -13,7 +13,7 @@ .case-information #case-caption - p #{caseName} + p #{caseTitle} p.space #{caseCaptionExtension} .clear #caption diff --git a/shared/src/business/utilities/generateHTMLTemplateForPDF/reactTemplateGenerator.js b/shared/src/business/utilities/generateHTMLTemplateForPDF/reactTemplateGenerator.js new file mode 100644 index 00000000000..8675d566cf4 --- /dev/null +++ b/shared/src/business/utilities/generateHTMLTemplateForPDF/reactTemplateGenerator.js @@ -0,0 +1,34 @@ +require('regenerator-runtime'); +require('@babel/register')({ + presets: ['@babel/preset-react', '@babel/preset-env'], +}); + +const ChangeOfAddress = require('../pdfGenerator/documentTemplates/ChangeOfAddress.jsx') + .default; +const DocketRecord = require('../pdfGenerator/documentTemplates/DocketRecord.jsx') + .default; +const StandingPretrialOrder = require('../pdfGenerator/documentTemplates/StandingPretrialOrder.jsx') + .default; + +const PageMetaHeaderDocket = require('../pdfGenerator/components/PageMetaHeaderDocket.jsx') + .default; + +const React = require('react'); +const ReactDOM = require('react-dom/server'); + +const components = { + ChangeOfAddress, + DocketRecord, + PageMetaHeaderDocket, + StandingPretrialOrder, +}; + +const reactTemplateGenerator = ({ componentName, data = {} }) => { + const componentTemplate = ReactDOM.renderToString( + React.createElement(components[componentName], data), + ); + + return componentTemplate; +}; + +module.exports = { reactTemplateGenerator }; diff --git a/shared/src/business/utilities/generateHTMLTemplateForPDF/reactTemplateGenerator.test.js b/shared/src/business/utilities/generateHTMLTemplateForPDF/reactTemplateGenerator.test.js new file mode 100644 index 00000000000..b0f5b4651ad --- /dev/null +++ b/shared/src/business/utilities/generateHTMLTemplateForPDF/reactTemplateGenerator.test.js @@ -0,0 +1,23 @@ +jest.mock('react'); +jest.mock('react-dom/server'); +const React = require('react'); +const ReactDOM = require('react-dom/server'); + +const { reactTemplateGenerator } = require('./reactTemplateGenerator'); + +describe('reactTemplateGenerator', () => { + beforeEach(() => { + React.createElement = jest.fn(); + ReactDOM.renderToString = jest.fn(); + }); + + it('calls the react render method and renders the result to string', () => { + reactTemplateGenerator({ + componentName: 'SomeComponent', + data: { foo: 'bar' }, + }); + + expect(React.createElement).toHaveBeenCalled(); + expect(ReactDOM.renderToString).toHaveBeenCalled(); + }); +}); diff --git a/shared/src/business/utilities/getCaseCaptionMeta.js b/shared/src/business/utilities/getCaseCaptionMeta.js new file mode 100644 index 00000000000..580b13856dd --- /dev/null +++ b/shared/src/business/utilities/getCaseCaptionMeta.js @@ -0,0 +1,28 @@ +const { Case } = require('../entities/cases/Case'); + +/** + * Gets case caption parts from case data + * + * @param {object} caseDetail case detail object + * @returns {object} case caption parts + */ + +const getCaseCaptionMeta = caseDetail => { + const { CASE_CAPTION_POSTFIX } = Case; + const { caseCaption } = caseDetail; + + const caseTitle = Case.getCaseTitle(caseDetail.caseCaption); + const caseCaptionExtension = caseDetail.caseCaption + .replace(caseTitle, '') + .replace(', ', ''); + + return { + CASE_CAPTION_POSTFIX, + caseCaption, + caseCaptionExtension, + caseCaptionWithPostfix: `${caseCaption} ${CASE_CAPTION_POSTFIX}`, + caseTitle, + }; +}; + +module.exports = { getCaseCaptionMeta }; diff --git a/shared/src/business/utilities/getCaseCaptionMeta.test.js b/shared/src/business/utilities/getCaseCaptionMeta.test.js new file mode 100644 index 00000000000..c87691929d7 --- /dev/null +++ b/shared/src/business/utilities/getCaseCaptionMeta.test.js @@ -0,0 +1,42 @@ +const { Case } = require('../entities/cases/Case'); +const { getCaseCaptionMeta } = require('./getCaseCaptionMeta'); + +describe('getCaseCaptionMeta', () => { + it('returns an object with the case caption, case caption postfix, and the combined case caption with postfix', () => { + const caseDetail = { + caseCaption: 'Eve Brewer, Petitioner', + }; + expect(getCaseCaptionMeta(caseDetail)).toMatchObject({ + CASE_CAPTION_POSTFIX: Case.CASE_CAPTION_POSTFIX, + caseCaption: 'Eve Brewer, Petitioner', + caseCaptionWithPostfix: `Eve Brewer, Petitioner ${Case.CASE_CAPTION_POSTFIX}`, + }); + }); + + it('returns an object with the case title', () => { + const caseDetail = { + caseCaption: 'Selma Horn & Cairo Harris, Petitioners', + }; + expect(getCaseCaptionMeta(caseDetail).caseTitle).toEqual( + 'Selma Horn & Cairo Harris', + ); + }); + + it('returns an object with the computed case caption extension for single petitioners', () => { + const caseDetail = { + caseCaption: 'Brett Osborne, Petitioner', + }; + expect(getCaseCaptionMeta(caseDetail).caseCaptionExtension).toEqual( + 'Petitioner', + ); + }); + + it('returns an object with the computed case caption extension for multiple petitioners', () => { + const caseDetail = { + caseCaption: 'Garrett Carpenter, Leslie Bullock, Trustee, Petitioner(s)', + }; + expect(getCaseCaptionMeta(caseDetail).caseCaptionExtension).toEqual( + 'Petitioner(s)', + ); + }); +}); diff --git a/shared/src/business/utilities/getFormattedCaseDetail.js b/shared/src/business/utilities/getFormattedCaseDetail.js index 89fe02a8717..821f4a25ceb 100644 --- a/shared/src/business/utilities/getFormattedCaseDetail.js +++ b/shared/src/business/utilities/getFormattedCaseDetail.js @@ -1,7 +1,7 @@ const { calculateISODate, + calendarDatesCompared, createISODateString, - dateStringsCompared, } = require('./DateHandler'); const { Case } = require('../entities/cases/Case'); const { cloneDeep, isEmpty } = require('lodash'); @@ -309,10 +309,14 @@ const formatCase = (applicationContext, caseDetail) => { result.hasVerifiedIrsNotice === undefined) && result.hasIrsNotice); - result.caseName = applicationContext.getCaseCaptionNames( + result.caseTitle = applicationContext.getCaseTitle( caseDetail.caseCaption || '', ); + result.showCaseTitleForPrimary = !( + caseDetail.contactSecondary && caseDetail.contactSecondary.name + ); + result.formattedPreferredTrialCity = result.preferredTrialCity || 'No location selected'; @@ -404,7 +408,7 @@ const formatCase = (applicationContext, caseDetail) => { const getDocketRecordSortFunc = sortBy => { const byIndex = (a, b) => a.index - b.index; const byDate = (a, b) => { - const compared = dateStringsCompared( + const compared = calendarDatesCompared( a.record.filingDate, b.record.filingDate, ); diff --git a/shared/src/business/utilities/getFormattedCaseDetail.test.js b/shared/src/business/utilities/getFormattedCaseDetail.test.js index 7970e3779ab..54ebb143d45 100644 --- a/shared/src/business/utilities/getFormattedCaseDetail.test.js +++ b/shared/src/business/utilities/getFormattedCaseDetail.test.js @@ -257,7 +257,7 @@ describe('formatCase', () => { it('should format the general properties of case details', () => { const result = formatCase(applicationContext, { ...mockCaseDetail, - caseCaption: 'Test Case Caption', + caseCaption: 'Johnny Joe Jacobson, Petitioner', docketNumberSuffix: undefined, hasVerifiedIrsNotice: true, trialTime: 11, @@ -272,7 +272,7 @@ describe('formatCase', () => { result.irsDateFormatted, ); expect(result.shouldShowIrsNoticeDate).toBeTruthy(); - expect(result.caseName).toEqual('Test Case Caption'); + expect(result.caseTitle).toEqual('Johnny Joe Jacobson'); expect(result.formattedPreferredTrialCity).toEqual('No location selected'); }); @@ -807,37 +807,37 @@ describe('sortDocketRecords', () => { expect(result[0].index).toEqual('1'); }); - it('should evaluate sort items by index if sorted by date and item dates match', () => { + it('should sort items by index when item calendar dates match', () => { const result = sortDocketRecords( [ { index: '2', record: { - filingDate: '2019-08-03', + filingDate: '2019-08-03T00:10:02.000Z', // 8/2 @ 8:10:02PM EST }, }, { index: '1', record: { - filingDate: '2019-08-03', + filingDate: '2019-08-03T00:10:00.000Z', // 8/2 @ 8:10:00PM EST }, }, { index: '4', record: { - filingDate: '2019-08-03', + filingDate: '2019-08-03T02:06:10.000Z', // 8/2 @ 10:10:00PM EST }, }, { index: '3', record: { - filingDate: '2019-08-03T00:06:44.000Z', + filingDate: '2019-08-03T06:06:44.000Z', // 8/3 @ 2:10:02AM EST }, }, { index: '5', record: { - filingDate: '2019-09-01T00:01:12.025Z', + filingDate: '2019-09-01T00:01:12.025Z', // 8/31 @ 8:01:12AM EST }, }, ], @@ -845,6 +845,23 @@ describe('sortDocketRecords', () => { ); expect(result[0].index).toEqual('1'); + expect(result).toMatchObject([ + { + index: '1', + }, + { + index: '2', + }, + { + index: '4', + }, + { + index: '3', + }, + { + index: '5', + }, + ]); }); it('should sort docket records by index when sortBy is byIndex', () => { diff --git a/shared/src/business/utilities/getFormattedTrialSessionDetails.js b/shared/src/business/utilities/getFormattedTrialSessionDetails.js index fc1f9e9a9c4..990b435227d 100644 --- a/shared/src/business/utilities/getFormattedTrialSessionDetails.js +++ b/shared/src/business/utilities/getFormattedTrialSessionDetails.js @@ -4,7 +4,7 @@ exports.formatCase = ({ applicationContext, caseItem }) => { caseItem.docketNumberWithSuffix = `${caseItem.docketNumber}${ caseItem.docketNumberSuffix || '' }`; - caseItem.caseCaptionNames = applicationContext.getCaseCaptionNames( + caseItem.caseTitle = applicationContext.getCaseTitle( caseItem.caseCaption || '', ); if (caseItem.removedFromTrialDate) { diff --git a/shared/src/business/utilities/getFormattedTrialSessionDetails.test.js b/shared/src/business/utilities/getFormattedTrialSessionDetails.test.js index 1aaac29d3de..a654802f478 100644 --- a/shared/src/business/utilities/getFormattedTrialSessionDetails.test.js +++ b/shared/src/business/utilities/getFormattedTrialSessionDetails.test.js @@ -182,19 +182,19 @@ describe('formattedTrialSessionDetails', () => { expect(result.formattedEligibleCases[0].docketNumberWithSuffix).toEqual( '101-18', ); - expect(result.formattedEligibleCases[0].caseCaptionNames).toEqual( + expect(result.formattedEligibleCases[0].caseTitle).toEqual( 'Test Petitioner', ); expect(result.formattedEligibleCases[1].docketNumberWithSuffix).toEqual( '101-18W', ); - expect(result.formattedEligibleCases[1].caseCaptionNames).toEqual( + expect(result.formattedEligibleCases[1].caseTitle).toEqual( 'Daenerys Stormborn of the House Targaryen, First of Her Name, the Unburnt, Queen of the Andals and the First Men, Khaleesi of the Great Grass Sea, Breaker of Chains, and Mother of Dragons & Someone Else', ); expect(result.formattedEligibleCases[2].docketNumberWithSuffix).toEqual( '103-19', ); - expect(result.formattedEligibleCases[2].caseCaptionNames).toEqual(''); + expect(result.formattedEligibleCases[2].caseTitle).toEqual(''); }); it('formats docket numbers with suffixes and case caption names without postfix on calendared cases and splits them by open and closed cases', () => { @@ -225,13 +225,13 @@ describe('formattedTrialSessionDetails', () => { }); expect(result.allCases.length).toEqual(3); expect(result.allCases[0].docketNumberWithSuffix).toEqual('101-16S'); - expect(result.allCases[0].caseCaptionNames).toEqual('Someone Else'); + expect(result.allCases[0].caseTitle).toEqual('Someone Else'); expect(result.allCases[1].docketNumberWithSuffix).toEqual('102-17W'); - expect(result.allCases[1].caseCaptionNames).toEqual( + expect(result.allCases[1].caseTitle).toEqual( 'Daenerys Stormborn of the House Targaryen, First of Her Name, the Unburnt, Queen of the Andals and the First Men, Khaleesi of the Great Grass Sea, Breaker of Chains, and Mother of Dragons & Someone Else', ); expect(result.allCases[2].docketNumberWithSuffix).toEqual('101-18'); - expect(result.allCases[2].caseCaptionNames).toEqual('Test Petitioner'); + expect(result.allCases[2].caseTitle).toEqual('Test Petitioner'); expect(result.openCases.length).toEqual(2); expect(result.inactiveCases.length).toEqual(1); diff --git a/shared/src/business/utilities/htmlGenerator/index.pug b/shared/src/business/utilities/htmlGenerator/index.pug index c28d66e585a..f5e74a7066e 100644 --- a/shared/src/business/utilities/htmlGenerator/index.pug +++ b/shared/src/business/utilities/htmlGenerator/index.pug @@ -33,4 +33,3 @@ html(lang="en") h3= options.h3 | !{content.main} - diff --git a/shared/src/business/utilities/htmlGenerator/index.scss b/shared/src/business/utilities/htmlGenerator/index.scss index c814c7aa5eb..bb0cc4770da 100644 --- a/shared/src/business/utilities/htmlGenerator/index.scss +++ b/shared/src/business/utilities/htmlGenerator/index.scss @@ -1,13 +1,13 @@ body { margin: 35px 50px; - font-family: sans-serif; - font-size: 12px; + font-family: 'nimbus_roman', serif; + font-size: 14px; } h1 { padding-top: 10px; margin-bottom: 0px; - font-size: 24px; + font-size: 14px; text-align: center; font-family: serif; } @@ -27,12 +27,13 @@ p.heading-address { } h3 { - margin-top: 40px; - margin-bottom: 30px; - font-size: 18px; - font-weight: normal; + margin-top: 30px; + margin-bottom: 20px; + font-family: 'nimbus_roman', serif; + font-size: 14px; text-align: center; font-family: serif; + text-decoration: underline; } p { @@ -45,19 +46,24 @@ table { -webkit-border-horizontal-spacing: 0px; border-spacing: 0; -webkit-border-vertical-spacing: 0px; + font-family: 'nimbus_sans_l', sans-serif; + font-size: 12px; } th, td { - padding: 12px 8px; + padding: 8px; border-bottom: 1px solid #ccc; text-align: left; vertical-align: top; + font-family: 'nimbus_roman', serif; + font-size: 14px; } th { background-color: #f0f0f0; white-space: nowrap; + font-weight: 600; } .panel { @@ -92,14 +98,35 @@ th { float: left; } +.case-information #caption { + font-size: 14px; + line-height: 18px; + border-right: 1px dashed; + + #caption-extension, #caption-v, #caption-respondent { + padding-left: 25%; + margin-top: 8px; + } + + #caption-commissioner { + margin-top: 8px; + } +} + .case-information .space { margin-left: 95px; } .case-information #docket-number { - width: 50%; + width: 48%; float: right; text-indent: 5px; + font-size: 14px; + margin-top: 50px; + + &.condensed { + margin-top: 16px; + } } .clear { @@ -116,7 +143,7 @@ th { } .info-box-header { - padding: 10px; + padding: 14px; border-bottom: 1px solid #ccc; background: #f0f0f0; font-weight: bold; @@ -144,20 +171,27 @@ th { .signature { margin: 100px 0 0 70%; - font-size: 10px; + font-family: 'nimbus_roman', serif; + font-size: 12px; line-height: 13px; } .us-tax-court-seal { - width: 70px; - height: 70px; - margin-right: -70px; + width: 50px; + height: 50px; + margin-right: -50px; background: url('data:image/svg+xml;base64,PHN2ZyBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCA3MTkuOTkyIDcyMCIgaGVpZ2h0PSI3MjAiIHZpZXdCb3g9IjAgMCA3MTkuOTkyIDcyMCIgd2lkdGg9IjcxOS45OTIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0ibTMuMTAyIDM2MGMwLTE5Ny4xMTUgMTU5Ljc4My0zNTYuODk4IDM1Ni44OS0zNTYuODk4IDE5Ny4xMTEgMCAzNTYuODk4IDE1OS43ODMgMzU2Ljg5OCAzNTYuODk4IDAgMTk3LjExLTE1OS43ODcgMzU2Ljg5Ny0zNTYuODk3IDM1Ni44OTctMTk3LjEwOCAwLTM1Ni44OTEtMTU5Ljc4Ny0zNTYuODkxLTM1Ni44OTd6IiBmaWxsPSIjZmZmIi8+PGcgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwIj48cGF0aCBkPSJtMy4xMDIgMzYwYzAtMTk3LjExNSAxNTkuNzgzLTM1Ni44OTggMzU2Ljg5LTM1Ni44OTggMTk3LjExMSAwIDM1Ni44OTggMTU5Ljc4MyAzNTYuODk4IDM1Ni44OTggMCAxOTcuMTEtMTU5Ljc4NyAzNTYuODk3LTM1Ni44OTcgMzU2Ljg5Ny0xOTcuMTA4IDAtMzU2Ljg5MS0xNTkuNzg3LTM1Ni44OTEtMzU2Ljg5N3oiIHN0cm9rZS13aWR0aD0iNi4yMDQ1Ii8+PHBhdGggZD0ibTE2LjQ4NiAzNjBjMC0xODkuNzMgMTUzLjgwNC0zNDMuNTM0IDM0My41MzMtMzQzLjUzNCAxODkuNzMgMCAzNDMuNTI5IDE1My44MDQgMzQzLjUyOSAzNDMuNTM0IDAgMTg5LjcyMi0xNTMuNzk5IDM0My41MjUtMzQzLjUyOSAzNDMuNTI1LTE4OS43MjkgMC0zNDMuNTMzLTE1My44MDMtMzQzLjUzMy0zNDMuNTI1eiIgc3Ryb2tlLXdpZHRoPSI0LjE5OTQiLz48cGF0aCBkPSJtMTE4LjIwNyAzNjBjMC0xMzMuNTU1IDEwOC4yNTgtMjQxLjgxMiAyNDEuODEyLTI0MS44MTIgMTMzLjU1MSAwIDI0MS44MDkgMTA4LjI1OCAyNDEuODA5IDI0MS44MTIgMCAxMzMuNTQyLTEwOC4yNTggMjQxLjgwOC0yNDEuODA5IDI0MS44MDgtMTMzLjU1NCAwLTI0MS44MTItMTA4LjI2Ni0yNDEuODEyLTI0MS44MDh6IiBzdHJva2Utd2lkdGg9IjguMzk4OCIvPjxwYXRoIGQ9Im0xMzIuMDgzIDM2MGMwLTEyNS44ODcgMTAyLjA1LTIyNy45MzcgMjI3LjkzNi0yMjcuOTM3IDEyNS44ODcgMCAyMjcuOTMzIDEwMi4wNSAyMjcuOTMzIDIyNy45MzcgMCAxMjUuODg2LTEwMi4wNDYgMjI3LjkyOS0yMjcuOTMzIDIyNy45MjktMTI1Ljg4NiAwLTIyNy45MzYtMTAyLjA0My0yMjcuOTM2LTIyNy45Mjl6IiBzdHJva2Utd2lkdGg9IjQuMTk5NCIvPjwvZz48cGF0aCBkPSJtMzg0LjA0NSA2ODkuMDE5LTE5LjY0OS0xNC40OTItMTkuODYgMTQuMjEyIDcuNzExLTIzLjE3My0xOS42NDUtMTQuNDkxIDI0LjQxOS4xNyA3LjcxMS0yMy4xNjIgNy4zNzMgMjMuMjc0IDI0LjQyLjE3OC0xOS44NTggMTQuMjA5eiIvPjxwYXRoIGQ9Im03NC45MzUgMjQxLjg0OC05LjY2NiAyOC42NDggMTAuODIgMy42NTIgOC44OC0yNi4zMTggOS4xIDMuMDY0LTguODgzIDI2LjMxOCAxMy4zMjUgNC40OTYgMTAuMS0yOS45MjQgOS4wOTcgMy4wNjQtMTMuODMgNDAuOTc5LTUxLjQzOS0xNy4zNDYgMTMuMzk5LTM5LjcwMnoiLz48cGF0aCBkPSJtMTE4LjM2MiAyMzMuNjMzIDUuODAxLTEwLjAzM2M0Ljg0OS04LjM4NS0xLjU3Mi0xNS44NTgtOS4yODctMjAuMzI0LTEzLjg3OS04LjAxNi0xOS4wMDItMS43MTktMjEuNTQzIDIuNjc3bC01LjcyIDkuODk4IDMwLjc0OSAxNy43ODIgOC4wMiA0Ljg1Ni01Ljc0NyA5LjkzOC00Ni45NzUtMjcuMTYzIDEyLjU5LTIxLjc5MWM5LjYxNi0xNi42MzIgMjUuMDgzLTEyLjI3MSAzMy45NzgtNy4xMjUgMTAuMDgxIDUuODI0IDIyLjE4MiAxOC40MTggMTIuNzY0IDM0LjcxbC02LjYxMSAxMS40MzJ6Ii8+PHBhdGggZD0ibTEwMC4xMyAzMTcuMzQ3LTEuNjg5IDExLjg1LTQ0LjIzNi00LjcwMS0yLjQ0IDE3LjEzNi05LjUwMy0xLjAxNSA2LjU2NC00Ni4xMTggOS41MTEgMS4wMDctMi40NDQgMTcuMTQzeiIvPjxwYXRoIGQ9Im0xNTYuNzQ3IDE2Ny41MDVjMi4xNjUgMi4xMTUgNy4zMDQgNS4xMzkgMTQuNzY2LTIuMTA2IDQuMDQzLTMuOTE5IDcuNjQ4LTkuMjA5IDMuNjUyLTEzLjMzMy0yLjk1MS0zLjA0NC02LjgxNi0uODcxLTEyLjA5OCAyLjM1MWwtNS4zMzMgMy4yOGMtOC4wMjQgNC45NDktMTUuNzczIDkuNzI0LTI0LjA5NSAxLjE1LTQuMjA2LTQuMzM3LTkuMTgyLTE0LjM3MSA0LjA5My0yNy4yNDcgMTIuNTI4LTEyLjE2IDIzLjQ3Mi03LjYwNiAyOC4xNjItMi44ODVsLTguMjA2IDcuOTU4Yy0xLjkxMy0xLjUxLTYuNTkxLTQuOTc2LTE0LjA1OCAyLjI2Ni0zLjI0OSAzLjE0OC02LjAxOCA4LjA1MS0yLjU5NCAxMS41NzkgMi45NDcgMy4wMzYgNi4yIDEuMTQyIDguMjc5LS4xMzJsMTIuMjMzLTcuMzM4YzYuODQ3LTQuMTE3IDE0LjA4MS02LjkxNyAyMC44NjYuMDg1IDExLjM3IDExLjcyMy0uMTYzIDI0LjkxMy0zLjc0OSAyOC4zOTQtMTQuOTI1IDE0LjQ3OS0yNS40MzYgOC43NzEtMzAuMTIxIDMuOTQyeiIvPjxwYXRoIGQ9Im05Ni43MjYgMzUwLjgyOS0uMTc4IDExLjgyNy01NC42NDYgMS41NDUuMTctMTEuODM0eiIvPjxwYXRoIGQ9Im04NS4xNzggNDMwLjg4NGMxMy44MDYtMy45MiAyMi42NjcgMi45MzIgMjcuMzQgMTYuNDc0IDEuNzA4IDQuOTQxIDMuMDc5IDEyLjYwMi0uNDU3IDE4Ljg2My0yLjIwNyAzLjgzLTYuMDU3IDYuMTUzLTExLjI1NyA3Ljc5NmwtMzQuNzU2IDkuODY3LTMuOTU0LTExLjQ1MSAzNC4wMjQtOS42NTRjNy4zMDQtMi4wNzIgOS4wMi03LjMyMyA3LjIwMy0xMi41NjYtMi42NTctNy43MDMtNy4zOTMtOS44MS0xMy43NTEtOC4wMDVsLTM0LjUzMiA5LjgwNi0zLjk2Mi0xMS40NTZ6Ii8+PHBhdGggZD0ibTQzLjMxNSAzODkuMjI5LTEuNDAyLTExLjA4NiA1My45NzItMy41ODIgMS40OTkgMTEuODgtMzUuNTQ2IDI1Ljc1Ny4wMTkuMTU2IDM4LjQ4Mi0yLjU1MyAxLjQwNiAxMS4wODgtNTMuOTczIDMuNTgyLTEuNTg0LTEyLjUxNyAzNC43My0yNS4wNTktLjAyLS4xNTl6Ii8+PHBhdGggZD0ibTIxOS4zNDMgMTM3LjY0LTkuOTAyIDYuNjEtMjQuODI3LTM3LjE0OS0xNC4zMjEgOS41NjgtNS4zMzItNy45ODUgMzguNTQzLTI1Ljc0OCA1LjMzNyA3Ljk4NS0xNC4zMjEgOS41Njl6Ii8+PHBhdGggZD0ibTI0My43NTIgMTAxLjEwOSAxMy4zODktNS42MzQtMTQuODQtMTcuMDM5LS4xNDUuMDYyIDEuNTk2IDIyLjYxMS43MDkgOS44NzIuNjc4IDExLjg0Ni0xMS41NTYgNC44NjQtMi4zMjMtNTcuODk1IDEyLjY1NS01LjMyNSAzOS41NTUgNDIuMjIzLTExLjkyNCA1LjAxOS03LjcwNi04Ljg5Ni0xOS4zNzkgOC4xNjR6Ii8+PHBhdGggZD0ibTMxMi4xNjUgMTAxLjAxMy0xMS42NTIgMi40NTktOS4yMDEtNDMuNzIyLTE2Ljg1NCAzLjU1NS0xLjk3OS05LjM5OCA0NS4zNi05LjU2NiAxLjk3OCA5LjM5OS0xNi44NTcgMy41NTF6Ii8+PHBhdGggZD0ibTM3NC4zNTIgNTEuNDUxLTMwLjIxOC43NzkuMjk0IDExLjQxNiAyNy43NjItLjcyLjI1MiA5LjYtMjcuNzY2LjcxNi4zNiAxNC4wNTggMzEuNTczLS44MTMuMjQ4IDkuNTk2LTQzLjIzOCAxLjExOS0xLjQwMS01NC4yNjYgNDEuODkzLTEuMDg5eiIvPjxwYXRoIGQ9Im0zOTUuMTIgODEuNjU4Yy0uNDA2IDIuOTk3LjIyOSA4LjkyMiAxMC40OTEgMTAuNjExIDUuNTY0LjkxIDExLjk1OC42NTQgMTIuODg4LTUuMDE1LjY4OS00LjE3NS0zLjM1Ny01Ljk4Ny05LjA5Ny04LjMwN2wtNS44MDUtMi4zMjhjLTguNzYtMy41MDgtMTcuMjE0LTYuODg1LTE1LjI4NS0xOC42NzMuOTgzLTUuOTY0IDYuMDc2LTE1LjkzMiAyNC4zMzEtMTIuOTM1IDE3LjIzMyAyLjgyNyAyMC4wOTEgMTQuMzIxIDE5LjA5MiAyMC45bC0xMS4yNzctMS44NDdjLjA3OC0yLjQ0NC4wNjYtOC4yNjgtMTAuMi05Ljk0OS00LjQ2MS0uNzMyLTEwLjA0NS0uMDM5LTEwLjg0MyA0LjgxLS42ODIgNC4xNzUgMi43NzIgNS42NjIgNS4wMzggNi41NzJsMTMuMTgzIDUuNDUzYzcuMzg1IDMuMDUyIDEzLjk0IDcuMTkxIDEyLjM2NSAxNi44MTUtMi42NDYgMTYuMTEtMjAuMTA3IDE0LjctMjUuMDQ1IDEzLjg5MS0yMC41MjQtMy4zNjUtMjIuMjAxLTE1LjIwOC0yMS4xMTMtMjEuODQ1eiIvPjxwYXRoIGQ9Im00NzUuNzUxIDEyMi42MDYtMTAuOTA5LTQuOTYgMjIuMjMyLTM4LjY1My0xNS43ODQtNy4xNzIgNC43NzEtOC4zMDYgNDIuNDkgMTkuMzA4LTQuNzc5IDguMzA3LTE1Ljc4NS03LjE3NnoiLz48cGF0aCBkPSJtNTI5LjMyNCAxMzEuNjkxIDcuOTg2LTIxLjEzNi0uMTI4LS4wODktMTkuNDc1IDEyLjkxMSAxMS42MTcgOC4zMTQtMy4yODMgOS4zNzItMTYuODIzLTEyLjAzNi0xMC4yNzQgNi42MzgtMTAuMDMtNy4xOCA1MC43MTYtMzEuNTg5IDEwLjk4MiA3Ljg2MS0xOC40MTQgNTQuNzEyLTEwLjM0Ny03LjQwOCA0LjE5LTEwLjk5OHoiLz48cGF0aCBkPSJtNTc0LjgzNSAyMDEuOTIxLTkuOTg3LTEwLjU1IDYuMDMzLTIwLjU3LTIxLjM2IDQuMzc2LTkuNTUtMTAuMDkzIDMyLjgwOC01LjY5MiA3LjMzLTMwLjg2OSA5Ljc2NyAxMC4zMTMtNS43NTggMTkuNDQxIDE5Ljg5LTQuNTA4IDkuNDM3IDkuOTc2LTMwLjg5MSA1LjMwMXoiLz48cGF0aCBkPSJtNjM0LjQxMSAyMzQuMTU2YzIuNDM5LTIuMzQ0IDcuMDI0LTYuNzkzIDIuNDc1LTE1LjUxOC0yLjY0Ni01LjA2NS05Ljc1MS0xMC44NDgtMjMuMzU5LTMuNzQ4LTguNjQ3IDQuNTA3LTE0LjU1NCAxMi4xNDQtOS44ODMgMjEuMDg2IDMuMDQgNS44NCA4LjMyMiA4LjI3NSAxNC44ODIgNi40NjdsNS41MTEgMTAuNTUzYy0xMS41NiAzLjM0Mi0yMi42MTEtLjAyLTI5LjIyMy0xMi42ODctNy4wMTMtMTMuNDQyLTMuMzkyLTI3LjU4OSAxMy4yMjYtMzYuMjU5IDE2LjgzLTguNzcxIDMwLjczMi0zLjA0NCAzNy41MjUgOS45NzIgNy44OTIgMTUuMTI2IDEuMTY1IDI2LjQxOS01LjY1IDMwLjY5NHoiLz48cGF0aCBkPSJtNjI0LjEyOSAyODkuMTdjMS42OTYgNi4yMDggNy43MjMgMTMuOTQxIDIyLjM3NiA5Ljk0NSAxNC42NTgtNC4wMDEgMTUuOTI4LTEzLjcyOSAxNC4yMzItMTkuOTMzLTEuNjg4LTYuMi03LjcxOS0xMy45MzQtMjIuMzgtOS45MzgtMTQuNjU0IDQuMDAyLTE1LjkxNyAxMy43My0xNC4yMjggMTkuOTI2bC05LjI2MyAyLjUyOWMtMS45ODItNy4yNzMtNC4yMTQtMjcuMjI5IDIwLjM1OC0zMy45MzkgMjQuNTc1LTYuNzAzIDMyLjc4OSAxMS42MjUgMzQuNzc1IDE4Ljg5NyAxLjk4MiA3LjI3NyA0LjIxNCAyNy4yMzItMjAuMzU4IDMzLjk0My0yNC41NzkgNi43MDQtMzIuNzkzLTExLjYyNS0zNC43NzUtMTguOTAxeiIvPjxwYXRoIGQ9Im02NDUuMzM2IDM2OC44OGMtMTQuMjcxLjc0Ny0yMC44NjYtNy45NjctMjEuNjIxLTIyLjMxNC0uMjc4LTUuMjI4LjUxOS0xMy4wNjIgNS42MTEtMTguNDE4IDMuMTUyLTMuMjY1IDcuNDc1LTQuNjg2IDEyLjg5OS01LjEzMWwzNS45MjctMS44OS42NDMgMTIuMTI5LTM1LjE3NSAxLjg1MWMtNy41NDguMzk5LTEwLjYzIDUuMTctMTAuMzM2IDEwLjcyLjQzNCA4LjE2MyA0LjM4OCAxMS4yOTIgMTAuOTUxIDEwLjk1MWwzNS43MTQtMS44ODYuNjM5IDEyLjEyOXoiLz48cGF0aCBkPSJtNjU0LjAwNiAzOTMuNTE3IDE0LjI0NCAxLjQyMi0yLjIwNCAxNC45MDFjLTEuMDM0IDcuMDEtNS4zODcgNy45NDYtOC4yMSA3LjY2OC01LjI2Ny0uNTI3LTYuODI3LTMuNzUzLTUuOTAxLTkuOTczbDIuMDcxLTE0LjAxOC04Ljk3Ny0uODk4LTEuODI3IDEyLjM1NGMtMS4zMSA4Ljg0Mi00LjE5NCA5LjAzOS0xMS40NjcgOC4zMTEtNS40OTEtLjU0Mi04LjMwNy0uMzQxLTEwLjk1Mi4yMDVsLTEuOTU1IDEzLjIyOSAxLjQxMy4xMzVjMS4yNjMtMi40NTkgMy4xOTUtMi4yNjUgMTAuOTgyLTEuNDkgOS45NDEuOTk1IDExLjk1MS0xLjM5NSAxNC41NzctNS44OTguOTQgNS44MzIgNS41MTggOS41MjMgMTEuMzgxIDEwLjEwNCA0LjU5Ny40NjEgMTUuNDc1LTEuMjgxIDE3LjcyNS0xNi40OTdsNC4yODMtMjguOTI0LTUzLjI3NC01LjMxNy0xLjczNSAxMS43MTEgMjAuODUgMi4wNzl6Ii8+PHBhdGggZD0ibTYwOC4yNTYgNDU1LjQ4MiA0LjAwOC0xMS4yNTcgNDIuNTM2IDEzLjIxMyA1Ljc5OC0xNi4yOTIgOS4xMzggMi44NDItMTUuNTkgNDMuODQ2LTkuMTQzLTIuODM5IDUuNzkzLTE2LjI5MnoiLz48cGF0aCBkPSJtMzAwLjQ4MSAyODEuMDYxYy0xNi44MTQgMi4xODEtMTQuMjI0IDYuMjc3LTE0LjIyNCAzNC45Mzh2NzEuMjU2YzAgMjEuODM0IDAgNzMuMTU3LTU2LjU2MiA3My4xNTctNTQuMTY3IDAtNTQuMTY3LTUzLjIzNi01NC4xNjctNjkuNjF2LTg1LjE3N2MwLTIwLjE5NiAyLjE5Ni0yMy4yMDEtMTQuNDA2LTI0LjU2NHYtNS4xODloNTYuNTU5djUuMTg5Yy0xNy4yNTIgMS42MzktMTkuODcgNS4xODYtMTkuODcgMjQuNTY0djg3LjM1NGMwIDE3LjQ3NyAwIDU1LjQyMSAzNy45OTQgNTUuNDIxIDE3LjA0IDAgMjkuNDgxLTguNzM3IDM1LjgxNy0yMS41NjYgMi44MzktNi4wMTEgNS4wMi0xNS4wMTUgNS4wMi0zNy4xMjd2LTczLjcwN2MwLTI5LjIxMS01LjIzNi0zMy44NS0yMC41MjUtMzQuOTM4di01LjE4OWg0NC4zNjR6Ii8+PHBhdGggZD0ibTU0Ny42OTIgMzMwLjE5NmgtNi44MTljLTQuNjQ0LTIyLjM4NC0yMi4xMTMtNDYuOTU1LTUwLjc4MS00Ni45NTUtMTMuNjQ3IDAtMjcuNTY5IDguNDYyLTI3LjU2OSAyNS4zODkgMCA0MC45NDggOTEuMTggNDYuNDA5IDkxLjE4IDEwMi4zNjggMCAyMy4yMDQtMTguNTY0IDQ5LjQxNC01Ny42MDEgNDkuNDE0LTIwLjc0OSAwLTM0LjEyOS05LjI4My00Mi4zMTUtOS4yODMtNS43MjggMC04LjQ2MiA0LjY0LTguNDYyIDkuMDA4aC02LjAwMmwtOC4xOTEtNTcuODc2aDYuMjc4YzUuMTg1IDEyLjgzIDE5LjEwNiA0OC4zMTggNTUuOTYyIDQ4LjMxOCAyMS44MzggMCAzMi43NjMtMTUuNTYgMzIuNzYzLTMwLjI5OSAwLTE1LjU1Ny00LjM3Ni0yNC44MzktNDQuNTA0LTQ4LjMxOC0yNS4xMTQtMTQuNDcyLTQyLjU4My0yNi40OC00Mi41ODMtNTMuNTA4IDAtMzEuMTE2IDI0LjgzOS00Ni40MDQgNDkuNDEtNDYuNDA0IDE2LjM3NyAwIDMxLjEyNCA5LjI3OCAzNy45NDMgOS4yNzggNy42NDUgMCA5LjAxMi02LjI3MyA5LjU1NC05LjI3OGg1LjczNXoiLz48cGF0aCBkPSJtMzU1Ljc1MSAxNjIuNDAxLS4xODktMjAuNjY0YzAtMi4zMzEgMS44ODItNC4yMTMgNC4yMTQtNC4yMTNoMy44NDFjMi4zMzIgMCA0LjIyMiAxLjg4MiA0LjIyMiA0LjIxM2wuMDM1IDIwLjY2NC4wODUgNC44MTdoOS4wM2MxLjI5OCAwIDEuNzQzLjg2NCAxLjc0MyAxLjcyNCAwIC44NjMuMDY5IDYuOTcxLjA2OSA2Ljk3MWw5LjE4OS0uMDI3LS4xMDgtMTEuNzM4YzAtNC4xOTQgMi4xLTQuMTk0IDIuMS00LjE5NGw5Ljk3Ni0uMDU4cy42MTUgNS45NzUgMS45MDUgNy4wNTZjMS4yOTcgMS4wNzMgNC4zMzcgMi4zODIgMTMuNzkgMi4zODJoNC40MDdzNC4yMDIgNi4zOSA0LjIwMiAxMS4xMTRjMCA0LjcxNy00LjIwMiAxMS4xMTQtNC4yMDIgMTEuMTE0aC00LjQwN2MtOS40NTMgMC0xMC4yMDQuNDkxLTEyLjQ5MyAxLjUxOS0yLjI4IDEuMDIxLTMuMDIxIDcuNzQ4LTMuMDIxIDcuNzQ4bC04LjM5Ni4xMDVjLTMuNjc5IDAtMy42NzktMi4wOTYtMy42NzktMi4wOTZsLS4wNzQtMTIuMTEzLTkuMTg5LS4wMjdzLS4wNjkgNi45Ny0uMDY5IDcuODMzYzAgLjg2NC0uNDQ1IDEuNzI0LTEuNzQzIDEuNzI0LTEuMjg5IDAtNS4xNSAwLTUuMTUgMHMtMS4wMTUtLjIzMS0xLjAxNSAxLjkyNWMwIDEuMDc2LS4wOTMgMTQtLjA5MyAxNGwuMDQ3IDMwMi45MzctLjAzMSA1NS4xMzhjMCAyLjMzMS0xLjg5NCA0LjIxNy00LjIyMSA0LjIxN2gtMy44NDJjLTIuMzMxIDAtNC4yMTgtMS44ODYtNC4yMTgtNC4yMTdsLS4wMjYtNTUuMTM4LTUuNDkyLTMwMi45MzdjLjEwNC01LjkyNi0uMTMxLTExLjcxOS0uMTQzLTE0LjIzNi0uMDEyLTIuMjY2LTEuMjEzLTEuNzMtMS4yMTMtMS43My0yLjk1OC0uMjYtNC40MS0uMTI1LTYuOTctLjAzMS0xNy45MzguNjQ2LTI3LjAyIDkuMjc1LTMzLjQyNSAxOS40NTEtNC45NTctNy41MzktOC40MTktMTYuOTU3LTguMzg0LTM0Ljk2OS4wMzgtMTguMTAxIDQuOTM0LTI2LjMxNCA4LjM4NC0zMS42OTMgNi4yNSAxMS44NDYgMjEuNTc4IDE4LjQxIDMyLjc3NyAxOC4zNzIgMy4wMTctLjAxMiAxMS43MzggMCAxMS43MzggMHoiLz48cGF0aCBkPSJtMzU1Ljc1MSAxNjIuNDAxLS4xODktMjAuNjY0YzAtMi4zMzEgMS44ODItNC4yMTMgNC4yMTQtNC4yMTNoMy44NDFjMi4zMzIgMCA0LjIyMiAxLjg4MiA0LjIyMiA0LjIxM2wuMDM1IDIwLjY2NC4wODUgNC44MTdoOS4wM2MxLjI5OCAwIDEuNzQzLjg2NCAxLjc0MyAxLjcyNCAwIC44NjMuMDY5IDYuOTcxLjA2OSA2Ljk3MWw5LjE4OS0uMDI3LS4xMDgtMTEuNzM4YzAtNC4xOTQgMi4xLTQuMTk0IDIuMS00LjE5NGw5Ljk3Ni0uMDU4cy42MTUgNS45NzUgMS45MDUgNy4wNTZjMS4yOTcgMS4wNzMgNC4zMzcgMi4zODIgMTMuNzkgMi4zODJoNC40MDdzNC4yMDIgNi4zOSA0LjIwMiAxMS4xMTRjMCA0LjcxNy00LjIwMiAxMS4xMTQtNC4yMDIgMTEuMTE0aC00LjQwN2MtOS40NTMgMC0xMC4yMDQuNDkxLTEyLjQ5MyAxLjUxOS0yLjI4IDEuMDIxLTMuMDIxIDcuNzQ4LTMuMDIxIDcuNzQ4bC04LjM5Ni4xMDVjLTMuNjc5IDAtMy42NzktMi4wOTYtMy42NzktMi4wOTZsLS4wNzQtMTIuMTEzLTkuMTg5LS4wMjdzLS4wNjkgNi45Ny0uMDY5IDcuODMzYzAgLjg2NC0uNDQ1IDEuNzI0LTEuNzQzIDEuNzI0LTEuMjg5IDAtNS4xNSAwLTUuMTUgMHMtMS4wMTUtLjIzMS0xLjAxNSAxLjkyNWMwIDEuMDc2LS4wOTMgMTQtLjA5MyAxNGwuMDQ3IDMwMi45MzctLjAzMSA1NS4xMzhjMCAyLjMzMS0xLjg5NCA0LjIxNy00LjIyMSA0LjIxN2gtMy44NDJjLTIuMzMxIDAtNC4yMTgtMS44ODYtNC4yMTgtNC4yMTdsLS4wMjYtNTUuMTM4LTUuNDkyLTMwMi45MzdjLjEwNC01LjkyNi0uMTMxLTExLjcxOS0uMTQzLTE0LjIzNi0uMDEyLTIuMjY2LTEuMjEzLTEuNzMtMS4yMTMtMS43My0yLjk1OC0uMjYtNC40MS0uMTI1LTYuOTctLjAzMS0xNy45MzguNjQ2LTI3LjAyIDkuMjc1LTMzLjQyNSAxOS40NTEtNC45NTctNy41MzktOC40MTktMTYuOTU3LTguMzg0LTM0Ljk2OS4wMzgtMTguMTAxIDQuOTM0LTI2LjMxNCA4LjM4NC0zMS42OTMgNi4yNSAxMS44NDYgMjEuNTc4IDE4LjQxIDMyLjc3NyAxOC4zNzIgMy4wMTctLjAxMiAxMS43MzggMCAxMS43MzggMHoiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLXdpZHRoPSIzLjQ0NjkiLz48cGF0aCBkPSJtMzg4LjE5NiAxNzcuMjEzdjcuNzU3bS05LjQ4LTcuNzU3djcuNzU3bS0yMi40MDQtMTcuNjY2aDEwLjc2N20tMTMuMzUzIDI4Ljg2NmgxNi4zNyIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS13aWR0aD0iMi42ODUyIi8+PHBhdGggZD0ibTMzNC4wMzQgMjEyLjYwOWMtNy4zMjcgMC03LjQ3MSA1LjE2Ni03LjQ3MSA3LjEwMiAwIDEuOTM3LjEyIDcuNDc1IDEwLjA5MiA3LjQ3NWwxLjE4Mi0uNTMxYzQuMjAyIDAgOC4yNzEgMS44NCA4LjI3MSAxLjg0czEyLjMzMS0zLjQwOCAxOS45NDQgMGMwIDAgNi41NjMtMy4xNDggMTkuOTUxIDBsMi44ODUtMS4zMDljOS45NzcgMCAxMC4wOTMtNS41MzggMTAuMDkzLTcuNDc1IDAtMS45MzYtLjE0NC03LjEwMi03LjQ2Ny03LjEwMi02LjkgMC01Ny40OCAwLTU3LjQ4IDB6IiBmaWxsPSIjZmZmIi8+PHBhdGggZD0ibTMzNC4wMzQgMjEyLjYwOWMtNy4zMjcgMC03LjQ3MSA1LjE2Ni03LjQ3MSA3LjEwMiAwIDEuOTM3LjEyIDcuNDc1IDEwLjA5MiA3LjQ3NWwxLjE4Mi0uNTMxYzQuMjAyIDAgOC4yNzEgMS44NCA4LjI3MSAxLjg0czEyLjMzMS0zLjQwOCAxOS45NDQgMGMwIDAgNi41NjMtMy4xNDggMTkuOTUxIDBsMi44ODUtMS4zMDljOS45NzcgMCAxMC4wOTMtNS41MzggMTAuMDkzLTcuNDc1IDAtMS45MzYtLjE0NC03LjEwMi03LjQ2Ny03LjEwMi02LjkgMC01Ny40OCAwLTU3LjQ4IDB6IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAiIHN0cm9rZS13aWR0aD0iNC4xOTk0Ii8+PHBhdGggZD0ibTM3My40MjIgNTY2LjA3MWMyLjMzMSAwIDQuMjE4LTEuODkgNC4yMTgtNC4yMjF2LTQuMDU5YzAtMi4zMzEtMS44ODctNC4yMjItNC4yMTgtNC4yMjJoLTE3Ljg0OWMtMi4zMzEgMC00LjIxMyAxLjg5MS00LjIxMyA0LjIyMnY0LjA1OWMwIDIuMzMxIDEuODgyIDQuMjIxIDQuMjEzIDQuMjIxeiIvPjxwYXRoIGQ9Im0zNzMuNDIyIDU2Ni4wNzFjMi4zMzEgMCA0LjIxOC0xLjg5IDQuMjE4LTQuMjIxdi00LjA1OWMwLTIuMzMxLTEuODg3LTQuMjIyLTQuMjE4LTQuMjIyaC0xNy44NDljLTIuMzMxIDAtNC4yMTMgMS44OTEtNC4yMTMgNC4yMjJ2NC4wNTljMCAyLjMzMSAxLjg4MiA0LjIyMSA0LjIxMyA0LjIyMXoiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLXdpZHRoPSIzLjQ0NjkiLz48cGF0aCBkPSJtMzcwLjUxIDE0NS45MTljMi4zMzEgMCA0LjIyMiAxLjg5NCA0LjIyMiA0LjIyMXY0LjA1OWMwIDIuMzMyLTEuODkxIDQuMjE3LTQuMjIyIDQuMjE3aC0xNy44NDFjLTIuMzMxIDAtNC4yMjUtMS44ODYtNC4yMjUtNC4yMTd2LTQuMDU5YzAtMi4zMjcgMS44OTQtNC4yMjEgNC4yMjUtNC4yMjF6Ii8+PHBhdGggZD0ibTM3MC41MSAxNDUuOTE5YzIuMzMxIDAgNC4yMjIgMS44OTQgNC4yMjIgNC4yMjF2NC4wNTljMCAyLjMzMi0xLjg5MSA0LjIxNy00LjIyMiA0LjIxN2gtMTcuODQxYy0yLjMzMSAwLTQuMjI1LTEuODg2LTQuMjI1LTQuMjE3di00LjA1OWMwLTIuMzI3IDEuODk0LTQuMjIxIDQuMjI1LTQuMjIxeiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwIiBzdHJva2Utd2lkdGg9IjMuNDQ2OSIvPjxwYXRoIGQ9Im0zNjEuODU4IDUxNy40NzlzLTE1LjIyNyAyLjEwMy0xNi44MDMgMHYtMjkxLjA4M3M5LjcxMi0yLjA5NSAxNi44MDMgMHoiIGZpbGw9IiNmZmYiLz48cGF0aCBkPSJtMzYxLjg1OCA1MTcuNDc5cy0xNS4yMjcgMi4xMDMtMTYuODAzIDB2LTI5MS4wODNzOS43MTItMi4wOTUgMTYuODAzIDB6IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAiIHN0cm9rZS13aWR0aD0iNC4xOTg0Ii8+PHBhdGggZD0ibTM0NS4wNTYgNTE3LjQ3OXMtMTUuMjI0IDIuMTAzLTE2Ljc5NiAwdi0yOTEuMDgzczkuNzA1LTIuMDk1IDE2Ljc5NiAweiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Im0zNDUuMDU2IDUxNy40NzlzLTE1LjIyNCAyLjEwMy0xNi43OTYgMHYtMjkxLjA4M3M5LjcwNS0yLjA5NSAxNi43OTYgMHoiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLXdpZHRoPSI0LjE5ODQiLz48cGF0aCBkPSJtMzI4LjI2IDIyNi4zOTZjLTEwLjc2Mi0zLjE0OC0xOS4xNTcuNzktMTkuMTU3Ljc5djI5MC4yOTNzMTIuMDY2IDMuMTU2IDE5LjE1NyAweiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Im0zMjguMjYgMjI2LjM5NmMtMTAuNzYyLTMuMTQ4LTE5LjE1Ny43OS0xOS4xNTcuNzl2MjkwLjI5M3MxMi4wNjYgMy4xNTYgMTkuMTU3IDB6IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAiIHN0cm9rZS13aWR0aD0iNC4xOTg0Ii8+PHBhdGggZD0ibTM3OC42NTQgNTE3LjQ3OXMtMTUuMjI4IDIuMTAzLTE2Ljc5NiAwdi0yOTEuMDgzczkuNzA1LTIuMDk1IDE2Ljc5NiAweiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Im0zNzguNjU0IDUxNy40NzlzLTE1LjIyOCAyLjEwMy0xNi43OTYgMHYtMjkxLjA4M3M5LjcwNS0yLjA5NSAxNi43OTYgMHoiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLXdpZHRoPSI0LjE5ODQiLz48cGF0aCBkPSJtMzk1LjQ1MyA1MTcuNDc5cy0xNS4yMjMgMi4xMDMtMTYuNzk5IDB2LTI5MS4wODNzOS43MTItMi4wOTUgMTYuNzk5IDB6IiBmaWxsPSIjZmZmIi8+PHBhdGggZD0ibTM5NS40NTMgNTE3LjQ3OXMtMTUuMjIzIDIuMTAzLTE2Ljc5OSAwdi0yOTEuMDgzczkuNzEyLTIuMDk1IDE2Ljc5OSAweiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwIiBzdHJva2Utd2lkdGg9IjQuMTk4NCIvPjxwYXRoIGQ9Im00MTIuMjQ5IDUxNy40NzlzLTE1LjIyNCAyLjEwMy0xNi43OTYgMHYtMjkxLjA4M3M5LjcwOS0yLjA5NSAxNi43OTYgMHoiIGZpbGw9IiNmZmYiLz48cGF0aCBkPSJtNDEyLjI0OSA1MTcuNDc5cy0xNS4yMjQgMi4xMDMtMTYuNzk2IDB2LTI5MS4wODNzOS43MDktMi4wOTUgMTYuNzk2IDB6IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAiIHN0cm9rZS13aWR0aD0iNC4xOTg0Ii8+PHBhdGggZD0ibTMwNi45OTkgMjMwLjg2cy01Ljc3NyAxMC40OTkuNTIzIDI2LjI0NWMwIDAgODMuOTkyIDM3LjI3NyAxMDQuNDY3IDQyLjUxNyAwIDAgNC43MjUtMjQuMTQ2LjUyMi0yOC4zNC4wMDEgMC0xMDIuODg2LTQxLjQ3MS0xMDUuNTEyLTQwLjQyMnoiIGZpbGw9IiNmZmYiLz48cGF0aCBkPSJtMzA2Ljk5OSAyMzAuODZzLTUuNzc3IDEwLjQ5OS41MjMgMjYuMjQ1YzAgMCA4My45OTIgMzcuMjc3IDEwNC40NjcgNDIuNTE3IDAgMCA0LjcyNS0yNC4xNDYuNTIyLTI4LjM0LjAwMSAwLTEwMi44ODYtNDEuNDcxLTEwNS41MTItNDAuNDIyeiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwIiBzdHJva2Utd2lkdGg9IjQuMTk5NCIvPjxwYXRoIGQ9Im0zMDcuNTIyIDQzNC41MzVzLTMuMTQ4IDkuNDUzLjUyNiAyNC4xNTNjMCAwIDkyLjM5MyAzNS4xNjcgMTA0Ljk4NiAzNy4yNyAwIDAgOC40MDMtMTEuNTQ4LjUzLTI0LjY2OC4wMDEgMC05OC42ODgtMzguODUtMTA2LjA0Mi0zNi43NTV6IiBmaWxsPSIjZmZmIi8+PHBhdGggZD0ibTMwNy41MjIgNDM0LjUzNXMtMy4xNDggOS40NTMuNTI2IDI0LjE1M2MwIDAgOTIuMzkzIDM1LjE2NyAxMDQuOTg2IDM3LjI3IDAgMCA4LjQwMy0xMS41NDguNTMtMjQuNjY4LjAwMSAwLTk4LjY4OC0zOC44NS0xMDYuMDQyLTM2Ljc1NXoiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLXdpZHRoPSI0LjE5OTQiLz48cGF0aCBkPSJtNDExLjk4OSA0MzIuNDRzNS4yNDcgMTYuNzk1LjUyMiAyNi43NzFjMCAwLTk2LjU5IDQ4LjI5OS0xMDQuNDYzIDQ2LjcyNCAwIDAtNS4yNTEtMTcuODUtMS41OC0yMS41MjQuMDAxLS4wMDEgNDUuMTUxLTI0LjE1IDEwNS41MjEtNTEuOTcxeiIgZmlsbD0iI2ZmZiIvPjxwYXRoIGQ9Im00MTEuOTg5IDQzMi40NHM1LjI0NyAxNi43OTUuNTIyIDI2Ljc3MWMwIDAtOTYuNTkgNDguMjk5LTEwNC40NjMgNDYuNzI0IDAgMC01LjI1MS0xNy44NS0xLjU4LTIxLjUyNC4wMDEtLjAwMSA0NS4xNTEtMjQuMTUgMTA1LjUyMS01MS45NzF6IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAiIHN0cm9rZS13aWR0aD0iNC4xOTk0Ii8+PHBhdGggZD0ibTMwOC41NzEgMjc5LjY4M3MtOS40NDQgMTQuMTY5IDAgMjMuMDk2YzAgMCA4My45ODktMzkuMzc3IDEwMi44OTItNTIuNDkzIDAgMCA3LjM1LTI5LjkyNC0zLjY3Ni0yNS4xOTkgMC0uMDAxLTkyLjM4OCA0OC44MjEtOTkuMjE2IDU0LjU5NnoiIGZpbGw9IiNmZmYiLz48cGF0aCBkPSJtMzA4LjU3MSAyNzkuNjgzcy05LjQ0NCAxNC4xNjkgMCAyMy4wOTZjMCAwIDgzLjk4OS0zOS4zNzcgMTAyLjg5Mi01Mi40OTMgMCAwIDcuMzUtMjkuOTI0LTMuNjc2LTI1LjE5OSAwLS4wMDEtOTIuMzg4IDQ4LjgyMS05OS4yMTYgNTQuNTk2eiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwIiBzdHJva2Utd2lkdGg9IjQuMTk5NCIvPjxwYXRoIGQ9Im0zMDUuODE0IDIzNS41ODVzLTIuMDk5IDYuODI3LTEuMDQ2IDEyLjA3NWMwIDAtLjUyMi0zLjE1MiAyLjA5Ni0zLjE1MiAyLjYyNSAwIDE0LjcgNS4yNDcgMjQuNjc2IDguNDAzIDAgMC0yMi4wNTEtNi44MjctMjQuMTQ2LTExLjAyOS0yLjEwMi00LjE5OC0xLjU4LTYuMjk3LTEuNTgtNi4yOTd6Ii8+PHBhdGggZD0ibTMwNS44MTQgMjM1LjU4NXMtMi4wOTkgNi44MjctMS4wNDYgMTIuMDc1YzAgMC0uNTIyLTMuMTUyIDIuMDk2LTMuMTUyIDIuNjI1IDAgMTQuNyA1LjI0NyAyNC42NzYgOC40MDMgMCAwLTIyLjA1MS02LjgyNy0yNC4xNDYtMTEuMDI5LTIuMTAyLTQuMTk4LTEuNTgtNi4yOTctMS41OC02LjI5N3oiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLXdpZHRoPSIuMzEzNyIvPjxwYXRoIGQ9Im00MTMuMjA1IDI5Mi44NzZzMS45NzUtNi44NTguODM3LTEyLjA5YzAgMCAuNTg0IDMuMTQxLTIuMDQxIDMuMTg3LTIuNjI2LjA0Ny0xNC43OTQtNC45OTEtMjQuODE5LTcuOTcgMCAwIDIyLjE2NiA2LjQ0IDI0LjM0MyAxMC42MDQgMi4xNjQgNC4xNjMgMS42OCA2LjI2OSAxLjY4IDYuMjY5eiIvPjxwYXRoIGQ9Im00MTMuMjA1IDI5Mi44NzZzMS45NzUtNi44NTguODM3LTEyLjA5YzAgMCAuNTg0IDMuMTQxLTIuMDQxIDMuMTg3LTIuNjI2LjA0Ny0xNC43OTQtNC45OTEtMjQuODE5LTcuOTcgMCAwIDIyLjE2NiA2LjQ0IDI0LjM0MyAxMC42MDQgMi4xNjQgNC4xNjMgMS42OCA2LjI2OSAxLjY4IDYuMjY5eiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwIiBzdHJva2Utd2lkdGg9Ii4zMTM3Ii8+PHBhdGggZD0ibTMwNi4yOTkgNDQxLjg1NHMtLjcyNSA0LjgxLjU2NSAxMC4wMDdjMCAwLS42Ny0zLjEyMSAxLjk0Ny0zLjI0NSAyLjYyNi0uMTIgMTQuOTMzIDQuNTU0IDI1LjA0NCA3LjIzNyAwIDAtMjIuMzQ1LTUuNzg1LTI0LjYzNy05Ljg4My0yLjI5Ni00LjA5Ni0yLjkxOS00LjExNi0yLjkxOS00LjExNnoiLz48cGF0aCBkPSJtMzA2LjI5OSA0NDEuODU0cy0uNzI1IDQuODEuNTY1IDEwLjAwN2MwIDAtLjY3LTMuMTIxIDEuOTQ3LTMuMjQ1IDIuNjI2LS4xMiAxNC45MzMgNC41NTQgMjUuMDQ0IDcuMjM3IDAgMC0yMi4zNDUtNS43ODUtMjQuNjM3LTkuODgzLTIuMjk2LTQuMDk2LTIuOTE5LTQuMTE2LTIuOTE5LTQuMTE2eiIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwIiBzdHJva2Utd2lkdGg9Ii4zMTM3Ii8+PHBhdGggZD0ibTM4Mi41MDcgNDczLjc2OWMyLjYyNi4wMiA1LjIxNyAxLjY2NSAxNS4xNzMgNC44NjQgMCAwLTkuNDA2LTEuNjk2LTExLjQ4Ni01LjkxeiIvPjxwYXRoIGQ9Im0zODIuNTA3IDQ3My43NjljMi42MjYuMDIgNS4yMTcgMS42NjUgMTUuMTczIDQuODY0IDAgMC05LjQwNi0xLjY5Ni0xMS40ODYtNS45MXoiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLXdpZHRoPSIuMzEzNyIvPjxwYXRoIGQ9Im00MTMuOTE0IDQ0Ny42MjlzLS40OC00LjY4Ny0uMzQ5LTcuODM1YzAgMC0xLjMyOCAzLjQ5My0yLjg1NCA1LjYzNS42ODItLjk0OC02LjcyNyA1LjM4Ny0xOC41MyAxMC40OTkgMCAwIDE1LjQ3NS03LjczNyAxNi42OTEtOC41NTEgMy45MDctMi42MDMgNS4wNDIuMjUyIDUuMDQyLjI1MnoiLz48cGF0aCBkPSJtNDEzLjkxNCA0NDcuNjI5cy0uNDgtNC42ODctLjM0OS03LjgzNWMwIDAtMS4zMjggMy40OTMtMi44NTQgNS42MzUuNjgyLS45NDgtNi43MjcgNS4zODctMTguNTMgMTAuNDk5IDAgMCAxNS40NzUtNy43MzcgMTYuNjkxLTguNTUxIDMuOTA3LTIuNjAzIDUuMDQyLjI1MiA1LjA0Mi4yNTJ6IiBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAiIHN0cm9rZS13aWR0aD0iLjMxMzciLz48L3N2Zz4='); background-size: contain; float: left; } +.court-address { + font-size: 12px; + text-align: center; +} + @page { + margin-top:100px; margin-bottom: 55px; } @@ -195,4 +229,138 @@ th { .notice-notes li { margin-top: 15px; -} \ No newline at end of file +} + +.please-change { + margin-bottom: 20px; + font-size: 14px; + font-weight: 600; +} + +.extra-margin-top { + margin-top: 8px; +} + +#reports-header { + font-family: 'nimbus_roman', serif; + text-align: centeer; + + h1 { + font-size: 20px; + } + + h2 { + font-size: 14px; + } +} + +#document-docket-record { + // TODO: These are basically cards, and could be refactored for more reusability + .party-info { + border: 1px solid #ccc; + margin: 12px 0 12px 0; + } + + .party-info-header { + padding: 10px; + border-bottom: 1px solid #ccc; + background: #f0f0f0; + font-size: 14px; + font-weight: bold; + } + + .party-info-content { + display: flex; + flex-flow: row wrap; + align-items: flex-start; + padding: 0 10px 10px 10px; + } + + .party-details { + width: 25%; + } + + .docket-record-table { + margin-top: 30px; + } +} + +@font-face { + font-family: 'nimbus_roman'; + font-style: normal; + font-weight: bold; + src: url(data:application/font-woff2;charset=utf-8;base64,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) + format('woff2'), + url(data:application/font-woff;charset=utf-8;base64,d09GRgABAAAAAI+AABIAAAAA/KgAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABGRlRNAAABlAAAABwAAAAcgSorqkdERUYAAAGwAAAAKAAAACoCBQK/R1BPUwAAAdgAABTlAAAjZJAaM2xHU1VCAAAWwAAAAJIAAADGWytVGE9TLzIAABdUAAAATgAAAGB2Xc0NY21hcAAAF6QAAAGBAAAB0uW5QgRjdnQgAAAZKAAAACoAAAAqD6AJkWZwZ20AABlUAAABsQAAAmVTtC+nZ2FzcAAAGwgAAAAIAAAACAAAABBnbHlmAAAbEAAAbB4AAMUwZnt37WhlYWQAAIcwAAAANQAAADYR5TChaGhlYQAAh2gAAAAfAAAAJA/SBa1obXR4AACHiAAAAfwAAAOmzok2fmxvY2EAAImEAAABzQAAAdaD0lKMbWF4cAAAi1QAAAAgAAAAIAIHAcpuYW1lAACLdAAAAaUAAAOkNP6GPXBvc3QAAI0cAAAB7gAAAtw2ujpWcHJlcAAAjwwAAAB0AAAAiuzYRJ4AAAABAAAAANXtRbgAAAAA0e+yRgAAAADZTTOreNpjYGRgYOABYiUgZmJgZmBkeArEzxheAHkvgZCRgQUswwAAUlgExXjapZoNTJRXuscPOKU4Ag6IouIMIl8qpVTkw+EjsrvjiCNfHUeF6XDD9nYb461uervGa7tNg1QG796uMdt6iZfVXaTDLBBrDJAJIbgy17iENMb0zgV31qixStgQQghpiDG+93fODNS6e+92c2Me3pl5z/uc//N/Ps5zzquIEELohUO8KSIt1kqHiHvnxz87KtYLHb8LTRPy/mYR9QPnro1i84/sDv5adu3nb1VNJX/tNVX8ddj38ndpfMQ//eSfj4po+UmJTkSqa7SI2HRUaT4ivhYzETERb0Ycing/4utIfeS/RZ5f9tayEV2trvulHS/9OepQ1C+jfFH//bI3+ofRh6L/vNyhL9bXrShc8YfYhNifx72/steQYHgafzj+9wnWhJ8ndK9KX3Vg1e8Tj67WrTatdqw+uiZ9jW3NO2vOrZlIikzasDZybePauXUb111e71rfnZyf/H7yH5JnNqzd8K/8/c8Na415xgpjtdGFVBtbjFeMA8Yh5I/Gp6Y8k4V/dqTVdN503zRjmjfNp0SmRKfYUv4l5WTKpynnNxo2ejbOpxan/lfqk00V2Dqh3RNBYRQvi3RtpyjSZoVZmxHF2qQo0aZFKZ/LkNXcvS5ytHlRJOKEWaSIYrFOlHAtFamijN92iQSxh6tNRIm9IlFUihhRha+q+a1GJAkX91u1K2JcFIjHYouYRCJEPPPohEFkiICoBctXYDHg0XTtgchkxFaxXeTwL4+n8pFC5izSToDxPTD+CoxnwNgIxnFh0Z4xe6Q4gDX12oBwgvgN7apwaUOiQXsomtHZgriRVi0gPIxfLvTaZRELCgO2/IwZjolc8QH4A8IKni/BoxcbwW4Do0NkoX0z1y1INra9wu85Ik28yuhcYRevYfc27hXwexE87eC7mc/FwgLyCtiywVYFbJlhq4hvubBVxqgCUaU9QWMRbO0UB9Hi4vtjYn0SWQbOWfBMg2cLbOi1LBGjecVK7DVoYyJdJIMvUWRqPxVbtQ/AFC3y4Clfa4KzSDj7hdihNcObDt4SwZIIb0eYOVqUax1wtyB2wb4VznZro6JC8wsbM9rh0aH1YXWkOMg8ddpNuHXArRN8daIB7zVq58QRfHGauduY8z+Ypx35NXIBucg8v0PPMM9e45kJLUcE+e0+Y5Pw9DCo74I4BsTToI0C7ThIvSDtAOVv8O4dZruFB4fFx8gppAVxI61o/pTnPkPOIW3IeWRE+wa/rIQXg/ZUxBOtRpgzIenabWYM4stIuHoksrmfQxS/SnTnEQmFICniczG/lzKmjNix8LmC3+xw4iIfmtHRgriRVvj6jOfaEA/jvNqc8DFuhKsfmYDbIP5dQ4wVMXub2IzGHDAWcdesnWamdiL5PLY2MVswNBs8nGRsM/IxcgppQdxIq3ZqaSY/49KIh4do304cRGLbtNhCbOcxbyEMF5Hh3+b0M2aZZZbZsM9niNxosRupQGx834udlbBXBbvVfK/hs517B5CD6K7XfPi/Dx5uklcz2L6A7QtLleQVMmadWElUGIimeCIjXTsMqgewPYPdV0A2BxMxZAVRiIfK+G7B/gp8vZd6UYWmGuyxY+t+7tUxqwsUJ8n0ZuRj5BQ6W7i6kVbtAAjmxCV0eMjsLvj0amdFD/r60eEjdga5DqFjGBkhs/x8nwBDkNxLgb8bzLcN9AXESAGIx4iLcVEIX0VUCDM1pJhIKyEvSuGljPsWbUpxZscDTjhxwclJfm9GPkZOIS2IG2nlOQ/jvUS6j/F+nlusLsvx2hZYS4WTBPhIo1bo0HZdtFJjPHz24ms9o2QlTGZUEtUjC/ZSyeMsnsgij5N5gmygnshKfoGKlKh0ST0tfHcjrfgkH1tvYzdVV+tG53bqRjbecaMlh9qWDZYcPHWWTxmgyla5kcuvr/F5G5LHPVmV82G7gHuFEhMId4DRjBSju4RxpcxSxn0L1wqiei+fK0FUpQ3i3TS8ewvP3oW7RlA6qSMPwV9APJ3Fm2exPEZ0IV709TNWenGY8SNUBT82LPKXiUUlVMMAHixQ0b+VaHwNCWWArCdHqH438WIuXqzFg9V4cJrKdwsvzuJFHRE/C7IreDMSVFMgugAiP1VtmvqyoKL8HPLv4Wi/gL6L6PHwnI9nhkF/jWdG1Jp6nAo3oDybBmfSZ/pwtBvhxKBmcsFDKxxvpErpqVDR+C2oauFWMjUPDEWMLOZptcZSqSzMUcHvkkE7nyV7LqpPM8+1IG6kld9OI58xrg25xDgP0oV4qaM9XPsRHzKISEbXk61PFXvxZIaRldiEpJO5mdSCreRADpm7fak2zsCkGybbyIcLsPmRqlr1POsku1zoaiAbm3m+BXEjraw/I6pz0GPPSu1Nou8qszUyy9siA5yZPJ1FjdhM7m+RtQIes8H7Ct9zWOVfxeO5YH0N2QYXefh1O+PyGVeA7wtVdTXi5ynQTYHuIejuge4BvAXhbZQVN5XqNqMyvgof1oDSTtYcJKOcPO8CW7PmIntdIHeB3AXyCjgMwmEQDoNw+BUcjsLhMBzehsNhZZmfWJnAw0FW/5dhKUnxWQDaHaAo51sdvDRiP7FA7MTAlIH4S2dUBvmViZ4sYmWzyrVcWB9VufiKynrZYcgszCELcxmVS3yMkYW5ZKFfaSjE9iIyYgeVyoxnismgEu6Xwl0Zz5fLig+KChDZwV0HLy50NMJHK5hOM/9nfG9DLqDjIs9dYrwH6UK88N3Ds/08K+0e4vlh5BpzjsC/H5kASzpjS8Jr7AxWPAFzAmifhteih6CbA53sLedUFlqIMStelCveXlBW4pkqqpb0joPnD6KnHkShGjv2wto7hmfm8cqM6EGHj1gdIZv9KgunhFzl7fA9j0fiiDs3nJ8g7k4Jo+YRJiRd6wx3TncZmwT/ibCeBPIp+I+D/0Tirxv+o2AzAf4T4F9aREYwLp+sKMCraqUgh3cw3owU86zqshgjO+hy7lnIFKtmxwd2VtrjVEQ91j7F2iAVMQa/2FnvTokDZEsddapey8bqLKzOVX46oplZYTphoJMY7WSF6YSJTpjohAkPdUquxjPUqRnq1Ay+nKEXkjXgHCzdhqVjdGJ2/NgkvmDefjAMwKAPGYSXIRgfRq7Buuyf/IydwGNBYu++lqrqxBzsTcFaOxY/URXKzF1ZpZZ2A2SnrFC1ZMrrzLqPCNnPDPWssaGe/EtVtRqUL9uxpB1L2rGkHUvaseRXdMAxqoeoDPvL9py/0vDVB/gpFR+dwkfJ+CgFHw3gnxT84sYfSaC7pdDtYJxEVY4vLNgT4t8F//bQPoUIDK1ISWH+T8P9JyA8C+cLcG6B8zSQpoE0DaRpIE0DaRpIjXDuhnM3nLvh3A3nbjh3w7kdzr+Ecxt8u+C7Db7t8N0E36PwbYfvs/A9CN/n4Pus4vs+Pq8kYifDDByDgQsw8B4MjMEAvT5RkIGlmTyVhWWb+bxFsfEb2FgXZqOPiDXAiJGINarOJo91czvjCrA6xE4c7KQs7eYWfVdOdFtg3YpUIDYwhJiSK48vzNQJmLoAU50w5Qkz9RZMmWHKDFNmmDLDlBmmzDCVA1MdMNUBUx0w1QFTHTDVAVMnwkz9FKZOwFQvTJ0IM3UzHJkemPLBVDdM9cLUieci0wZ6PWtFDP8MxEE6/GTydB41LB8pohoUc68UK8rJ4wpmsxOJdUSnixhrJAZa4bKNsV4s6eG+j/vD3B+hy5mgtgVhpZhZHqnavpLu00DPEq8dwi/n8ct5/NLErIfwwzHFfx7ZlY/fCon77+6ajWpPEeLZCRorHDvg9xGorOTLu9S9EtAdJmfeAt03cJsNt01w2wS3TXDbBLdNcNsEt81wexxuj8Ptcbg9jiXH4fY9uHXCrR+rZNZb4fYTuLVi3RC8WuH1Xay8jJXNS/37fS2BnNIzAjbpTUpUjscjsncxsYqkw6HsrXYgxVSEUipBGTW2nHpmAa2s4PV4zIm3XHi4kfGtiOyhPNz3yv2ZqtBD9ElP1enCoOoxZAU1w1Ex3JSomExWe9RdYNkDDhuf5Q6hUu4S2JFU871GrdxxqgKOEw+PWe0mkVRw2tWuPZNxcue+VdSFd+2VrEo7/2LXnkcXsJ1x+VzlDr5QfMCK9YwssbBqPVA7whJ+lz1FGdfd4iNQfcSnY2j4EERW0HzISnQCFIdBcVjEwmAC7IEdlqrUXjqGNe0BDHlhqFO8IU9HuDYwJgCuCSJvhYiFjXjmNmKBCdQ2KkIVnqon+p086UIaWLMCzG4SOnwnTzFkJ2mAXdlNGuHPhGyiTuRQISz8ZkVrhdrjzagetJpnatQ+fxJcenDJ3dZDtN9h5Y/GU8+Il0niZVJ1uH5qgOyzJ3g+CCoyDk7kKYT0u0310F4wjoLxhtqzh04Inii/B/DKerCOg3UhdHahcOaCMxecn4Axkj3pPbEHG0J70UnFWQjnFBh1YHy01A+8oTpgH0xMid/KTpfnQxzeAZ0Or+vVyYINP5SQtTOq54pHu5F4NCGbiLdyvGdBq5VM2U2FrUD2EHk2tMtIqYKFGvoTO/cPwNBBbK7jNycx7+LawLWR7L6EDg+au7h6WdN7GP8FNvdz9eHlQa7DWCx7xQCcTOCVoDgkvsaCDHi5DpvzcAOj8GPAhnhYM8KSCdnEUxbiZjf8VXBvjzyVYnaVB2irwXY79/Yxw351DhZJZxsj6vnulDtKcqRB9qBY5UFPFxLaEdwB4Tg+HgfZHfiLXjppigJNUO345e72GhKAVxmhsWoPKaO0CD3l6uxgTvmqHj1O1v4Gnm5c8kfoZE/qm1LRJWOin88+FVFyz6nj11jGrVR7015iOJLaukBtXcD2q+Hzijt4aQgObsLBdThIZN5vqAkGPJXA/GPktx4uEtjBxInXVVfVR02dpaZehRfdc3E+D9ZZsE6TgwmgmgdzDF6UVWoBfhbUCUsP8/Sjw4cMMyZABE2QO0GeXQ7aOJDGPGd9AI1yXQkqBgLqLG4xM/aF2Qydn/Sp7AioKC1i7bGhvYr1ax8Z8G3HO8ioaEblMqs8pYhl1OKscmU3IUWsH6E5BsP9sqwtV8mP62joVeefASyfgDe90mAL9z0H4b+eq5N5XUiD2scOMLoS9DHEl5VorgN3I7EjO/4AsWrGW0OsEVPhaG0KeYz+1sjsJjyyCZ2ys5fZbEXnbnlawpx7qEjKY2hSZ8Tcq+ZzDbPUYufrzGrn8z6uDp4NeUxGcgLV20A064nmKDwWR0TrwftMdDDPJaQTkbuBLrUjmKbXnRLdXHuQXqQPvf3IAOJDBpEhdA4j19Dlp8oEqMQTxGZQnbPImFzJSmIAaTwZbsRyE7V/E6MsjNqD9dLz1YiMsQOgOsi1ntmcaHPxWZ6ReRjbA9IA68oEswapCulon1L5sJIoNhAz8dgYqvcZij+5Y7Lwm5UnK+TpNrNJr1SRwbUq2xfgaJ5O7AkzJ8JRJBzpmPkp3OgUN5d43oN0IV747VEVfQH7F7Cb6GPsBPU6iN4VIIlWeReK5m7suIW2MdiOwZavwhGdwRO3sCCWUaFzvhvqnM+ItSZ1sjgK5l4w96FpNJyZsoLfA3NvyKcwW6dWbgP+G8V/o/hvVHyOeJAuxEv0dqOjB+lF+lRn2Av2Xnx3VfnNL2sSc2aHI/ImqGZB1a7OxePpy4xEmwkrQxF5E2RXQTYYrp83QSfPYx6BTu6Mr3xbP6ljsn7WqUiLU1W+g/GXkE7kc8SDdCFeds/d6OxBepE+9PQjPmSQLB7m+QA4JsijIBmwKlztJsPVbiBU7YjBUKUfUmfAVniV5xayV3Uwg0v5b1T1pgFyRtaDIM9tCtt+IxRN7CRCJ69nsH0O2+fQeB2Ng2i8jMbL2D2oMq8GPHa+H4CrDn67hHQinyMepAvxwlc3Y3qQXqQP6Ud8yCASINYX63t8eHWfxq4stbrHkz1G1l4TEjpFf6Zi2E7M1qlVSafOsn18V/FInVtFP3iFfvBB+KzpGZ3Xgjq7LkN28XkPTMl3PZXMUMVMNVz3cU/mWyu5Oc7q/Zh5J5HlaBtAUwmadqLJSf9WQCc9QAc9QAc9oDpHvepHFt+fLL47efG9iXxnsmHprcv3Gf233qz8tbcq8m3K829J4r43tkUt8p2LfNeS/P/C+vfifAmtY2i8g8av8BddMtcIdRq0bOncUJ4X6tWJ44unjc+fLC6eKv7tkYtnkHKe8+pvu3j5OycVL55ERH/n7i4q54sjYv/qDk/u6hZ3YHL3JXdXclfVH95J6fDuLGvBHdgaV136sqUuX3b4L+4Fer/HXmAQrftBV08WOsk2FxLKsr/sn6/ivVnVN9dQqxx48/leebFPXszVZd+5E6H6tmVLnYPsGiJ4fvJ/7TjGnus4Jv/PjuPvWVdGGSUrmKxeOmaZxs9P8PO8eksUoToRI6tiBn7LYr/lYBfmoDd3UBNyqAnZ9II51IXc8PvUbGpDLlGTQWexhb2eg/ou94Q2anwq+KzU+Gwq0TYwPQTTDBYEwDSJBfSBjPUxepj7GURLLXk0SR59o/a/+aAKvSG6E94fBlXUl6KpTJ073yWXxsilW0TGLbqFBRiQa+Ao3rlB1Z1VnWg9Y53IG3jLhYROz2uJsVrqUy31KYsaeZdKPK7OjvzoeownJ5FVMFgAY8MwNgTCanrxVGYcYpYhIucWs9xjlnthzuXZW4C+fB0zVDNDNTNUMwN2qlUo9AbxNjYG4XE7dt7Fzof0Iluw8zB2GrGzEhsrseWheitYr72N5mNovg32Wfbb6XgvE8a2ypNq9e5+GxrKwu+uXvzfAyn4Mzn8HjIGX8q9vtx/G9W7NYfay+Tgp1y6vxS6vxTiJo2VI424ycWOM9hxBjvOYMfb+CyJTidRvWcbYZfvR99jYmUSkWvBe+ptjJl4LmbGUq7N/NaCuJFWzSbXH8Zm4uUcIiMfPYXyzTz6zdoPsf7d0NkEV3myLv/Hg8RXT0V1UiXkm8oG+b8duHeRMctVlSnSUnk6g6d38mSyOvn89sTzF9i4hnjXqf/hsoI4j+XfMlUvdKzvm+TbIWxZDlP/AK8f8q9cnBSnxQ/Ep6INvs6Li2D8Lf2eAwa8sNUjeuHqC/65RJ+gs4cRH54fptf9Mcz4xT+ScwHxE1bLP4m3xQP+vfM/QMllXQAAAHjaLY2xCsJAEERnTwliESSFWFikDKn8BTEJBC8cHGeTLlUIBCvxk9W/iON6HG+Wm93ZhQDYoscTpmpsQDoPjzsOWNPHslAKJOe+znG6+ECt6luOonOW6l1HDf5KX6clpoTPzNM4cN9P97QNEYU9JEj1hmAXa0mOZBO7H6zQwuLFv9VUSzKdEGbe9N3f/wIFVRngAAB42mNgZrFk/MLAysDCasxyloGBYRaEZjrL0MmkDuQzsDHAAFM7AxIIDQpXYADC3yysPn99GBg4opiuJDAwzAfJMR5kmgSkFBiYAXfADaIAAHjaY2BgYGaAYBkGRgYQOAPkMYL5LAwbgLQGgwKQxcFQx/CfMZixgukY0x0FLgURBSkFOQUlBTUFfQUrhXiFNYpKqn9+s/z/D9ShwLCAMQiqkkFBQEFCQQaq0hKukvH///+P/x/6X/Df5+//v68eHH9w6MH+B/se7H6w48GGB8sfND8wv3/o1kvWp1BXEQUY2RjgyhmZgAQTugKgV1lY2dg5OLm4eXj5+AUEhYRFRMXEJSSlpGVk5eQVFJWUVVTV1DU0tbR1dPX0DQyNjE1MzcwtLK2sbWzt7B0cnZxdXN3cPTy9vH18/fwDAoOCQ0LDwiMio6JjYuPiExIZ2to7uyfPmLd40ZJlS5evXL1qzdr16zZs3Lx1y7Yd2/fs3ruPoSglNfNuxcKC7CdlWQwdsxiKGRjSy8Guy6lhWLGrMTkPxM6tvZfU1Dr90OGr127dvn5jJ8PBIwyPHzx89pyh8uYdhpae5t6u/gkT+6ZOY5gyZ+5shqPHCoGaqoAYAIpLiH4AAAAAAAOeBUwAMQA9AEQBFgEWAUYBYgCcAJoAlwBNAFQA7ADDAGUAaQDOBQgAAHjaXVG7TltBEN0NDwOBxNggOdoUs5mQxnuhBQnE1Y1iZDuF5QhpN3KRi3EBH0CBRA3arxmgoaRImwYhF0h8Qj4hEjNriKI0Ozuzc86ZM0vKkap36WvPU+ckkMLdBs02/U5ItbMA96Tr642MtIMHWmxm9Mp1+/4LBpvRlDtqAOU9bykPGU07gVq0p/7R/AqG+/wf8zsYtDTT9NQ6CekhBOabcUuD7xnNussP+oLV4WIwMKSYpuIuP6ZS/rc052rLsLWR0byDMxH5yTRAU2ttBJr+1CHV83EUS5DLprE2mJiy/iQTwYXJdFVTtcz42sFdsrPoYIMqzYEH2MNWeQweDg8mFNK3JMosDRH2YqvECBGTHAo55dzJ/qRA+UgSxrxJSjvjhrUGxpHXwKA2T7P/PJtNbW8dwvhZHMF3vxlLOvjIhtoYEWI7YimACURCRlX5hhrPvSwG5FL7z0CUgOXxj3+dCLTu2EQ8l7V1DjFWCHp+29zyy4q7VrnOi0J3b6pqqNIpzftezr7HA54eC8NBY8Gbz/v+SoH6PCyuNGgOBEN6N3r/orXqiKu8Fz6yJ9O/sVoAAAAAAQAB//8AD3jazL0JfBvlmT8+78xIsmRZ1ui0dVrWZVmSx5IsyfJ923EcxzgHTmJyJ4QcJCGEQEOShnAFSLkh5Wo4GlrK0hlZCQHCVaCUsvRYSvpr2S5LWbbNtqVsD5aSePJ7n3dGtkPDsfv7ff7/X2ns0UiW3ud4n+f7HO8jiqZ6KIperRqiGEpD1YmI4lvyGlb1h6SoVv1zS56h8SUlMnBbBbfzGrXldEsewf0U5+OCPs7XQ1dJAXRQWqca+qTQw75M4bekHjvzPk2p1lNGqpK6gMpXUFS0YFFRejaK35SKIsHBC9wJgUqKtpKTgpr8mtDbuJJooVRNlbJR0Ymiop7jTPlyc0UulxNKOYHJCTaTaLHncnhNFs4klObqE+aGTCpps1o0BqTx16FwCN9I2izq6tBji0dGx4LRGmuTJRIN0mtuWLP6luXsQ8suWr+yddtNP3n22M8OXHw61btm7U0rV8Ka80yUeQ6vuZSyU7spsk7BkCpoVFQJGxXMSSRU8AI6IarUJyfUKoSXqiFLFTR8QS1fqYyiHq+bw68wc3r8Cot838IXzDJZlfhpDcJrp3P4jfBvJida9Pi3ISdyZvy7PEfVJ0yEBsZfR4cRXFrxdShM5/suGRwbZXVqGv2AXFpRF3v/V+cMXSbt4+IuNRptHx5qbpWuGWeRicgB/2Q+UO2inJQXraDyDiyHvNVWmUqlBIqfsNgrnAF7qoBUlIuNTtCcyx2wJwWWn2CMHi88o1JRbvyMWqsrw89gJdBFJzpUJdpoXlOqTyYxT6p4wXGiUCnTWWnExEULJeRRXlMCr9aw2qhQYhRt+Amr/ITVBk9YzfgJq1EsxU/oZe74UFTIOJ5u3/Ffz1HWqO7p9pX/5YcLwWGcoB0ac3SCIT/V8BN/2oS2sgRf2IwTOlupGd5tosyqxy8wkp8c+WmBn/AaO3kN/qsK8lf4PZ3F93EV38cNr5nwFF/phftMh5FmgAVGDjjmcnu8dZ/6n9DhwGIzp1NmP/6XYsg/q5/885vhXxY/Zfq5/4W3mu9r+rfm+1rEV/xPvNxyb+69pvub8+8F30OHb0dlt6LD0mL4d6v059vlK3Ify5Kh+s7ksH6+S0UonspQD1B5J5amWM+eFELJvAdfC3FeMKZEFXsyr4oTQam1eKtleYE6UahVU2YsoVqjGELRvModw9Ir1CuCMjrxI6HeKKawLGxqyoFlrrelsAKXyYIt44siasQKXEtxJtHnh31Y78Q6680Jce7JUkpv81XHMgG7vC2zmWw6ZfUgOwf7ksMXyja1+tNwww5P1aGsxc4ZEGpD6YZQuG/x/PO2bb58b1+0ds+GW/amz1vN79+5+YKdl0eS+7a89uhz+WXzkH/Zkq7LmfeW38PX6e+92xKtlf7trtsqpdHBsebz7/3W6rpG+6uvqrxJlGMfvtuGPl7zyqkb2tEu+4JT95ovXDQ6r5uiVNRfzrymMak2kb3upMJUinpItlL5KJiqIEM9rZgqoTIlWpmThYQ3yJRFxQS+LNeSy3LmJBIaCHMxbyKYS3qjaMLsUauxSTOKLnxZgy9rjGIdvqxWnxTT+LcJ7/a8liFGTc0JzpxY48I8rMwJdVzeG3TkgK2JKOZwtSuXE63l+IpS52aYOrW/OpS12FLJDGaZv1ptRikt+ozn/vLsnbc998Ldtx/7JMzX1dTEEuGFTMWm0yfRs8/ccefzL95+63OnwvWx2po6voZl73/t+wfv+f7zj//Dgeu/8cjNXz2VU+36ZB9qv//VV++97x9fzx+59dYHHjmwB3TxwJl31M3YVqapbmou9SCVTwHbWlSUE7MtDtfVKsqKr7WYheIc1cmC3RbXlhFu2oFvI8A3MYPZkzGKaqx1PUTrhB6jOCjbA6yt4nmYXz3YSuaZVCfwa5Cb0La0lWMNE/Qm0VgPrKpuwdyrx66Be5KhjMFQpq0TPy/OsXOmCX25un9KHeuwhilM0ijqlvZZDagcqTUehDmWtYN2GhBmYZj8RBabHZ7Jhhh8w4wfkT/DbD1QONEa+6cjX3/y1kOIH+uILUL3d6RdjeddtGBlLpB2hqvCMYf/wvrhqxbt+qct3z6B7HO7AsvrBjbNfnLF/M6PeuYOdV48mMiirq/9ZP2Fl3fd8Z1rLl5xY7M0f8NXWmIuPc9rvLGx3bdumB2osac7Gs1u/5xV46PfRxcN57vD8ZE1qPyWxDx6c9tNaxxDbWvubsHmgULUfUwUPUD816DsvQolxHUhQU+Yjf0W8V3g0Io2WijhFS8mlmFel1CKZ9IQz0QRxk25n/uIzzGzneyvOuYMNTdJV80rQwby2aulJ+jNqq2UjQpQSLAXNwWWaF5PgSnSm7Cxx36+AkXJu5qybSiLma9Rc0YwBFZw3auv39u0fumSRd75Y1WLFt5xqPsOuuR7aOn17XNTjS1Lu49KS6VLnu4az+YW37bxD+RzW/HnDsz8XNWJglH+XJWRmEAd/lxq6nPxh2Y4Yxh/WBrsEWehQeStixfjj/QtWgAfef3e3Ial0vvNy7uPokPo5qe7L0g3wedJv3tReviGtrkN8Lk7aYq5EfN6NXWEypvBTGAruzBVSBCtF5YkhZW8UJMqMPLjauwo1/DCrBOCMVnoli2xNTmh655VEhXmporusy2Zr9TBqiu7tVFxLRaIbhZnOqI1mEaWLgOlr+SEvpzQbSqYXfG6VnwHW4osZzra3Dk0Z978RfCSldyTOqdL29o2dwQeMqajmjJ7pbcqCI/MnGiwTpsSYDzeFmGyMwiIUlstXrw3sHCUjaL2g8HGr/Mg2bgA7zSyLYeH+A9BkuHixkk3pNpQOyJvujMdrcl4A/GmctrotZU3jWWq4rQxUxfxxqprOmrd7o729mRjf89IZzYaaW5w10TL1bYqR1Msmtab3Qa6PJcIV9V5o7nH2lrq6NahnuFmdrwuW5NqjvrUbe1N4YgjmmtJ1jTOmmU3qKOplrqq9pCrSW9gLD5jpUmtrktFc4nB2qBd1zHYnvbGWtobKvy+hpY+XW2ipa46F92KzL5yp0WtimKZDlOb2C52Nd4/YxRGR4KGAKMKgHXJPIVALhTWpjwiCo0YrbyzdCcEOlnQyhJkk3ktkaBWg1+p08KljtKS3UUAgo/DuNnq4/zcMHpIQA9JSwXaKKKHpQtE6QL0MOjWfOkgegVlsU43UnkL+HUjUaQy2MpYxctOKHAzX6bG70+VwfuDfsugWI3Fm50ydGHFYmlAWPOXzF6y5Rv/YN+6DiNttc7eOXLr7CV71+396eroyFebzBU0fT7+/OVoIT1At2MrXwN8ACaY2KjyC2F0KFLYQjNaSouthqpIl3U5+i1aePKkbIvGzryPHkc5SoexSl4L/oCR0f+MaySUErukLjlJ/unJW00tvTo0trqnby3G7Df3rlnT34dBOjrz1plf0CtV6/Daqqg8Bf4akXCCJRaH1lKaqTVpEAYz6BcFKRxW3fzJVorg4eYz7zOvqlZTHOWj+qm8ARCUFeMlNZhLD/H6SKgmyzLhwMRkFB2wC/Hq/Pi3w4R9sUENXsdjBbesk/eSSd4vJquFBjbTKnDA+F6aI87C2tySaH9q5e6f7Nj+k6/u+8mlqK19sM9jsHYODLbSj+1G9HmbrnxSOv7KD6TnjhRQj++dF8Zqvr8IvfGrV59/H/PyAHa4e/GazVSXzEtRx5wUNMk8TUi3gEaIrPpkni0DdWMBnZcRoF6GsGZY8cLZMmLXiaSCKQ47MqsvjSEC1wCacQB94h+5btJ4+wUDyfNU7MLU26du2N6PEok5X2HU+/00XgN26czreA0+6jyZ7wWHijJieYLtK+iIauR1ZqLuBq3MQ/UJ0aaWGWeDSMeH2eYAB4Nygo6bUNu8VcQ3p9JgldMNYeCVxg8Pil7a10ZnU0z8X741e22k85qR7Xw2Mti86f6Hf3LxZdIziL94adqTGI//8dXtd9823Ll54dItu5u3vPHgtje3Sq8ja/NsaTHoYvTMe8xRvHaewhEQwSbYL2K4li8BkEyV4I2c9wAZFSpwHEio54XSE4WIDEgiRsFXdYITrRiqWHnRhylKYIpKsfyFAKaoogTjDKfLFyG0EO0lmAHwF/EzRcigCZt8MlmK9WSxqkQHcos3J7r9S9an+OyVe26+7OJlczY3RR5CkXu+07u8uaN67BvS779547cONnRsTIS/umHwqtqGzrivbseqZVuGllag1K37zt/QUlkX2njjLf95wyqi4wksq1cwvWU4+l5GYf+Ld4kK6KMMehWGYNiuYQQMLkiL3RLHC+UnBH1S1GACdTjCLydBmxYzpVwDl+VgXgDWajASFVSYZJUB6z4yEt1PZ0ztKMXhOEdOByTG/+XlHYf27JF+JS1HjyDfe7ejBune0/e9I72DfO/Q87E8smc+ZJ5WDVFe6moq7wZ5YERSDWGIG+ShAXlwtJww4EAeVWBkCw7Z5jmIeXVgOFGMFlv/+Y93kiCRqzMIxhdUokX1N4NgfYESjda6OjSBozarEqMh0aHDRJgxERaAOI4pkdmmJWb2aXwaG3F4FKDp3sycKy/pWnDpwWt677r5e/R1Cyd/Gv3RikeOSi99fM1Dh9I9S+ZfumD1QxGbXUsXpIf0bv69B34m/edyIosebG9AFhaMT1ZSeRPs3kpGtjeiBscS+iqTugzjXRVVB6QGiemxYtODA2M3Zno5Nj04YBPdWN/yepMOUHA5h4UFRqiqEoxQOb6l5wRdbhpXqVmNvIdofzUdNAJ1RT9gQD3f/faWf//BP0tS43mLvvOPfz3+5iTKpX0DiaR17pq6ylIj7X8Nzdo+PNedjp36le8XT/6j9FfU9H3p7fXNqV07//isteR22caDTXgNy1GL46c8W7TFBbWKKgdSdDxE9pSoZmGRWtAWJ/IhP/KF1Jr4GNMjhZ9Ht0nLhy9wMDejZz8psDl6ZBxbduDZc5hnlVQQ6/JaKm8HrrmxlS4FrvEsDh+SxN475LCrBPZnCKuvwyjGsE5UJQsGNWiUaMG7FXsBMRbiTE+Wquxuzh/hCWzi3RhYUSUGiz+iBAjAuJkhQhHwTEVTnwoBesZCixfcedVHrxfe/OqtD9505qcv/MefLxwfHV97uCUSvP7KZNX46MBy1HzdglC9a5FwyaEX7rt2xb7UhT/cd+RXxx+89u5L12y54eIl2+k/zHuoo2d81ra9y0Ff2jHtLxJ9qaXWyHtXLMP6AnBeDGN9MVXocexZMCn6Ep2pL9WYdleS+FLMBtEKUbq+DGtHNZdnTEYSWFZgFyYYc0KYE9WU4r1SSZMChNOZQFYtBz7YgWWyDbJlDoFpNqD2vzz7pnTonh1/fvN/UWc6Z216+IcoOby0waVlEI10TptvVrLBytz4I1QqvSqdfkF66dJFi7yZ6MfvB99GiT+8YlQH2bJK3debLnq+tjv1FbI/Hoc8IVPAOMGGY8mzkIIBTeUMlYhCKCXECZxMY8Wn8QI3IwZ+XMEOq3oHVq/uG1hZxBD0K72rVvX3rV4l44HHpYO0G3++jaqGPOXZaCvvgCVUKUvwz0BeOLwX3KB1drwcWFtKdOMVBTDXy3DcicGRzlFF9OwzIVkUEUh21pqn4JnFUG4r0baOFlc/E6aZKml6Ef18kQyEo72FbB+7i1JTlDmNrFpkHWROnz7NsLTlW+jFF6XHpe++CLQOox62izlAcr1VRWQH8JblIc9XAUSW8KJ2CtEh/G+Y+ctpPfMX1CMI6OuCQLAdtZydz14Hn5dNaxH+yDGGxZ93evmLaBTNf0HqeozwdhfW5etUa/Eu5qlDiueNTOeAxQrVyQl/nCmRPS7ezk4SGOWdgK8pZxUO3JxGsXwqOwjpFaucXpmIqq0lUTGEuR/ixWiJ7JPL8S4XK2qIOcQKHwdbaTWJukguJ6qjWA5aLBB/BNIvZj08WcHl1Va8C2bmVvA2sPqVsEbe6FbLVPCj5Jbx1a6fffPo2+tvWMo3s85AMjA2mun2Vpp6ci1zvrfmhlUr+gdWsj17Hj5694W3LGiZf3GrNzq/b+mu4V37436nz1Prae5bePoAVsmvrVhJePWI1KN+EdvSbmo+9VsqXwa8CqmoGCAsuO5XUX58zYKBrVdRtZgb7XyhUUUFQGoLCPsaZC41yKnWHvlRj1GM4kdyeCIulD1mW89/NoDHNAizjULVC2K1/m+C7wX8YMI7u8ocnRiCn3n8s+qGqhv8auzuc4I3Rx3xVvmqZw/JGU901iPiW6M92MqyZldZfWNLO9H+skYskeYWzP/6fs7UgUMGm9EViDaMKDbXFEgl2SncHFYiSAVO2zH0w8yXkXRDHXZlLG21mFiSqYGXBkJ0kBhn8oJwCGT3yNto53v3IPPL27a+sHl0q67llr6xHSsXpvcPNLUHK+67lT1v7dx47sLH/7D3WemfHhNR+w+3Pnu1+4GfXvEP0uv/spe+or+FXxqsblgc2cA3NKFjp9A3/7Ljden9bzwq/ctjFy0cW/XtKw8g+7r2/szImsmNFdade4d+uXL/J0c3viVd/ftfSo++mO1bfH7H/t+hAX7l9sWjQ//W/4Ca6WvrewnL2EdRqu04dvHgqyYZRQtlKRFh864vdyeTSRml2b0URmkFu4pKy8EIIGgMurwEQitwGcc2HiaFQXwmRWj3QeSOUT3jY3wD3Tn0bA49H6tPRfyTO2Lmhti41OZtmr2IR9f9MFE2eoCdferXa1d1GRIJNev1tr85ciBSE1In0C/Qb7F14CmKPYl1sQKvM0ptlvOioos9KaBkXgc7twZflyQL1b4KXVlUrAaHHOMF9oRYiTdkdRLKAB5wQNqTQhCsZBneoHF8I4jxiuDKCR4OuyBK9EHe0wruCTxSjUkoK5LHAXD2JdlptMz6wiBqzujzTyFqK7++m2EG1tCbTiP9LU+suyKzUXr9DHV7tufP0hvNx/asWt9Un9A1DjM/HGlhE9+8d9v+tC1Vt/TAYz9+uieLImighd18/9eujWVkPLP1zC9UW1XrcdSLPUEQdp1LRUVZGTwL+hTGlZjQCPG4dkyanRgnDJ0BbcDuqgUbhM1/XuUKgnkxcCTmsWAyj2gog9ZXXVT7TECBnNkUSY5jamiSByPKrmg3vXXDMcTe/rVHeyq8QXs60XB+11dvOPrMwtgTq5YsHtp+ftvXP/rOj6TjBfqeryP9c5v6naGMFN26q3mrdBz73xP3Di/3exddkDq8ZwJ1go2JYv3bgeVqxMh7kMobQaqYJPkCtJDI1q1SLkogTVtFxMqB0zWS2lWZ9iTgbkp0g2MrCiwtC6yK4oyULCjYkkagyxpdcB7dt5RejS5AN0rbpOM3J7q/tybROHrhW5cl6I5u5lf9TZqE9ID0A+mH0tVP99Tf2P3nmxH74Bu9IBOsiyoLXnMMcswxWGhwhh5yM9aa50hgwOm10YLVFwPFtOKnfVa46/PgmMLqI1UnJ4SncUJXNabLksyz1SRupqBOlRSqifIKzmTBLZtQNynqFeuSkMr3VGOzxgUBT/mC+LI2mjtbc7FQGVBQLklgFBGyn1P4gs0av6ELFJe9JmFp3vLA7uE0zdzX11fR0GD+2iO9K351TWY2n52b0GZHZNWVNl64a647mJPiHZ2PT45993rJ2cVviK5fIy2VcTj7AOaRH7wspQgTb8Mv4JGHKvLIQ3jkcQKPPIRHFcCjAOGRV+aRlyQUvH78GtY7k11eI5RqhYqkEqABCJ/BriBmlxNMFwfZh7NZhPXeR5hU3AZQI7LGMW/oWWvYrbw14lsi/XFOw117XYmE7eqvM/OuS+gyUzxZtjK8DvOE34NZ8sT1SKpbkGUTmB+L8T7+BO/jeurris44MZHgOoXSlGhWnSxU+2MsGC7MpiAOgRNkS9vwlrbJhitScjIfIZyIBCE5ECH8qdZGJ8oinpKost8FA4/fUKmQiUnQCxve/GY2pmx+NVQnoD4WyYlmP4aFaqqsxDbD9X2GCci0IsIiSI9bIU2AHd3io6j9lZuxKfAEKqZMwd7U1cvXLGEG9tDCphZmpfSze++T/vrMRfTBN9Dsp/udwaxiD56SXpbue6yruW/Om/NTbCql7bxYyvWsO4bUsMeaKUrNYv2JUrcoXskreyWPrxa8EpRwBGuKKFCpxQ51w/IQpcU+qpzYx6LxD2NNMSTzYaIp4ShWDx3eW+GZyhI2AkYWjEnRiVnsDMBzTi9+zpbMB5zwKACwz5IEd3G2vgAzON+Ma9AVH3neR66b13bRTN8K+pE1Qwx6jxlaQz+2agjRvRdNLtzQx0huNLAhoc/NZn44p0WDHV/rHGkF+sZwixpftw2dzszO6RMJXW4O+kepYShXmpB9Av5Ff4h5Y4Zs4dTeMslMAY7gmISk4DD9OFTPlxPiy80K8eUziAfseg6SYOmJTXMQM7yefn7TCE3P2ZLQNg8xPyRLY1pHTmfmNqtBr41n3mFex2uppi6hSL1XLMN6XeYhOWBImlhhTRa8JnuShCsYE+rkWoiOQGqdGpZlFI2wJ4H/pELitOM/NRLmGy3aKAlijJAl8YDvgsShc0b4QnAGxMMzSABAHK5DxgXZlvO9tkSku4UZuZx+aVMX889v7pvbMnQyd/7itpqQy+6uHh1njs/PMZjnvVsmMz//V776K4TPQ1gH7Zi2DGRJiA6GZB0M1qSndNCh6GCli3QeZAnXk7LWJQnjkxmF8cmZjG8Ef1WCsKEur/+UoSbrJ8XAOoY8ZDRIVqxMigS+ioSGLupBaNZq+vCGXgYdqatUG6KZNN0zvOauRw7Sq83R4OTSJtVSs0u6LUP3rk+UZjHomNuiwnQObJLmo0JdTaWRK9eq4Y73ogfun9TZTXQiwTIBzh9AryakHaB/ss6lsM/TY144qWGlxm+Rfd5ZOucqeuY8R0jnSsE0czPpdhO6sZ8WKx1/RzejmeGPUus7MXkr6Wd7+usNdPeS317eMNCQG03oM8OKItKGaFfb6eHO+s389h1STvHNmkG8zjB1g7I3KqtSstQqnCGQWqncQkPy1Ua85hpIChf8ciLPD8WLDn8YL1vth0s1LNsvW2ALpstCLLClXAveJe+xECPswBoaAVPrh+SGAVywDks2X+atzik0MgqNWqTsMLpoKJAfEWnyrV2RMmwaNqDT6GZ0G/oEXE5lz3mTay/uZCR1WlLTI1ck1FwoXc8cG85pE6eHmXxC3bf59E1zun26RELbeD5z+lQze/j06Oa5WkVu/Jm3VQcwP9zUATlnNW0wXIoGG4kGi+Um0F8PSFAp/eUriRAr3SDEypkms1JukLHJL7OVwnM2E35ZKWmiKcXsEb2QkAZsrYMyuACRF1H30oqZYvenfYgrFr2tXJEXG7tRX78bHaafH96EnljR1Hh6Fxq6JKFvXcQcXdiSOP0QvXb9aGkiUd668NRKtu/0zzcMG8AsUguxn30X+1kOU9xTrKUonhZcLqEQCilaUkipwIvUYvQIi4UslMgS6TmtU+nBs+JBcHt00EiSU0ZIYy48igZ+fBdSPbX+oqelj7/+hvTMEbTyyce/e+TYYfEYfehHqO/oxuPSxwfvlf7rmfVHUO/T0o+l51EXyqAmNC49Jud7ACtBnO2haqnt0xZdZHD8ldeT2AZTQC6w0hasXkovgySSaoOKBjY33mTeRpTXBrBSbZtSXl0SEARAnnItycFR2OhjsbA5scZLertAGhCynRXhECVV4eAtOZV0sMZrNN0NNNO+lr5mEpn2XtF5/48Qa7REk7XChkv8kcCmK1cnSjTDS5nLNvZpEs8+sUPgHeW0dFOkPmY1a1UJ+nCF17dj5YNf6yV0L5QOEVn58a5dQpGIRoyrTgqVfMFM0gxKDkYMYGEFjCSUAWFBWqU2gKGLiq30GqCErOVEsw0EZwaFs0HnT0FLWb3h6dimCkRoBLIgdsM2xi73VJCicDiEZgp1wzNIi+pRydPrj3fs2+moca+7I3Oe/tKD49f+cX51ne+SnW15tPLIE9898tSjjz9DH7wXIp0Nx6WP7pVO/KBnqCbb7Fpn42vc4/Or+3oiw70vIw+OfY6jbtSIcmhMepwiPY6qx4jf5KlrFe9SSeyUWOHDYi8DZkTBlcJFKRa7y0+VlZGQl7BFcwKye4I/mXeTioi7WqsUKzo0IPbSJMQINeA3FZbVuInbFIycaHUAs/xKqBuFUJdsSVZRgSpWbopCNhzO4yABrBWjpF2hOGftSTbWmrSI6dpAX4csyLc4snQxut3RKK2WVmTAagmX7qhZ+pUbZpvLE6oyWyyTYC67uFedePKJA/NDvGfylXCC3i7tIIaLLtBWR+uzD9zo9diJzRo98wvWqNpEZamjVL4eOEOlRA3mhaaekIcwpRawXM6U6GdP5v3ECvs9EB80QgtnISSXySgc5xeyMi6mk0LIiM1ytBAnafgJd1yHUbNHfhYbBWdKia3EHGZWKAueOZmDquBRjcFi80fqQdM8pnwFRFaYfZp6zL5kTvBzE1xFvAGetYDy1SfsXEpWMuAXj5QE/qeANcmNqCCJh62KXGYczTmTtVvz2/ZfcNX1+Ud+948X72q1O5365qyvOXnx/rWXLfgKCi/fKX3wzu5rO0yVjtIw+nD9FZk7r7xw5MLW9oWv7nvu7bjFVSPNXrWpYevGC2Ytbbmdf2Prc/+RsHpqFDyjKiG+YAOV58DKmLAbKE+SEonoYEn91kF6ChygQkxSsZYzgk4It0uwHywh/qDEiEVRSToqKzm5o5KFMrzMRy/Blk7kM8txlIq4PFWWw5o1xLJH6Vzld59Cas7ON9ZNNsSzvJ1To6eFSuYYukPaWLhHfepfa1MxO6fB0IwpMdliqQhbpb6nIPu1XxC/FoauWC/kRUpJBpLQIphTIgUFCpOVgDLs4gMn5GUTdE+qqwGy7AAlL9uAl130egZCjxW/xkCoNJgU/24oIX2FlEiVAn4JyMVG7LloGbdA7To0DUBJ8wn0seBNxdOHF8zx0jfdW/iH0W3o2AUt9Ozejle2vnfL+CDTrHJiAj2DI5Or3njmxDv06k3zcDBQ1rNkcu+BX+ZybRu6vn0Hff/m7rP9eUzpnD0XwR6eMF+kHMWGZHlRBmSxI/OMNjMNRh+wuIfK61S5RBzZJLe+ayN6fLgzKKXTk1KwEdZGs4jx9W2aXEXfPlRbUe/Hq9O3LD21ls3P4yFWO/Ou5hW8pjqoi0GrohBOyTpVXp0iCzvCGDirLxCAGIDnxXo549vy899XkxppuM4ghF4QnWV/E1wvYHjpCkEudwL/DhfzuJgW6D7URqZ4jjeO3UmMtywB5UZGoU2NSdMS6prp4eFU+X/+vs/U2UZfotJr6I608xfvGhrnoU0ra6TNWekx6cacNOZKAK0af8xSNxmm170Y8GG9Q/h/TJXfPj65lBZTPj6IYad++6l+5vnTnexTs+LFfNB+TH8z1aJY8loZcUZiTYA4IdMheFKiFpKq7ioioRZebAUJaQESWVNTkEirRNnQ4gQGwqx4X5nIcjQzEAgzGvlFVn72ojhaKm2ra8nQR3lDplZneqkj0R9PLEcfzV21YfwQ2jTQm55cmCxZG3l9aMtQ33iilM+i4/RAdwwTpEGuKrPDLb25qHvFaFXEocW36rfuemfyB5vaMA9YdUOoD/VceMeu6lCQAEuS3yE011LjVN4HtgQSF97kOdURo5TwCdGB95+DRN4OHE/nww4Skvvw3oLCoCMMOUo9TUwrVY31Vq9IWk1spRdNyxb0lvMwxJxgYI1CcfqQ3dWS8uv/9M5w9xp0LN1ik/ZiQ9bZOTnQ0RkrpaVbyCajXdWejkqJR9uuzcVAjbUB/+St0i2tbdFyiLnLo22tKETfs5bQ2IdpVJOYR+kvIXkrg1JPzmAfUkYZoFKEw57KYi8AKZA7KomrpUROaS0p40i4IxrUpNIJwkaYLih90xq/2WdFKWwYU0wfjfWxvHxZ+8CWWcFclHVOlty56eDeBQMJezrtY99Xl5bN3b0JPeA75aTLQ43Ld5wvuclaD0hv0StVI1Q51UCRHhyRxUiqnIdwHAnGYtxtLsbdHToIYeikyMmVNc5n9UP4pbbZU9YD6K1dfL23BNE17d+Q3lLv7EJaX7L+FNVei7pIXHHmzTO/oFcXe54YEld8Vs8Tk0L++NPo58dU66DjCVEDeK3u4loJrC2V10opa8URiEFeK0tsMVtOAI2yVjuGqmEOh8Y4duB8A9/oCNOoxFvP70JvSdGTqKZTRdUncaDV9bdr5BjoEL2V1WE5qnFUoLRmaXgcjBDCUQrsxCG0+iG0Oi9J0ml6K/32ZJCumvxX+Fud9AHz0ZkdmE43JTA8NKl42Kjyi/SdyUTafVafjvn9acv+/eQz7awf/UV1F6WDqqaGh+Jt6VR3WUEt96nplb5TAAfIH6xD9my4KYnMW6X3Yn5VczDTKL0iOHnAyq1n3mPeYQrYxjZS98kZRCGUKiTJUQjysOBVUVXgvhBmqBbDIi04L0prBliUIziaV5+csPHQaCu3Muf1ECZQeuzFBd4IjeCCCkfo6pNiExx0sWFdjeXENA+GtxJDITcnhiKwP70x/JQ/JyQ5IYLRt6lAudzVGaXZCKL3qSLldEcmZGo4SyrZjuwzupmVWhmGBK17G8WJkbHMLHtwqK2156ePPfVWtFRr9eTWds0aKp9/+8KVu1EwVxfsjFyx69juRaG+zB3j86Neozseaejsa9964+17Jv+S1Fqi7Q2dc2Z3X/6NltlhHvmrdsox1pn3WB/WAQuWx0VyDwMEvhWYT8RTgblSQ2XdraJCICgfAEnSYEUn8xxJRnOUfDYETgFpMZOqoZzEkRBKcHKiWg+scVeQTvrynOKoOCgbmkjTSyis8WMogGSoYATEF0fX5LYNfOtN6bXZl/c+UEHj/TXYvmLps4kOh8rNT37c0iB98uN3pfcb2reyL7XET+UHxl79Cfpapp3kSLFOrMM6UQUdVZB7g/qcFyrZoAIcJo1jQL6cVisThFXAggmyyMlwNWlUIVToIR/DeEjzv2gnwQEHNSPK4VQK0dRUQ4DSeaGk3OQwim5Ghh9dNTHQ3pRlS8zZ4cX3XtU63hgYm7j02f9Ez/0SufaMt3T3Dra4ysP5e37052R7cMsqpFP0mm3GcnFQNZBBhKqeYEkVPCoqyEJOVvAYRY5Rumx04FOQXIUOgpDkupcT0+QknSai2pJMimXqk/lq0nZYrdPKFTDIeItwvIESQx4gTG3NTTWa2OxK9h9cqUatSROSgnK7CYA3TG3r24d7N3QwqRXoiUTvrluv6Lt05NAbKDI00t0WtZyfGhtFT/8SVWV60eb+GjV/ak97ko0bOf++2U1I+84LT/bgDf7bbM+TSr/ne8xyLDc7llwXlbeC5AzktJMsOQ97slChtcJxjgqwiLLksMYJFUmgEqMGA9DAmaZpgK5pnxJ0KDJBvrQsqebfPv3ttfUJraRWO90tl3Vc2JJY+fgVz7yH7EjPlFWcP7sVvfY2Mm5vvu/KdZfx61sHnAc2Ix0a8O7rWnoT1jM/RTEmHKdHqetn5Jtrk8QVwmrzHjDTlMcCISimQKhOgYfksQQDSSUTD7k/aIfyJfMhklYKBfBuwm/ChoiJV5OWeIjR8PYqcErXBUe6LuxYilCqdYbImbSphLU/nSItETN0UwlR1W4E3X8Qt/p76tC2bZVVkYOrv/pAdy7V4+CqHJm6J55AlV0DCTXfRT8wtu9r2IRsXtTY2867465yzjIw/89jk/v72ioRyaMxVI+0knkLyyyGo9JO6kUqbwRJdbAnJ0zGDmxQrSoqDCeZeGgFExr4gp/0CWJoIDZDxN4FjTpw1iCHeUDi0rhyiMlY8MrRas4IkFC0YyOdtLfi9wzLrzAnxW583xsHFU7jPZrjhJKc0GoqGP21vAPiziQ3YQoEraS9oQHMdZjKQWAqMmoMOpohzsd/YeUmyuyNrcRM25WzJ9BpL1tn7MH8MhvVkE/3IC9SgtNQ1uKDUNbvMyCT0aac4ulZsWx5z4cDA1WD/1a4eBtiHxo5fmhl2NzvPW9s74Pfxo70+Z8JyHDnoQelb9a6L23DGKt/4P22OTp/b9s9o5660LyNX5uIrp93yXUPMBp/s9uhRzSze/ud96xYe93svjU+njkq/fuOy246sJP4UxxWsLmZeV3BJmNsa0WomIsniXjSoeUhdpAEfuwJ0S83kfrZqdwu65+ZzfTLJt2EzYaJlBxMNvwap6lYiCCxn8kp657oIUlM7tPFVVkLlS5muE26mOUb0S4MUYK9aO+cPeftvL2uQYokY+ii3h5/LJPQxTpZqiNs4CffOL/n63slQ1sjSiRUqRx6/3CPXz/528aUOiHnCcP4hxrvw3Kqklo9YycaknLHM7b+BuhmR8VCuYOQX6omxdJStpiazbOlM8kvNYrGkpMYdxEulEJnpAmOs55NH9CBpjqNwt1Bmg53or21DdIVS65avLi7ayxRFm2nR9rien6SzTWwCfbHHUuWXD22GNZ+5qC0jq7Ea4cc5x4qXw3rrZHXa0VKhQjvlTJsTMpcxeKR0kp4FnA9q2CE94oQTOaN9mKhCPofoDjs5UlQ4dVhYsrgxJrdCGfXaghZmnOXjTiLfFpk5qm1dd3ZRJ/DHHCl4ig1G92Zjjywbue9aNbijq7x8a7u83/c2N0R99YGtOWWWSPMU128mj+99pvLZs3dovqvzsVLujoWj8kYNIv1dwjrb4RapeivS9Zfp6cG9LdE6b3Nm5GSl7Fiy1nLC8wJMYip1CbzQXDmHcEIFiAThEsGBKhJQi8VJZqg4KCr8CsFh0xRbkhuQyqGTbYsNNmT2JFEjtmlDF2XQDsQxTkM5oXoiWX7DqJr7A4pOp9/nvf3JZhLWao5y/CnDyGai5dZdaV6ntePf2Py36twaBis6EKGxPv94WK9QdbRIcqEreS0hpZPb1AkmItaWVRJ06dVUrQoVcnkFBkW8Gwpa5jPIDqRQrscFbUMk2jLsdjQMfyp8RaPO6HURtXbsJ0eABtNPt+blus/BY+vIdsPB4bBRADIaCNWQogmZ2yZWWRxPbLF6CHr6xmA9fXM3DI9RoKQE5iGRBM8kUjj1zQl4LIJyn0JOePuwC9wEFk5vPgFQRLyBnH0C+cJxUQTdGwYsHY6gti4WLBxaQMplnL23KdLY3LzWdHIALAmaYBsJtwgH+iAVMCU9QmffSvREafpeAfa03TTimXbY8P7xq68zWbLSf5GmxUlc6lWS000JUUzMZRsrm+xhSKphLa+jR5pT2j4g+Ojc5etmHP3XknN0LmKSjqRYCorGhka/WbRHL6cL5n8bS4NCbqGJrgTN8W1+A7e/rI+pLHe92B51E7Z7cpiNS4Cek/MtU+GrdNSiBIphGQpKHChFqQQmimFkFKWU0+V5SqhMWK6JgcmwOJR7LbvnHbb+mmWfsp0p7HppsNdaE/uhvErb7PaGqVIIkpf1NftjxPbTY90xnT8wSXzZAY1VlQCL9I59JvDfV5j0XrL8durmA+lVAXUpciJmXJWhrNw2AcJlQTl6THN0yd2yUEfOJsrahnArmedu8WQnCKnAajg9NlaHEch1QsvIfoM9dL3pTMo3L9orKdnrL3HjX78I2SXfvezN6XfIevRXwlHfvvxi/O/R85mSKvZMF6bC3vZr1Byb2cVQdj5smm0nS9BsokCO43DJcEhQztsoLAZFrVQrLITE2WHph2G2GTGJdtkOG9jVMsNd347GGUzweJVWN2NNp2MY88WSjFmknsqUPH4iqzWib4ITUewWPhLlzz6o1881rVyAHUunvwVus4+mhibP3tud5upUrpLV9vGfNhep+NvGhuUpDffkd5P9kv/vm6QidIbcl1Hjr/ydI8lWgo8GME8aMc8qKCqoQZnAx44SShIRCRoUqIPAzsDDyesBX2xl0GsxPKqJPIS3EnA6HktwQ3aMswDEzlqZzIoDQwmOBnB2HJQryJ9OD4nwHizemYokk3NaCKRAxEjjkPIhh755OXBbUP3elGkZ/I/ltej1ksGHv4JCj690TvY+hw6+q/Ik+jccmpha21pMslllyF7awNSfyjt2E4bBxQ/1IPB7FZMpw9qAFP2uUrZiJWk43pqI8qpcKrSohyewnvSrYZKf95N9qTbB3vSPdNyg6DdLKn6UmIlUtLPf7/hZBRB4kiyz3o6arGJakVfGdg53L+kLxfKuH2Vif7MEtkStSU1/CNr5491N8+uqolvGZauWdakgv6T3Jn36F9hepKQFalVakUsNBCC1Owp0QsRVIqgbypZqCZIopCcqglVy8MhwuT+RGVYg3F3sWeMx3+vFAXEBggik2BB4lh+Gu4oqzOavIFaQN8Ok2ghfXdsLaaXzwlebgKVVULxUTCCXScVIdPUYZ5zVoMstunTrKQYlGvsfLNn/viFd187cV3vWNJgsZbEU9YaX/e8ptlL1t255/H9tfvq3EaDrdyJhqSP+lvqR2Mdt6/ecxjHLzbpV5193o6utaPR9ls2XPeYy1xW6VP6AX5DH2L/hPV8o3yyoFAmp5BI8kMrB21UMq8mqqtmQfLYMtlPiDoseVUyryP7Wgfn+eykcc8OR7HIgUTY16wFGKEtw5dGTh4mgEgiBFo6yImsGWmDUJrjV31tSer48WDE1+BJtFy/5sLLmb70ggf3So+PTT7ckqlrsu288JIV9E3KmTm8Rx/AO3QrlXeBrCtInFmFJWdWu0oIiswjJPd3gIkqk/ep9wQOhE7mvcQ6eUlpywhHCiCeNsKWNRa3LNmnjJd0BFPY0kKZx1vM5Cipqhm5AjidohBSh6LoimRLbCCJkoPoDr7zylUXti/aObzra7Sf2cxPjg13hZJ0EyDEyXhHkokbSi32fXMa77oGfdIek30l9hE/J/TF5R4bmRYLoWWC0ZhtAbmJClaJV+dUml3lEpT/UwUQUtxh6mgNVjj0kZorZUJe0wO3WjEOiNdFXNLz6Q+NrSlG68Cr4xFNq6x2LiatQ5ta3UEXw/Pqms7T79GjkevWo3K9fK79zHuqe/D60tRyKp8E/telyBJFe41c5ykwtspwLVllBo7wiS7MXRdpOHOBby53kU40HF6JWcxorKkY7fD1cs4/CQC2qj43s8Ljpc11dLpOFS5WfGz2TPYsCktJjacVPRvx84OJ62gVU4oBpctSgX6eC6dbNb30opocKq8J2aXX4j/+hJd+XlsNFKudlZ6dT+1FCzWmUibsD5caGCDaavc8+a9Vx1T/VlXtKuH5klDu9Nv05slb6Q/X1FFKLuQtzIM2qPUQHrhTYgqrnctbD3hmhsTyjNlGyh/tvNhBBJaC9qDwWRUsDz2DIHU5QjKuI5A9JB9gt1qKWC/bRmcxsX70UUO0i7EEuBrfkGcAjSzI/hBFLGHJvTioM3PdJVbU1B/LSE80VDQuKwm2W89QXtBBnjFZXCtUzqS9MTQ/6irX8Lyh67SUduswZAk4c2aHa1Wpi+7baqu04xiUMQWu0tfPdaGb6hxyDC6tZt7AtGeoKyiSZhYiKbECYpiaKNAOtyARkoIDHzwYlgBAiIbpcI5MfYG2XB2pwQvqZLEagSEDmeKig/NhTAMBO9iIFDzVwTpSeK/g8JYkeYuzYrd2xGCGyJ5FPm5w9g4wyCeaov2NDZ00bS3z9zuq/+haxWodmIveIZ33lv2WGOyIWKX0Vqa7qm39wk2nG/uzUbNOrdZbx4bW06M9b5br1TyvUkf17jnSAbS3sVreIbXtp9+9+frqnkVTPXLMfMwfK7VQ8a0knCUElpmhOwr2Co3v0STaoUle1sYL2hPK5AvRDuV1reI+y+TikVhKK9WwVBpVG5hivQhBEzeTQm8tunhB0mdMGejfSonc3osbYracL8HEdZWZgRbkbjj9FhPtbZkvPUdsjHSILqiuoNzQbQ9BZ0HDUO1YFHa+YCNXpObvOCEwSRgPBSdysb83k8jFrCFdsXJtucSGJaVyTCE37NdJC5fcYUNAjBqjN2x9do8h5skPti+nV9xw43KaXrr9D08jNEbr3Us3oXUPXllp37JNemz3Rodrwx7psUsvttnonQ+iCzcuhfW+Kr2EdqjWUwy2imcdq5d7DIqtBsqJfy7FvSpIL6kf/dsi/LfbMa1/KdJKynblMq1uvkBN08qcwFEGOH2g1ZTMM4RWplye0UFoNYBWmpxTtMrJM+IJIHvsgZKGBlMe3r59Kb3qhptWoOWX/v4pBo3tBtqP/UE6Zt98KVq4e6PLtX43Wrhts61y5yHp4Kalbu/SjdLXH7qSJvVGtJR5nz5I2agchaNkqBlhNDZRwphLSIK4Qj50KI9VMBvkTqcSTqRKczBTQz5sKweKMxqcCJjoS1w2kth+0Y5ob9eW/g29yfHePStiLX704dhIoD4zvnL5oCfUG0wUzx+uo2nmA0pHOan5FExjKc5GcMEh9OKANJU8II2zleLlGWXMZOQhdVssgxpLyQl/gePEEqgf2c6e3yIfXiPNntOzOx5ffcvyNb19q+lgbY2tyVITC8LENKavb+XKgd41a043tG4/8KPnnv3xge3ty9avJ+vdLv2GeYi9j5wMmiN3RUAD2VQlJKKcBUInyLwjiEGqIRh0e0nLmEMeFhXhjlA6bH4D8oQSoQRzM2PEQRYc+fIg0k/MKCN5SGMH4zeHwmaL3SxnnLcj3WvpzkVzl3e3DDRnAo9EBlMdy1PB8Se2xxuXjl44yt/b9r1kaM6S36AnkNf4sfTH4PxL+sJSKuJLtQW3LS+X/or8ER698tA1tFsd5I/KsgBM8JpqnOqi5qBSKt8EtCVIajnfARamD1uTvg5Q2L4GrTz5AAKVvA/GHlA+7HQLzOymhjJygjWON0yprslcBpYbGmYg/RHGHmqYbKluWYbdpBtGDGDXbSDtMgYYVxMwCjFIW6vkfaLihVmpQkxOzMVU8LJYhLyMjJiCGQtz8W84lX+E0eo7+mYDWwOc0JoTYqZ8uJaH8wguTjT7iGJMVCYamuTZMX2caYJq7Z4FA5OY2WBkeNKGBbVIXymJ5osH5OsQj/zpFDkZOWPUVDqbkStUJntKTmprZLSteAO59Cifoc7CK9MbL4y1ImddySuHnPP6V9x708OD7dl+hkV10VRbwv3+26zRfnn/svPt8VJfVfvOjnXzkxu6F1zQ0ZrKddsGBhtabl60vLxh9V7b1Q/3LftOeuArF3UN96XVi2LJvlyV9MHVV/tnDS7rj7fOu+Ka+Ir0YGfLWF8s0znYkSO50Z9TO9ko+waOv2uoS6l8CMnTKyphdh0PkXilUutiZnZi4UirYJo+4+VmYP6BiqT9J0r0difw22QSyy1Th/Lt2IAJIRybqMot8KzOJJbowaaFs1A5CWftwNOsnZwy19g1YVB5jXnG4K7IK4ODr2x/Yes1X730he2v1FTDgx17du144egd69cdvGP9xjs+fHn9tVdd+vLmFwcGXtz8cvfmnuvXvbz95dmzX6YjW+67f8O2+++R+wf2UxQ7qhrCWPIu+VybGGJINyPpH+EUAGU0w8GOaCyIyiBhWoiSGRmCJ1moT8A9HHOkUnD2FO5WyqgzckKIJ8UqqAkm81XklEyVh7Rr44sA3iORKnKIBs6C1Cfl0zQEjVbBIVxGRzpQ6hNMEaGZ7eaZgCJl9WmsPvzfVJSe9uH/wlgNMTTbQS9e1DZ+s/sDU8tKdF+qySK98470SQkySH9iZl0xuf7KYUb6EzLY/+v70ifu2arKVIqprAo8Kb2fQ2/4/QmfOpVSVwcm311tv2b1qvXdmlRK07tu1eptkdU0lanH9mC/9AbKqaLkvLSfgrPRgKjYpOIIMaIqukTtlEtk8L/9giBIb9CfTKqZo/S3JsfIWWjpY2Yf9q2zqMXUx5RcYnUCnCslVTdo6ON5sR3faefhTnsa34nw4giW1BgvMpCpW0IsxyD5yImSQWq6pbIFarfFSDvJ5z1JUiPM4vcYNIrzsPYG5L+KBebhv+qUX9jJg1GBqwqwNvKhpnwFyUNUwEmQceizH8RWoA8wYYeOKVVVRfj2nt4xUOlOkzCSEw3zlMkukXas9rG+XE4cG8FXAaiKMXAAUnBi3a+aOmNtnzFj4awyIok4lAmBxfBcGUulViCo3OLJZJWxbMXJBOpduy8vr7hyzqNXb39iOBWbk3V3RWdf8OYPF0WGqpaet3npU7fsEmdtHHZVe0cb76+Kbdm8a7jizsSSZefDDK3kC+fzbfTQ5buZTVsGLr1tx3nJOYOReNRexjmGWtddd819nSsuaXFUoOHrz9t662XzMrO74o6QxayrrD5Q1+S/YPGW1cM35QZGRlJdiSjmaLvsS2g2TR9W5ch8wTQlaHnBSqYKGDG3y5PKFRkoCgOQ5HmBerkwBn2f1NnD/oIzrumhRGb2YDY1iA7Prs/MmZ1JD7DHUsNzGjOz5jSmhoaz6cEhpY565heqo2QGaxXVQX1LOVUuV0/lk+RuFVWD/VRbtozFXquNjD8qBOrhkRggdWeEtQS0TkYacAjUh7WpQa6iNhjBweNXFfUoRppWiwC7C9MTb+BMR8usbjaQbQOliXFiUzOZG5mF8+AlXKWPitU0NSseKzR9CmD6EEDWYsKyD5jSDTQIm7YXczpZ7HGgY6AYoMA8OcyhnmOo43svoo4nNzwjnbrzOemlJ2++4/Tt9yL6jjvO3HXwzB27Tr8wvj2oi6jDYfu+ZZfNGrpuz+zdHb33rnvhA/rQ99HA8Wekp185KH307MZnUf9LD0u/ffgQqvjWN1HFww9Jv3lZ/F1Qz3+8YuPomPDtQltvZ3vTW1jeLOOml6tWUzGqgXqYytuLJSaNnYy0gf1dywsBYkAT4FSSQgpjPYa6DdQgTXgclxNjljjsbJ28G3UWUocz4L+PG+GMIcQK8pwEMQMxHJzCrc2JSahYa+w50h0TCBMO18KQTnwppLi8k8I7MIeXpAy9gXmIX7pxiHjvbFrN3vp6PB2oN9rT0XD8xu2X32ArUelN/q5YfUKXuSDXNfqK3xWrvZN5aPaS9EguUWHWGx1mbzga7B09f0j6vlelrwx6gvFYaNYSfzwl1GG+5agB5kWmHeNwnkyvAGhhtZTTxBJArzaPmDQCoA2GgS5HyhM8nUMH9TW2ivWrXFnnvbYyT6m+xILuDlSWVaxnK+vs7qzzPjvnsJegl0rQrNIqW92tu4ND3uNNHlOprgQN4ZuuclvygNrb5MX3n815TNYSObZsp37DDjBGSoWjb2VKBjR7KRPgSJpOTRrnZOufZ5liVhbym8qUNz/Xzmqvow/sm/w5Oiy/7//5XDX2rD09hCOGdz97V/uqYR8Ls1MFH0NdRLxEoXsO2dvdzMlCaj55OkFSKsUREtPbPDI9QmJOMt9DfHvPELh0Up2L+KDyRqpz5+FXZuRXZs7a/wuxfp7Xw5kKeP93sLDDM5zQmBMq5ZEQlFjtw9rYnBO6OTHcgfV0jqmADQLVCC+dz4mxTO7LmANzuo1tSHMtiJzgIwkLKC+ReCzst7oQdK8yxFtE0RfZhrddNqdaq1U7bS60b93uQ9tndT1U2ZCM5AbJvfG+ls6dA19sJSZ/H6SRFq+jAkkVNrtGi+jgRWO3dD2yrsvevey8JT8t3kQ7xxc+AOcF2MX0cvbDmbrhknXDdbZulJylG0O0hV18112yz9nJhOlj2AbpKGtxAiic74eZLgbIzNuKUzmVWSocfkfVdC6Eg7m0DF1CMoQWGPGlUgYETUWQmWl8uvPRDw8fvnL74dHL5y28/Ip5C9i+yw8fvvwr3/zWj4U9uxeN7YF5M2Se4ruYpnJq3dnzZuDctDxyBqrtLIlpWGzkigOmNbDJjLxggD6e4gzikmS+jPSoQoILqpUG0nhmgCQzW+xYzcpza6anLML8muKkxU2CQFcJ6BFpXJB+jTyY72o6Quy2ixpV8hYa0m6a15BP0pRCZoKH7UUmw7nJvlfCbiiIcqySv7Yq3ccaboLlHE75MNT07Dd/sRRTjlIw006jfue2sY5Ut49P3bBi/bU9I98/Nqu52uJrpSPuf37t/M6xRPOey65c0X3F4DGk99dJYD/0tJNejNdaAx0pTlre9VHMmBAvliijKUqLxysFv1HwAKwzKckWHsAiRJAmz1SlDIKZUpMC4KwlMBGLrqj0+IsTscjYTwVnzZhjV5yUo2iFfiTGx3y1FU29l926dKi/pa47FF730potfNuhXz98wUb6ukaHylbjsfW3LNzEWx39LbmuWKPh6ILhhq7q9ruuPpLDtBVYP31rsYeX+vweXlT8fFUBmZON0bQnIb3H+lFzY6KmutZDZhQNSytJ/SJCXSb3a0L9QieX3Ej7pkkWswqRISyk/YM9QWbgQccYROSCRoZk5RiSRSFIh26dKuxPRb0GXzk9ZBKbUIFZZ4I+R6sTXCwEzxaZe5k0JxcyssXf1mmnGrYV3e6wJY7sWBVGkT1ebbV1zW+ftaKKX9S+eWmJ293Z0t4jnfbN/4fb6A8mD3TNy9I/nYzXZPSJlnAq08T3dS9bVTs4MkL2v166kXXjOA96Hc9T9r+ROSmqXMlk3kiclBGABJdU+hwLFQr8l4uqzqTSCwj2Hw7plMk4o3oKjypnJTRWvLHgPzJuH4NxSESq9T97nx6rUw8G6GdXH58zXvfUkfVb+2c5Eswrrx9PsFpfs2Xok5z6lr9tYfYzdtcGZHngeIR+y1xXOwQzpdCf0ONMH6UF+zeVBZtKhunOGhRaOgMgz5wTSt+nDPNH1M3SID0fc8WOvbncgWwjb5pUULfqxMyB/GYVlMmN5HsFoBObgglSIjIT85eVAw8MM8N4304B8Zt9vfXbEzGX07ZwfqPXP++Cmy4flzbPco36QyXGF/fqZneNLlfwBB2mo2TmaJ98XgCHAwUdgX6CBsvCRAaLsUoX/jlneJrPNcMzNT3Dsx0N2BsWSZXLmngzeyyyb/KC/tpIJD6Ijo/KviGK8ekVKphta4NT5WQ6tJWhjrNkMeUKDp2a22yeGmYOrcugBBXn6I4oDpA7x+TxanX0W3u++uijV+86/BL249HIJVG2ffejj+ze+8jhS6/ZeOG1d2/eAuvqwvjvNYz/nNC9Ym6AfCqyyqOEcWSILSX+P/bjwXM8k4EnumwGcwTdL12krrKX29azFbyd0evY6vp70X7y1APSOvkppqK+QmVvtt/L+F16nzShlZ5SO8psiVvU3hYPW65nE83H2s5+RuVp9Wpco44jMvYaOPMb1btEjlbKT4Wo71H5atAsU0qWqjlVsAVMdBnUqQo2OePnTeYD5HxwwKmNFrQ68rQmVdAqHA9/oewFlvQ3CdVT82iqknk3aXRyk0Yn0hMQhDpfjaIlIm3ChijIidYAnCQw5c1OC/Hq2gBWIXtOpGG8A4m1/k6T4JBGMA0jnEkJ2epPB33cAOovqpfpNebSradvRk+0XHnb8LrR0ePSh8j0KZU7ZYK58a9et+jB/PjkR9c88cQ1aClGAfSZ36j9Cv9S0DMG0zDl9o8Y8a9TbPw0nwoBN9woBGSj7Q4UOyLI/P0vwUAHKrb4khH800xycE+aLVabLxCNAeoMm4QU5lPMRvgkaLkJRzSRhOyoG1gWxqwLQFuQMvv0s5j3907fKnt9Gg3Y0oukimXNvPkZwki65Z3bx9pT/VV86qaV66/tnvf04wQItJyTp5XuX75+fseiRG739itX9Fw29IROQQegn61YP9/A/I1QcaqJaqXepvI5+YQcQQtCNKUAhkJdc60T87chVaiT1TSTzDfXAcOak1hNwyXwtBgGTNFGMIWcPoLE9BdhCshKt2B1zSWL8+iyyXxDCzzdkMFyaYESZUdLHVbXdgV95H3VMKpPbAnI4UADl48mY0Rhw82ky4Ngk6MEmwRavyQ4sSomSUtkkjFnZ+hz6xRi2S4jlh4ZscQa7wbEgqLMdtDxQxe9M+ei0dFnpT8h7nNQTKe3pO3Oq47kJm+X1f4BZJhWe2zjrpA2MfuYD8g005sp6CkwqU7mTdAXTZncJPOnzEVU5poC5JgIlVMlUTFWclIol78gQad82UwSOnKt+EaVzHsr5FgpKzThwajTECV/qYwaLDSrJ4gk74+QGkDMJJhg9qlpqrXNLs85TCmJN6VJtyF8dpJupom/4qIbl/LNNN1+1tBDmIb40eqBvpVQT+pbdzMMPXQ7QwM7x3fP3X193O/wuaPe5r6FXXsePsIG+lau6u9dswbbBDITT9NMZuLF/htT8eI8DOL68lPxStH0ya8vGJD3RGOoOUEOhkUDXzAsj6kKprPSK4KLp/4/pWUaAX8BLRFkSjRF096U9N4XkEKXoOZsfY2/xitM0xLBtAQxIvs8WkJn0RLhIajAtMDxkZovpMWcMvvDms8fWjjrr0/99ZJ3fr3w82cXql5Dy6VDL7982khmGJL1qz/A62+kmqGH4jPXn5uxfiHNw/eWOEin8kRNdbokWuDlx15ykFjwnig0KmWhZN7bWGxyIqdJGr1Q+CF2S5UjpuyLyAf/4JXbLaFg5q+GAQZgxT6fI2OuS8bbR0f9FeZwwrLQf8nC1p5cT401lFVHv4BJf9q7M+znSuKZq690Od2GVPTUbzC7sO+Q+fUOOTMQp3LUVZ/DsehMjtXwQjYFTIPMdgIzqYn0gEEffZB8740QS4oNOIRqhvmPmEMFu8cdjYOzreMm1KpyMlSkwZTnbDJGUcGg1vgXsm6mdfIxMw3U5zBuGHLnszLpQS/m0w9nJeX0+ecwTL08OWdOY3pw+JSAt8j9DXPk9LrCL81mZa9nqVu/5G4XojykgCFqz/CFoDI/rZEXqk8U6mTFqpO/halmekBGXTUxDEKK69CqVZzNUBWsjQLbakyiidQcFdMhZuqVoxefxT6lxaloEOW5yTPSOp/BvGaPbE9WfPX8sV278xh71CX7++v5c7HurkX2KaPy9oLde8YWXbn72qV9PXyiX45F3BSluQ7HqT3UAPU6lU8rnaR12Cmmi/N4st0Qs0IEa4cGU+CjgYQreTtpILSbME5p6U0by8i3DqUwqHHWwiMy689ZS84TVQNAnMULTSeEviRMCRYcyXxTlJwcwFBFOT8QncLXUyiHBD5KlgdODwRhHoK9DjjdUodVOBhINcCAW9EOXcWl/QPTo6fQVIvZjAGHcN4cRkKGZ4zcUkbXwYRbmxdZzfj17qrqVCqNHitlmobWsB8nLEHvAukPo42d/X2+gNUYj5f7Z609v3XJ6e0Ni/Tx0VO3bepC0r7XvNm51RvQaHlCbWhesJTRm0uWO4M+dVTauHxZeF1FUDKqta6qgZGBybGVWwadKqmiI3Z5dn9MGkuoey9Bl0jXtXojAS2boAW6D+agSnvJHNRu+I6xEEinI3WOUahCghezABF7Zk5Exfo6Q5HPno/ai1mZs2Mkp6qJJFLtHYoRsISiLrgsNwmaqaGp2QQHWFwIcYVItE7m9v9gkCp8gU11eDpqD2ftM8J5f4D6ohmr2xY+JFiN4ZALAvwLVvt0vTXb6qP2alu/WvqD9B36voOo9LNnr+5s3UQPazub+uf52llLr9enNux3o6vlfUBmm2K8EKEaqMepfIRMdvgy0009kS+Y3JmeObnzvzWuE2pKXkh01cZJLWmCq65PkF4RMvM0XPNZg05t55hyOgNz/d3A0wcP2M+ednr6uUxNSwKZtkjvxQLnGn2KrvrU6FP1u6GGIvr6ND/z/4/xU6hVuEmGF4l6B/nOsv8RV7XT6O+LuTpZjcyJXDTjSWIE+GWYinHUNA4s8jSCeVpPPfV/laeJ/zFPk1M6Wk90tMBVR2O8fDpAqCPfhRH/HyqsjEe/hLLu/8uxj7e9++svy1ICTSl5trbKgnFWhEpTndTv/y9yFA5etKcKcRmJ5ZLkHPRnc1iohzR3LYZptbxYj3+dg+kTpY4WQ1T+kj5ebJG/YGOGIMhRaagyx1O5Ivbg4IgdTADItef+D6zGORofvoxUivgOPTIF7r6UJSnCvHQR4Snfo0N/iO2JGaO8uZ8z/dX7paa/VkEpgZVn1Zx7CuwMc/mpgbCTl2Rrmqdt499Ph51hCs9e9+gXrRtm7X7ppXs+a+kzbNKnly7hEBQbIG8CDNDfr1yxN3Ldprj2CF67g5r3OWt3fimeu5SFw1fe5nKfyXd513964XM+euqvW3797mcsWtnRsKfJmvGeNlNeKkpd/pmrhuphJAWBAOxQf3Faw99TMeEoZ0ui8vwQHg62TlSRGyGlo5aFESJ2N95pIUjy+CO5z1Wpc+ylv6N1auMcnt4451Czc+4TpzJX3kLVUFcqc0ArYHoTJReg5APXVSrlQs2cLCDKUFIGs8ugJAzBEIzhjvCCGb5Lj3ydTSCZt5KvE7PCEAEzsXhmZSgM9DuXak/KmQYE/eKlbjkhm5oxhz6C5JmvU9Poafmoacrqdx6FifQr0VJ0k3SJ9MzkdQvm0qgP5tLX53767PwK3Xvv0QeWoUenJtO/Jl2TQB096OdSHAbU//UAqkUD/rI6qWuZgj1gVpz6AxzbZKjjX2L6K3T/+OTMQiQ5EfLBV+3G5cee4mjjLzMa1nNW88UXDoqFYx+lGTj846uFhOB/d1iskrGw/V3C4jOmyG53bB3vGh1JOSP15oX+rQs6Ols6opaaDPsF42XlREWlnKdwlaeisM/IvFls12DebM30t/edNXE2cq6Js7XKxNkJ1uAJEDD7pYfOzhgY9bnzZxPZmsYGOWkY/OJZtIxhGrn+/0TXtMH+XLqenE4gfjFZ6KOzcogyXRFCV+Az6Aqei67QDLp8/z26nIjY8s+lifvrUx9te+fXX4oe2cwrtOD9zZEdvvMctHzxjp4m1FM6c9cWyYbNWYE351GDlXX6InF52i6OHP4b9HOftUE/lyOuS8Y7/3dvVx7dZnXlv0WWLVu2JWvzIlm2tUu2vviTJVm2ZTve4kUxJjEmxCYkadIENwGyMBAChDQnp5NSCpQpMAwESNuUocBIsgiQ0g4zQGmbtnQ5Q0uXwwTaKeG005mWQzuTRJl37/s+SbblLYcpf2BJliO9373vvfvuu/f3k2bp1bZ9E/1t7VG/3h1WLA0RZ507URUSVu9I/tzC7M6HligAp1oj3QvrRakGMgMQbYqAVAwQwgjkoZAFCg5VHjv4h6Gs5jLmM8165e6Hi6Ljws1x1xB7ZLiZ7o3LwOUeulNmS3JZgsM9CpuijylhGJ0K6CdNKrZQxe5mN6VP3M5ex24+mH4C/5d+ki0me9OWg+nH8X/pE3ewW9KP0zm1u+BswRsksnMzIrOR9hUnGmVknVIHNkHSqsKYXpDIqKGp2srQa01BO6Ogunc058IknI3aiheY4vLCalODmCNQAT3ykgAPggm0akhj5NAbTehZnA5yLRWwVRAQB76/4+R1h7YfHxqq2zRNkHxk19PX3bv9mWuusQXYrbpqrjN064ZnXhoPHLru2eeNFu6J77NrTvkCX38/emXr1773SPrPp6cbW35wPnbr5F2f3fPQRn5gy/r0Vy+yW9azfWzkwFOb5b327YJ7yHrpIggcW5qRNvAxMNICekV2vNKIl2lnrD4/VRFcOTltbk5kMZ5a8j43vYb6daN9maS17Js5CZHZOH36r4cTMPcmrW4/7TReMUCOnPTGYgBxFsxsBMnB4t1l4vNCzlEjg4+H4ONfjh8JHwM+q+b4kcfnv0w/ckipikV9aPJPL/1577tnlw2PfKjhKTZkDQff6WSeXQoduBpbFUiF6HLuw0bsRdGacRfZyYnGTxb2IrzvQLK2CIGwZAkIu+FCBF3M1xzB4vZ4yeXPxPlbweKIXivvBScHxdBoLBRcs9y5OSptCKHs0YnqERQcI3PUywSZTUuz+4aWYPcNS+y+qQI15wtS11ohv2/O/FsO1S8XZfVyhLgi2t8XZuUZZV0GqJE4lKvLYJdkRFBDpFRMmZ1MCVDzF5xL6QV8iKpsIoozgAZnhZP8hQXlGSwOFVw/JJWWXIUGC4rEwn0F+B2TMEsKDYITd8c5Cg0glGIIyCT9hoVlGo53dbpV3FG2jNXNXBn/oyzWML1vnlhDc5Gmqa2j8qVTr32quYa7SVZsYE9Iig1wB9N86bcK4HATmb+T9PdqyR4vw0K7yf20X8flrCySq3UCVBIHtMCzCjgiNu0gv6oPkn5AB+bD46HPKa3ZPpH4TFGlpraa5voZbBOJO7VJhQFoSaEwSgOXNYmCkuwpUeYHkIQeci5YaAmJK9jJSU0m2uZuB/f+C19772b3+NBtd4jbf3W8eazaZNKvaRk1hFra2kw9I23RZlXTGj725Jvxo4fHq+u1tg7/5hPP/NHaV6p54I10j66c72c923fce8fYyPmdNPeCXL0FD5IVPML0MiezbL3RZbL10surNmDrbcvP1tumgTVHZuvtl9h6E43QKdumBVWC7gryT4YiyNqbdHqCkVze3mgub+/qy+HtzTmD6lZC4Xs87GoNSknDz6yAzVfx75QN2Syc/2WW2Hcu1l/562Edb0SkBQnpCEV6xukR6RL38UGdk8fkV8SWzGEleqhuVfq90RVAzX8bq9brvdb4hZ/Ox/oowTrIdDFfzWIdWSbW3Yh1CLAO5cc6RAv1JKxXS1gnG4UgFuORg+iMqmoVam1YtCmnp1kMzEI7kot29HLQlg7rK3LqPR+9+NGes2d7Vwby1vTx117LRTiL8SDBeJBZx7yVxTi2LIzj/QJwgteQgKddnGkV+wnKXfS5QLbq9WiAITDAUF4DzAj4+iDNAwxpoIlfska8Q0yMg0EGqfMPaeP9kfgVFc+rqsSW1b0ZkwTbu2aZJJZrkrHLWmsWLElakZUmqvdcu3rdmMNU4YXE396rO1e397r1rlbFwZUY7k+HD7hsFYWN4SMHzVW15S3eC89kTKiQ7Bch9mtj+pgx5t+yFuxcngVbhfgoErtD1DpIjHalEBfeSgSJBYKaeDtslgx0hAiJdsxAxI1Q/Tp/KgU1MH9k4/XD342QObUOTCjAnBJbYU71B4GvvKoTHo+sJvPL6RkcnWXAzlwD9lz2ZiEXRmVMlvvqMsy3Q+4x/qZkrfflzMey9o9rpXbkC7fK1uJ3BEalqFe221lpHxll/rDSnSQeFkAQG+4N1uIcxCKqK8B2qX46nfo18bYc88Geo+4XijA9DqXLRiGPGftx90kUDItoyFSQXnOOSWYEUozufm3FKTILo+E1a2EaBtFgFqimX2QfSqxdQyzfEhSwTuiyLDrHoBXZkq1l2PPnhyY23HHH5IbbRiR7GnqF5oGBZv+yzDlz1Z13Jm+/88KajDXf39TfK4hryBq67tJ7BYf4FLFkDzPMvMkkw2C6jgKmnkDbDI+91KTIYWUNgCXJTJONqVf5Ur3OcFUp1BgleiGEHVk0SNDSIKGLzjYXsW4vqor2kZO3g5Lsx+SoIRxJdLXJegoubcLcQn72kYOjFw+ODlom4PRC21uTv6UN1tJ4rzZeALZDBqw5lkJWAtlSlCAWXqvPped3upD2xKGXDOWop3++bk/Lc98YXN82ZDSU9dwW++HxrZ8OR24ZuyHeWK1Lc7tvHdkf8V3z8r3TR9rUT/3L/gNs/V5b0HF0mlOwxeGB0ejpw+sa+qMnJmIuq6HSaLO0tg9Edt8rhMPCzqmWXZuEZx7tXGP5293Dm0qeuuHJ+2oc7Jiw94Oee268G7QL0sOoXdAK+q559AriLgEy1aICeszjXpg2HrBEJL+KQVyARZDWyiE1rx5u4DzeCCQWX+C1tVZXUxAEKuJqrFq0axMqaExXwpGCSWi9QMRpF5YhdlDOLlC35VxABGHNozubrA1QqTW5vbZ0qP7mVY2WGuNw6mf5hRE2by3diX1ajiFFJfZtndSxNDZA3QAS65qYBsbHxPIoB3gU51I2qhxgK6CkR5JygA3VaxMqgKWyBvtulqMhkBvmLyUncHPY1S5iaO9znFhMWUAxKsfyF01UY2Du2IYvd2zY+biskeVG1UsKJZSyejHsC9YL6fc+udjI+BBt+PRZ4ukKOrTM2I6SsdUyrrx2c5CxWenYkK/UnRmbVcTLBmq32mXbTY5ilxrZxIcv/mXvu++MLTEoDFUzI4L9ko4pQsZkYxrJLL4/z6i8ZFR2Oip7wTlo7wwFgFQXAptVojyXYZR2Ma6ibTyJSpC5EBK1wHmOVB6JgKRHo6qEDtd6Eqc0YWsr76WpthltmcuBEcvyXTpTpS3hk/viQliNywHIqzJav5TJTvLCdkaKOC7OIG7sm1kiFO7Sj8j/FNhbXM0MMckSSKKo+XPxKjGpB+x0wH9QgxyaRuW5pBFLSIzVwKGJN+fl0ASuo9UkxnIt3pisauZzpusc7n6Bzk5M3Y9n2ftllSGz8L/vziXwlzUHYuR7ltPvmas5kKXrrpnL6D5PZAC/J0gLwHI7X1ggZzLmKgtcz1YEQ3TazRMXsGVmGuJJvhk3QeaYkjECB1whI1W4GESq1FEO39MEfWNU56Eko/NQgnzNJUBtWC7SltIS4kYsVyARQdGk9lw8Rz88/dG+d84qsl+XfCWcJ+d/NQ9I/tI3yffbitw7NQTTu2j/b6IUabSzCggqIe7IUPJYqXKhBvm15RJzqK+T5A7UKEo+ozRpinxyTKkkIYoZXwCmO1g5NEioqSKzpgH4ea2OSMZR5EkwZ2S5v+uRff767DhPzKP4OX/nPPOczji7xH2O2g9NUIsDzL0JO9ntyzlsVE2USbI+CR8Q9fnpTSGt/oPu0SoyEkG6KZwpLikrxy4DbUrFa81qeFxVkVJWFOp1uAb44A6WKaxSQohbxmsrUqpirU4v3R8yeH1I4iGyX7vCRkp2RqJduIcFGnVYKOS2vSjLv9J1hVvRsfcXm8/d/vmp5H2prS9OTdm6f//Wa+mLrEtf5RiN9lgGJib72TM/YivtfuVTN+7pvmVDdUA7MhXdFLt18uHvpX+Z/jpreO3+R329V7741Q9e/mfg9ANOfHLGdzGrodcgj5pJjohJZprFOwXgP4OjfIs40+zrJHFoK33uzhRWLiF1MuO2KbJcW0vqnkAtpY2cCRO+Tlp43SS0dlBeuWRZM00p1i5Kq6/Mx6nPLnien822zzbmsu2nk7Rux2XQwvm9Ye9E9+pId6PBGVLOI+LvEOez8CtG5YP7p2+Hgzut36G++SD2oNuYcYmZv1pm5q8Dj7TTXgIl9hJYJGZ+kHcwwdxSl9Mcq0rHR2hECe2MddV5mfrnpU3zkfZ/OZMj9TmO5OfvJ8uOtGxfuC9L5f9xjCeupqMxSqNJlFdEFh7PvNxkXhECW4YS4+yn8o+H9+FyDjcvF+/ODkgez1EyngrGymyQxmOUx4NqyHU4Hh0Zj44K1MJ44HZBh/aBluoqslyUlml5cF4YE9IqmI15xzQrA5hvPFK6r3/BoeA2kG8cg2QcDkZkDkvj8MjjANGoBiFVTudzpThjKG8gE9VMn6tFuYDCCTkDJxxBHXQOO+nFEYwY7kycICTSAJRmz6vKdeY6ecCGKhiw4MnvlEvk1/JhsHAy7Y4FYJmYmze7uDkDkELCh3LT2ZlVzGckhGpkhEB9wSDE/QEASSMtes0ICoaMmngFhI+onyHAmgYMIrUUmrgDfuUjGEGZfiUwRpQbyI7ogHouFV8D9VwJHwkqE27spwJdhoUm76w0loTMrEzWLE+JNQdjsH2eyoDyXzFBihlnofMK5KIgWGyUQeGuaZbTU8R/RhlB0aM4gbxFNUyYiZcKwApUpvDlcBhR4fQyialX8VZcIyaKi84BZbMlQ8+UW36rzXk8yn94cddkV+fktR1dk1Od0Sn4yWkSifTXO6/ZGO3YfC1/e+fUVGfHtRvRnwf5NxSjjIHMSuT+wWoq26x5SesDSfgKAvRQP0ciRKwPNDKoggpcpGXAf0l8tKQiXgCS5GX0N2bt80UlOqbSLZHxFsimoLU/aA9XoU3nZx16WvNDrCB13ruirOLV3VsPTN0/NZ6+9K+7pw9temjjGOviWKu+LdDdazHpu0ITAwr2zI9ZU/OZv6x/+fYfpz9o/QnLXHXqyk1N7G96wle9nu7tb0u9Z3oZeUpAd4CsqcDLf3gFygP+FSkPCJLyQNJsc0YiUpUd6Ed4VqxEkLPLLCxK8IWQmxwI9ORA0ORYWqCA/ZkziBuOX+Ju+atikjDbKCJNgIgkQroyTHJKCBbGhDWxFSKt3/n10pi8ksPulMXkKMHEA+vXsjHxrggTX9ZPPNRPknaHGx4BMq6VIxOmB5yFUdmO+927ywEEdz5YrygWEYIF3IScWjYakNZpDYDkEKzxUF7Snh+duAfWdIh3bULCQ34sBBhkFiA7CDcocLmY4G0AnhPIPHBHjCsjiaCKIAYXIpc11fI0MyyM5ieyXKnyVrCM6XeVzKaa2RQ4qsdA5mCInCMuV5GhZ1FFht7/P0WGnMhxReIM7INkisKttph+b+VCDQWfnDNnUfuqIIbc27L2lVXSu5L5UlEEy47Y5WpfeZbSviqk2lf1kvYV7Hz1We0ruzWv9pU2j/YVgZUKuilR+Ir19rFHffsnT76ZK3wV3vFUbHSg3YeqVwVPRBvJWfy1DbH0xR/Pkr06yO557aU+fzXMUfSfCPGfHhJfvHpZHgR3+rFAqo3O1wERr7wW9qiZcDEwyEThmKpB9xoiyMBlVphSxABVXQuIm86U1rZ108uPGW2DgB43VDHj9vhpru/j9MUFJ/FKHPPLmXn9ZTlBchn+eX4eazLH9Fz6qPD1gilip2HmFSbpZ2hRNcrPJKJwCyn3aCK93hBcpKiyPZoNIi/1aDZgx1IDMHQZGrCPyQxrAL3dCqvOxcPUJjZsz4T8gJWsqGZRpvSundVpCXdavWHixKt4EdZSqw3kDEnskihRI10GkyARZkXS1xiG3cmgjTPg6RqmXrRy7Wx9Rvoqw0XAzuIiIO5uq3M5QYiZkipBgZsWL2TqetjbWdF3v2uzguPbWowd0cn/6BYig93EN8qamky3HY9s+MktwZGW0PiFJ+/va6tNf3DyhgPsRKPNfXhbz1h1pbbc6NmT/jx3nI2wR4s4ZXrXgf3uiNGaVnNFNfY1V/Vd3Jg6pEoXtzk3e3dNpzcqFccm2ZrPH7vYNbja3FB710Pc8K6t1s7MvUzBET5Fzi0iE2WOSHtdAzJbQTIcE15uKTSOqwJ42msXUwGNGSwTkCitmAxDiY9mZeIBEfmofA5YgRsIhhXahBJFKwxuKlqh0SaZyirMg1fEHXDZRXazTKJLvg001VvYWdeBkq6cXIsK0XNBwM+5IJA2tDOXvrVuf2hw99obvuK31CjT6j37Brb2e7Y+e+fo7qaOw1d/639YW89EX1f3SCRazfnSLPmPb+04wp55i9U1BSOeqQ2hv9lpU/7jV8Kj1s/tamoJ+NnyC+nz3z18N9v3hduGnrpKH6wt2vuJnxLssNZU+Q7jxVXo0aWqTYFarRsZwmC5aSPLTe/i1adxl4YWGDbTTmEoRiWrD9zNJlw+qovcrJ3hCvwtUrO2OpKIgldX6MpptfgKa1UXam9cTuEquwkOjCOhliH2S1DdsDYUHFhRASsbozUNa1vFtaPhlpEYcD1yCht3EnPjPuAxjfPY4YjUXoVUS0fFFJIJXSS3LuJxS0qDcFKe2ybHduyl3yqGudcLBpkqJsBIFJY0S0HO0kbQgqHPGREViBm5ZxCSjZB6XjDbUGW+CVp+XEade5Vug20fJPj63XpnWJnN3UHywFoGubtc7mpmDif15f+umJ3mP+Ks5HcWmR3YRDmPTRLncZbouJj/HTv9/PP4d3p2uvB3y/w7feHPMn/3AHeGUxRMM3rgs+IxIS6ADF8p/JWBEs3SynMlqh8roWPSiBrwSJhWLrFdhk2wvbVnL6edDzyWMLxt1JapDavHJkcmb+KTR364vemhPbpKbqJ/ZPIuOt6T5PNN5PMNTKvEwKnDD4+Xi0jOrM58vlqJxQ5ALGWCz+d1GDrncG0WuiSBTvj4k/CZjz9rIl+hSFls6B1TvDF8zeGdh3+0zffgfvIduA3089MPcyY2zBjh86FvKK7BC5BSifqzNPP5pfj5pfD5KIDE66XPD2c/X0rdz/oCe3biNzCtHrt/ZJJ+gbG72uAbXE321mHuDP824u9hrpcsUBkA+lNXQLIDtsp585sCJBKA9q6G/qLGgMoZdumYZoCjBK/AW1tINTHlBrt0EZHHYI58Lw4/ltDnWPFGzvxYwvQLfKHnyqnYfLPugKdf3Je1Mse4yBhPoY19kKnBMVYFJEMnyx0eLONvzG9sGGEDGaGZ/qIBxbkbgNkTdZRghNY6JKnVAfuqObKgRzjyvuqa6yechQzrxsf/yfgLeAWGOc9zBuXnD++lnkTGmH6YP4V+1AhjBE9KapzeQED2JgzZm/I7FIwR5HQol2nSBqX5jA1uQPwQDcEY6+pxjNDkrrREFva6xQeZ9cX5o5znnQPyC3TUV+N8Wcfezx3kTzMl5FwNLLlkcEWUk7gIZoxapqaGF+mPROk86Y51x/ff8sSX9u5/gntq//Enbr3xxAmMY05f+k3hABthipGlYUTKwGrNFEM1/FMmciSAVzMkyFaZBBkwLIGTDkjJa0DBGzZloGlgcsBCgChBsiP72ukMV/L2z27Hn9v6BreRB/f2b9++hip/AYfyoPQU+xYHuWnUaHAwuFCwb6UKkZEbkp5wi1sIUtrqsgp6i5uRcShU5ug17GYfQr2G4g0WKtiQlWYQ7ym7yRGzvtiZq8EwyEXJZ5qZegZp18k5p1yEjy2SmNcLYfOsimTgzssb3FVavAA/8KO8Ta1ZgAf4Jaqb9Oql/+TfKdhHIs2HmaQg3yGoOZoqTzGsoC71xW2BFEM1PRxiSlmAr9Vh7qUZ17MZo6Au8uGlAvdWopDMf4j5E7VOEaN+sr/EdWLKkJW+NZLYPqW22j1IaWPQJhqbMDaCCwV4mKiBu5RyvAbkw4EoawsHIF6XtehIdO/E6FLJ1xeSaDRQaKMBAERUDB+NjH4mMlEVGPrvz3WMrzNVhkpdLn3Yd9vqmw8b2bvb08+lO17W3X3T1EzwkXd+kv5fH5se7+oev2/6H56r8ZduSQePj/fGzqf/PO7aMH72w4Nbd8bZUpaH8z17jA8rJwq6GBPTwfyeiZcJyUp/EFYFKgWYUlc1rWq3m8S4XkgW1jnhNyz+JlFvJ2CwGgAS+qV5snxEcXaZ6GHIRBnZVHTNyKv6DBUsClYWKYQMlZk8o1yNyVbUQm3tIH9hRs5GMxDm1InxVsq156Vv8wbgd17oGmoSkwEkkQsIZGnqhNKYVqC3saMpymmdp16baAmDGVgSaZAjVaEtcwkbJEZQFrKoDx8iwWugRpJszMrG8zaeXtEeY9+pVAxEtJzJl77gMZa1DyrYP/iMLGvyvv7wk294jEZPOu01st82fdPoUZx47LFoH5c+JFp4k4k3B9jDXF80/UV8GG6u5Y3pk+xGI3mW/k7ADG+xiOya9BgbT78Ezxla4PYI/whZhYL0RhxCp0KFL/dxRvoRw1U5aqVxVbO2Xgv/wIVPZnXntxVsJFHFDJMM0PNYooWcI+rtzZDXwOROJZk6lUUoLUWslWKZABCANGJ43ATJHlqkFEYCED9VFPOHwQJ+kZgtjOzEYegc7A4HVEgu5yZTxyBC+VLSjTRIbhv5hVsDh2Zgky5xY7VJA/lzN8psubUqWrHo9hNbFlVKq1VgtqRdVpHKQg7OkkE5NGPWvi5t8EZPYN/bL/1gTVuoX1OyqW1igIvx1s50i9eu5nhL58/52vZ0W3stz4enxqcPNG6bvi7UE22utdfwRvvYtp9fHL2pU9nUpDAPjLIn9nYoLz6Nz5WdN3ETWVy3Iq7PS7hWUFy1esQVUxFOgiv0x0GxV5kCgVXNAtY7F1hPBthG1WLwwsJeSrAtrUQmbWASqUR+7UoowS7VpGpVTDEscQJiWguYqpwRTBDZcpCFlclEgJRE3AiSUrlzFmbQqs5F1uYTj+3YPcz6uDJfMF0SbCznavSNq8nEt5kj/mee4S0dGWh3HvC3rCo7/8WxPrOCwGnpu4LvVLZ7DDV2fam+hgA9dfHpPdEsshwzyDDK7xBc1zKb2EImOYgre1sgkBjiz6XcvkjHAFmk0GuBznNSgQQuk+i7kzD0K0WC8iD03AW6AzLOibpRiOyuE+IxRLqHID0qJntigFjPGgJerAcexhDj2CD5d3poHfMVIjYckDN4sAveEWwjb+4KwsOu9fDmrnbaYuDHIPBcsgGN1eAhb/NjasnvRYvFq6AwV4NFuskqDcrJG4jHbyZ/19UDHr8hghXrxVDHEy8lK9kkq5W0TDOzwCSTls+bCdLJG1Y0PwtzQZblc2nrc5846skBOce+hsGDtsYt3/3hSP8De0+f6dsbUyu6AlMD3GpWUVRTV592dFk4rsTue5NT273pMLFr+qes2uZN+/oaeLaa9Rws1hULtpFWnEm3+LdtavFObwl1dzRqo3pFdd3aHWQyBYON2mKeWLl9H3viij6L4uLTowPgEWj2i09T98AnU+OicpPejP4R20lz06PEJ1LEJ4bIibWKSfZh5UOY+EQ/8QlDZSjSk/EJNfUJL32aGqMhrwWcog+cYlU06xT+YXCKLUJ8EJ2ii9h5WEx2DaJxe4kBB9Hkg+gUg33EjF20K2tEhC5O2IZE5E4XV8E7xDAwqGNnZ0crefMGMS5qUuvpPFwvQKenmWbAkxrc8jRQZWTG+xkzibFJtJhqoO9uEBJbyVvXg2pf0STxiw5tfCwSF8Ed4g3ahBrquc1AeU+8ZGy+l4SkSc0tOqkLs9tdfc4Mh6L48Jw/KFQaRg/aG6/9xvcHplN/H2JrOEWlw5V2+BxqrljjX12kK/aau5qfe45ziukIOMlvWHN7uon6SA2nNjR2q3QlPou1Wa0DT7n+Vv+26WmyMnRGPWpYGsz9V/BtXLtHX+3Ul+uq6dLQ37GKzzgJWYYzPlKnh7fWOIylumqzyQtHgv8DvyTDPAAAeNpjYGRgYABixQntnPH8Nl8Z5DkYQODi+01uIPqmr/Hq/53/XNjfsOcDuRwMTCBRADeWDAMAAAB42mNgZGDgiPqrAyQZ/nf+n87+hgEoggJeAgCJLQaQAHjabZK/a1NRFMe/ue/lpYiDiOCgDiJY4fEIJYTyCCFQQgklBA0SilMGKTgUa6CDv/6ADKFDFwUHwR/wSqciCA4OCrq4iIiIo4OLbi5Oz8+5eYEa++DDOff8uuee89xPtcXn9sBkpr1wSwehdBJWF6TfUaaJS/UI33VoYr8b7qhH/FXOQ+S6S/PP2BswgQRiWIJlaBc2ky1y9g1qrFkdWMd+v7Klp+V3Ol8eqIq8BbHp4XclUapr0AjO+pon0Lv4apWJj61yHhRxA87tcKQ+/q75DN7RKPQE+6rzb8o/ITvhMz2m5jH008gmuUkw4S0jNU1iv+B7HylmDosuyx+gL5vObJbQ60We6ZfJadNnSl7VcvDVudfmZnVi/LXgouqlN3qP3A4v0c909vv4ty0+VP4FxsSMbTb4XPmP2m5DIeeUmdkch96WqRvUip1sKILj2F5wdy+8gm77ybSDveWe+H5WIqkDLpLv67af+xEwt3N+F7aTQ9geDkPMmdke5qGvzWIv1TkS25mf27SP/yCmbzuYh9199LtI8wN4Xcy/fmQd+8em/vgf5KXdHfPOFe6yfySxWbPjH8FLqXJTmkl3Ryp9g+YU/ULeQ97wuxvOsH+JeqfQd+G5gW0NFg33QX38rywX3ya0rC77frug0jh4iG5vgeirOur9BXd+pmp42mNgYNCBwjaGD4zXmGqYZZifsaiwJLDMYW1jPcXGxabDFsFWwXaJXYS9iP0VhxXHBk45Ti/OE1wOXA1cj7i+cUtx63Ef4dnGy8XbxvuNL4DvEX+WAJPABIFrgi6Cp4TkhJYJywlXCH8RKRJlEF0jJiTWJ3ZDPEL8koSLxCyJSxIfJDUk3SSTJLuktKSmSH2TLpA+IeMlyyXbI/tKLkvunryc/DOFLIUdilaK65TElNYp8yjXKJ9R8VM5oxqjuk6NTU1FrUbtgNoBdQn1No0KjU+afZpbtNZovdNeouOg06WzTeeG7hHdZ3p6eg161/Rd9HP0nxm4GOQYbDL4YuhgOM3IzOiZ8SYTB5NlpjymOWYsZnPMrSy4LPZZplkJWO2w7rN+ZeNhs8hWyXaJXZjdIXs9+ykOWg7bHG44Rjm+c6pz5nE+4OLicsY1wU3M7Yx7nUecp5WXgtcn7x7vXz4ZPpd8i3yP+Un5Zfm98C8IMAuYF8gWmBX4K6gr6FKwR/ClkJiQR6FTwszCtoR3REREfItcEXkhSgQHVIoyiLKLiooqi9oW9S3aLHpFjFRMX8yeWCEg9Inti+2LU4v7Fa8Ufy6hKrElaQYAg/ybsAAAAAABAAAA6gBlAAUAAAAAAAIAAQACABYAAAEAAWEAAAAAeNqdkr1OAkEUhc8uaDAaoxQWVBtCCGpEIBD56dSoIWoMKLTyq0RgcQXUztLSJ/AJLHwES396Exsrn8N4dvYGaTDETHb2mztn7z1zZwF48QkXNPcUgDofhzX4uHJYhwc3wi4kcSvsRgBPwhOw8CU8Cb9WEPYgqV0JTyOoPQrPIKS9C88hoH0Lz8Oj+4W9MPQl4Wcs6FnhF0T0Y+FXzOp3wm/ke4c/XPDpD9iAiQ6u6a2BE5yiCwMxRBBFnFTmjoEQjpBDEYtY5jCwiRoulL7NVVAifT5Nla1FaqtM2+QydrBPtU09fpejpsWIiRR2sc53E1XWC7OqPTJSzSCN/m4Fe6xS/UNhDHIXqLSUY1M5Hq51gPxQJMMOmHReUcr+YCeMBNa420IJZ8xma+qMNpmzzH45mhjVSdZOjOH7vz21b6jLdRqrHJdqhFnH4rvDEWbu2hiqirj69WmI05Jy4Pg1hm5o9JmcExU5l9kVU+7e6dwhvfS4ynJuqmhUzXF6i7NjaXYrNvjnUsp9nR5stX0C5+ZqqurWIHce54w0uGfZHfoBeoCIcAAAAHjabdBHTJNxGMfx7wOlhbL3Bvce7/u2ZbhboO69tyjQVhGwWBW3EfeIxkRPGtdFjXtGox7UuBXjiHrw7I4H9eTBwvv35u/yyfMcnjz5EUFb/rSwjf/lM0iERBKJhSis2IgmBjuxxBFPAokkkUwKqaSRTgaZZJFNDrnkkU8BhbSjPR3oSCc604WudKM7PehJL3rTh75o6Bg4cOKiiGJKKKUf/RnAQAYxmCG48VBGORV4GcowhjOCkYxiNGMYyzjGM4GJTGIyU5jKNKYzg5nMYjZzmMs8KsXCMZrZxE3285HN7GYHBznBcYliO+/ZyD6xio1dHGArd/gg0RziJL/4yW+OcpqH3OcM81nAHqp4TDUPeMRznvCUZ3yihpe08IKz+PjBXt7witf4+cK3cLMLCbCIxdRSx2HqWUIDQRoJsZRlLA+3vIKVNLGKNazmGkdYx1rWs4GvfOc65zjPDd7yTmLELrESJ/GSIImSJMmSIqmSJumSwQUucoWr3OUSl7nHFk5JJre4LVmSzU7JkVzJk3wpsPpqmxr8uolhC9UFNM2tKctNPWrvcShLWzU0TVPqSkPpUDqVLmWRslhZovx3z22qq7u6bq8J+ELB6qrKRr+5MrymLq+lIhSsbxtc3rJWvR7zj7CG0qF0/gVaBp3uAAB42tvB+L91A2Mvg/cGjoCIjYyMfZEb3di0IxQ3CER6bxAJAjIaImU3sGnHRDBsYFZw3cCs7bKBRcF1E3MqkzaYwwrksNhAOIwb2KBK2BVcdzGw1f9nYNLeyOxWBhThAKpjV4BzOYFcDiEYN3KDiDYAoXooiw==) + format('woff'); +} + +@font-face { + font-family: 'nimbus_roman'; + font-style: italic; + font-weight: bold; + src: url(data:application/font-woff2;charset=utf-8;base64,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) + format('woff2'), + url(data:application/font-woff;charset=utf-8;base64,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) + format('woff'); +} + +@font-face { + font-family: 'nimbus_roman'; + font-style: normal; + font-weight: normal; + src: url(data:application/font-woff2;charset=utf-8;base64,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) + format('woff2'), + url(data:application/font-woff;charset=utf-8;base64,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) + format('woff'); +} + +@font-face { + font-family: 'nimbus_roman'; + font-style: italic; + font-weight: normal; + src: url(data:application/font-woff2;charset=utf-8;base64,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) + format('woff2'), + url(data:application/font-woff;charset=utf-8;base64,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) + format('woff'); +} + +@font-face { + font-family: 'nimbus_sans_l'; + font-style: normal; + font-weight: bold; + src: url(data:application/font-woff2;charset=utf-8;base64,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) + format('woff2'), + url(data:application/font-woff;charset=utf-8;base64,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) + format('woff'); +} + +@font-face { + font-family: 'nimbus_sans_l'; + font-style: italic; + font-weight: bold; + src: url(data:application/font-woff2;charset=utf-8;base64,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) + format('woff2'), + url(data:application/font-woff;charset=utf-8;base64,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) + format('woff'); +} + +@font-face { + font-family: 'nimbus_sans_l'; + font-style: normal; + font-weight: normal; + src: url(data:application/font-woff2;charset=utf-8;base64,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) + format('woff2'), + url(data:application/font-woff;charset=utf-8;base64,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) + format('woff'); +} + +@font-face { + font-family: 'nimbus_sans_l'; + font-style: italic; + font-weight: normal; + src: url(data:application/font-woff2;charset=utf-8;base64,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) + format('woff2'), + url(data:application/font-woff;charset=utf-8;base64,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) + format('woff'); +} diff --git a/shared/src/business/utilities/pdfGenerator/components/CompressedDocketHeader.jsx b/shared/src/business/utilities/pdfGenerator/components/CompressedDocketHeader.jsx new file mode 100644 index 00000000000..47920626e31 --- /dev/null +++ b/shared/src/business/utilities/pdfGenerator/components/CompressedDocketHeader.jsx @@ -0,0 +1,26 @@ +const React = require('react'); + +const CompressedDocketHeader = ({ + caseCaptionExtension, + caseTitle, + docketNumberWithSuffix, + h3, +}) => { + return ( + <> +
+
+ {caseTitle}, {caseCaptionExtension} v. Commissioner of Internal + Revenue, Respondent +
+
+ Docket Number {docketNumberWithSuffix} +
+
+ {h3 &&

{h3}

} +
+ + ); +}; + +export default CompressedDocketHeader; diff --git a/shared/src/business/utilities/pdfGenerator/components/CompressedDocketHeader.test.js b/shared/src/business/utilities/pdfGenerator/components/CompressedDocketHeader.test.js new file mode 100644 index 00000000000..0022e5f9351 --- /dev/null +++ b/shared/src/business/utilities/pdfGenerator/components/CompressedDocketHeader.test.js @@ -0,0 +1,36 @@ +const CompressedDocketHeader = require('./CompressedDocketHeader.jsx').default; +const React = require('react'); +const { shallow } = require('enzyme'); + +describe('CompressedDocketHeader', () => { + it('renders the case caption from props', () => { + let wrapper = shallow( + , + ); + expect(wrapper.find('#caption').text()).toEqual( + 'Test Petitioner, Petitioner v. Commissioner of Internal Revenue, Respondent', + ); + }); + + it('renders the docket number from props', () => { + let wrapper = shallow( + , + ); + expect(wrapper.find('#docket-number').text()).toEqual( + 'Docket Number 123-45S', + ); + }); + + it('only renders an h3 element if h3 prop is provided', () => { + let wrapper = shallow(); + let h3 = wrapper.find('.case-information h3'); + expect(h3).toEqual({}); + + wrapper = shallow(); + h3 = wrapper.find('.case-information h3'); + expect(h3.text()).toEqual('Test H3'); + }); +}); diff --git a/shared/src/business/utilities/pdfGenerator/components/DocketHeader.jsx b/shared/src/business/utilities/pdfGenerator/components/DocketHeader.jsx new file mode 100644 index 00000000000..4e21cb3c1c9 --- /dev/null +++ b/shared/src/business/utilities/pdfGenerator/components/DocketHeader.jsx @@ -0,0 +1,27 @@ +const React = require('react'); + +const DocketHeader = ({ + caseCaptionExtension, + caseTitle, + docketNumberWithSuffix, + h3, +}) => { + return ( + <> +
+
+
{caseTitle}
+
{caseCaptionExtension}
+
v.
+
Commissioner of Internal Revenue
+
Respondent
+
+
Docket Number {docketNumberWithSuffix}
+
+ {h3 &&

{h3}

} +
+ + ); +}; + +export default DocketHeader; diff --git a/shared/src/business/utilities/pdfGenerator/components/DocketHeader.test.js b/shared/src/business/utilities/pdfGenerator/components/DocketHeader.test.js new file mode 100644 index 00000000000..7e58c98e97e --- /dev/null +++ b/shared/src/business/utilities/pdfGenerator/components/DocketHeader.test.js @@ -0,0 +1,44 @@ +const DocketHeader = require('./DocketHeader.jsx').default; +const React = require('react'); +const { shallow } = require('enzyme'); + +describe('DocketHeader', () => { + it('renders the case caption from props', () => { + let wrapper = shallow(); + expect(wrapper.find('#caption-title').text()).toEqual('Test Petitioner'); + }); + + it('renders the case caption extension from props', () => { + let wrapper = shallow( + , + ); + expect(wrapper.find('#caption-extension').text()).toEqual('Petitioner(s)'); + }); + + it('renders the case caption postfix', () => { + const wrapper = shallow(); + + expect(wrapper.find('#caption-v').text()).toEqual('v.'); + expect(wrapper.find('#caption-commissioner').text()).toEqual( + 'Commissioner of Internal Revenue', + ); + expect(wrapper.find('#caption-respondent').text()).toEqual('Respondent'); + }); + + it('renders the docket number from props', () => { + let wrapper = shallow(); + expect(wrapper.find('#docket-number').text()).toEqual( + 'Docket Number 123-45S', + ); + }); + + it('only renders an h3 element if h3 prop is provided', () => { + let wrapper = shallow(); + let h3 = wrapper.find('.case-information h3'); + expect(h3).toEqual({}); + + wrapper = shallow(); + h3 = wrapper.find('.case-information h3'); + expect(h3.text()).toEqual('Test H3'); + }); +}); diff --git a/shared/src/business/utilities/pdfGenerator/components/PageMetaHeaderDocket.jsx b/shared/src/business/utilities/pdfGenerator/components/PageMetaHeaderDocket.jsx new file mode 100644 index 00000000000..5ebe92b9450 --- /dev/null +++ b/shared/src/business/utilities/pdfGenerator/components/PageMetaHeaderDocket.jsx @@ -0,0 +1,17 @@ +const React = require('react'); + +const PageMetaHeaderDocket = ({ docketNumber }) => { + return ( + <> +
+ Docket Number: {docketNumber} +
+
+ Page of{' '} + +
+ + ); +}; + +export default PageMetaHeaderDocket; diff --git a/shared/src/business/utilities/pdfGenerator/components/PageMetaHeaderDocket.test.js b/shared/src/business/utilities/pdfGenerator/components/PageMetaHeaderDocket.test.js new file mode 100644 index 00000000000..c82b9d98b2f --- /dev/null +++ b/shared/src/business/utilities/pdfGenerator/components/PageMetaHeaderDocket.test.js @@ -0,0 +1,10 @@ +const PageMetaHeaderDocket = require('./PageMetaHeaderDocket.jsx').default; +const React = require('react'); +const { shallow } = require('enzyme'); + +describe('PageMetaHeaderDocket', () => { + it('renders the docket number from props', () => { + let wrapper = shallow(); + expect(wrapper.text()).toContain('Docket Number: 123-45'); + }); +}); diff --git a/shared/src/business/utilities/pdfGenerator/components/PrimaryHeader.jsx b/shared/src/business/utilities/pdfGenerator/components/PrimaryHeader.jsx new file mode 100644 index 00000000000..0f54e37a228 --- /dev/null +++ b/shared/src/business/utilities/pdfGenerator/components/PrimaryHeader.jsx @@ -0,0 +1,17 @@ +const React = require('react'); + +const PrimaryHeader = ({ h2 }) => { + return ( + <> +
+
+

United States Tax Court

+
Washington, DC 21207
+ {h2 &&

{h2}

} +
+
+ + ); +}; + +export default PrimaryHeader; diff --git a/shared/src/business/utilities/pdfGenerator/components/PrimaryHeader.test.js b/shared/src/business/utilities/pdfGenerator/components/PrimaryHeader.test.js new file mode 100644 index 00000000000..9d67ac8c6ae --- /dev/null +++ b/shared/src/business/utilities/pdfGenerator/components/PrimaryHeader.test.js @@ -0,0 +1,29 @@ +const PrimaryHeader = require('./PrimaryHeader.jsx').default; +const React = require('react'); +const { shallow } = require('enzyme'); + +describe('PrimaryHeader', () => { + it('renders an h1 with United States Tax Court', () => { + const wrapper = shallow(); + + const h1 = wrapper.find('.court-header h1'); + expect(h1.text()).toEqual('United States Tax Court'); + }); + + it('renders the Tax Court address', () => { + const wrapper = shallow(); + + const courtAddress = wrapper.find('.court-address'); + expect(courtAddress.text()).toEqual('Washington, DC 21207'); + }); + + it('only renders an h2 element if h2 prop is provided', () => { + let wrapper = shallow(); + let h2 = wrapper.find('.court-header h2'); + expect(h2).toEqual({}); + + wrapper = shallow(); + h2 = wrapper.find('.court-header h2'); + expect(h2.text()).toEqual('Test H2'); + }); +}); diff --git a/shared/src/business/utilities/pdfGenerator/components/ReportsHeader.jsx b/shared/src/business/utilities/pdfGenerator/components/ReportsHeader.jsx new file mode 100644 index 00000000000..4a58cf3124d --- /dev/null +++ b/shared/src/business/utilities/pdfGenerator/components/ReportsHeader.jsx @@ -0,0 +1,14 @@ +const React = require('react'); + +const ReportsHeader = ({ subtitle, title }) => { + return ( + <> +
+

{title}

+

{subtitle}

+
+ + ); +}; + +export default ReportsHeader; diff --git a/shared/src/business/utilities/pdfGenerator/components/ReportsHeader.test.js b/shared/src/business/utilities/pdfGenerator/components/ReportsHeader.test.js new file mode 100644 index 00000000000..eb19d497c5d --- /dev/null +++ b/shared/src/business/utilities/pdfGenerator/components/ReportsHeader.test.js @@ -0,0 +1,19 @@ +const React = require('react'); +const ReportsHeader = require('./ReportsHeader.jsx').default; +const { shallow } = require('enzyme'); + +describe('ReportsHeader', () => { + it('renders the title from props in an h1 tag', () => { + let wrapper = shallow( + , + ); + expect(wrapper.find('h1').text()).toEqual('Report Title'); + }); + + it('renders the subtitle from props in an h2 tag', () => { + let wrapper = shallow( + , + ); + expect(wrapper.find('h2').text()).toEqual('Report Sub-Title'); + }); +}); diff --git a/shared/src/business/utilities/pdfGenerator/documentTemplates/ChangeOfAddress.jsx b/shared/src/business/utilities/pdfGenerator/documentTemplates/ChangeOfAddress.jsx new file mode 100644 index 00000000000..be283e5b4a4 --- /dev/null +++ b/shared/src/business/utilities/pdfGenerator/documentTemplates/ChangeOfAddress.jsx @@ -0,0 +1,63 @@ +const React = require('react'); + +const DocketHeader = require('../components/DocketHeader.jsx').default; +const PrimaryHeader = require('../components/PrimaryHeader.jsx').default; + +const renderTable = ({ data, label, options }) => { + return ( + + + + + + + + + {options.showOnlyPhoneChange && } + {!options.showOnlyPhoneChange && ( + + )} + + +
{label} Contact Information
{data.phone} + {data.inCareOf &&
c/o {data.inCareOf}
} +
{data.address1}
+
{data.address2}
+
{data.address3}
+
+ {data.city && {data.city},} + {data.state} {data.postalCode} + {data.country &&
{data.country}
} + {options.showAddressAndPhoneChange && ( +
{data.phone}
+ )} +
+
+ ); +}; + +const ChangeOfAddress = ({ name, newData, oldData, options }) => { + return ( + <> + + + +

+ Please change the contact information for {name} on the records of the + Court. +

+
+ {renderTable({ data: oldData, label: 'Old', options })} +
+ {renderTable({ data: newData, label: 'New', options })} +
+ + ); +}; + +export default ChangeOfAddress; diff --git a/shared/src/business/utilities/pdfGenerator/documentTemplates/ChangeOfAddress.test.js b/shared/src/business/utilities/pdfGenerator/documentTemplates/ChangeOfAddress.test.js new file mode 100644 index 00000000000..c6ae9489ada --- /dev/null +++ b/shared/src/business/utilities/pdfGenerator/documentTemplates/ChangeOfAddress.test.js @@ -0,0 +1,253 @@ +const ChangeOfAddress = require('./ChangeOfAddress.jsx').default; +const React = require('react'); +const { shallow } = require('enzyme'); + +describe('ChangeOfAddress', () => { + let options; + let newData; + let oldData; + + beforeEach(() => { + newData = { + address1: 'New Address 1', + address2: 'New Address 2', + address3: 'New Address 3', + city: 'New City', + country: 'USA', + inCareOf: 'New Care Of', + phone: '321-321-4321', + postalCode: '54321', + state: 'NS', + }; + + oldData = { + address1: 'Address 1', + address2: 'Address 2', + address3: 'Address 3', + city: 'City', + country: 'USA', + inCareOf: 'Test Care Of', + phone: '123-124-1234', + postalCode: '12345', + state: 'ST', + }; + + options = { + caseCaptionExtension: 'Petitioner(s)', + caseTitle: 'Test Petitioner', + docketNumberWithSuffix: '123-45S', + }; + }); + + it('renders a table with the old contact information', () => { + options.showAddressAndPhoneChange = true; + + const wrapper = shallow( + , + ); + const table = wrapper.find('#contact_info_Old'); + expect(table.find('thead tr th').text()).toEqual('Old Contact Information'); + expect(table.find('tbody tr').text()).toContain(`c/o ${oldData.inCareOf}`); + expect(table.find('tbody tr').text()).toContain(oldData.address1); + expect(table.find('tbody tr').text()).toContain(oldData.address2); + expect(table.find('tbody tr').text()).toContain(oldData.address3); + expect(table.find('tbody tr').text()).toContain(oldData.city); + expect(table.find('tbody tr').text()).toContain(oldData.state); + expect(table.find('tbody tr').text()).toContain(oldData.postalCode); + expect(table.find('tbody tr').text()).toContain(oldData.country); + expect(table.find('tbody tr').text()).toContain(oldData.phone); + }); + + it('renders a table with the new contact information', () => { + options.showAddressAndPhoneChange = true; + + const wrapper = shallow( + , + ); + const table = wrapper.find('#contact_info_New'); + expect(table.find('thead tr th').text()).toEqual('New Contact Information'); + expect(table.find('tbody tr').text()).toContain(`c/o ${newData.inCareOf}`); + expect(table.find('tbody tr').text()).toContain(newData.address1); + expect(table.find('tbody tr').text()).toContain(newData.address2); + expect(table.find('tbody tr').text()).toContain(newData.address3); + expect(table.find('tbody tr').text()).toContain(newData.city); + expect(table.find('tbody tr').text()).toContain(newData.state); + expect(table.find('tbody tr').text()).toContain(newData.postalCode); + expect(table.find('tbody tr').text()).toContain(newData.country); + expect(table.find('tbody tr').text()).toContain(newData.phone); + }); + + it('only displays a phone number change if options.showOnlyPhoneChange is true', () => { + options.showOnlyPhoneChange = true; + + const wrapper = shallow( + , + ); + const oldTable = wrapper.find('#contact_info_Old'); + expect(oldTable.find('thead tr th').text()).toEqual( + 'Old Contact Information', + ); + + expect(oldTable.find('tbody tr').text()).toContain(oldData.phone); + + expect(oldTable.find('tbody tr').text()).not.toContain( + `c/o ${oldData.inCareOf}`, + ); + expect(oldTable.find('tbody tr').text()).not.toContain(oldData.address1); + expect(oldTable.find('tbody tr').text()).not.toContain(oldData.address2); + expect(oldTable.find('tbody tr').text()).not.toContain(oldData.address3); + expect(oldTable.find('tbody tr').text()).not.toContain(oldData.city); + expect(oldTable.find('tbody tr').text()).not.toContain(oldData.state); + expect(oldTable.find('tbody tr').text()).not.toContain(oldData.postalCode); + expect(oldTable.find('tbody tr').text()).not.toContain(oldData.country); + + const newTable = wrapper.find('#contact_info_New'); + expect(newTable.find('thead tr th').text()).toEqual( + 'New Contact Information', + ); + + expect(newTable.find('tbody tr').text()).toContain(newData.phone); + + expect(newTable.find('tbody tr').text()).not.toContain( + `c/o ${newData.inCareOf}`, + ); + expect(newTable.find('tbody tr').text()).not.toContain(newData.address1); + expect(newTable.find('tbody tr').text()).not.toContain(newData.address2); + expect(newTable.find('tbody tr').text()).not.toContain(newData.address3); + expect(newTable.find('tbody tr').text()).not.toContain(newData.city); + expect(newTable.find('tbody tr').text()).not.toContain(newData.state); + expect(newTable.find('tbody tr').text()).not.toContain(newData.postalCode); + expect(newTable.find('tbody tr').text()).not.toContain(newData.country); + }); + + it('only displays an address change if options.showOnlyPhoneChange and options.showAddressAndPhoneChange are falsy', () => { + options.showOnlyPhoneChange = false; + options.showAddressAndPhoneChange = false; + + const wrapper = shallow( + , + ); + const oldTable = wrapper.find('#contact_info_Old'); + expect(oldTable.find('thead tr th').text()).toEqual( + 'Old Contact Information', + ); + + expect(oldTable.find('tbody tr').text()).toContain( + `c/o ${oldData.inCareOf}`, + ); + expect(oldTable.find('tbody tr').text()).toContain(oldData.address1); + expect(oldTable.find('tbody tr').text()).toContain(oldData.address2); + expect(oldTable.find('tbody tr').text()).toContain(oldData.address3); + expect(oldTable.find('tbody tr').text()).toContain(oldData.city); + expect(oldTable.find('tbody tr').text()).toContain(oldData.state); + expect(oldTable.find('tbody tr').text()).toContain(oldData.postalCode); + expect(oldTable.find('tbody tr').text()).toContain(oldData.country); + + expect(oldTable.find('tbody tr').text()).not.toContain(oldData.phone); + + const newTable = wrapper.find('#contact_info_New'); + expect(newTable.find('thead tr th').text()).toEqual( + 'New Contact Information', + ); + + expect(newTable.find('tbody tr').text()).toContain( + `c/o ${newData.inCareOf}`, + ); + expect(newTable.find('tbody tr').text()).toContain(newData.address1); + expect(newTable.find('tbody tr').text()).toContain(newData.address2); + expect(newTable.find('tbody tr').text()).toContain(newData.address3); + expect(newTable.find('tbody tr').text()).toContain(newData.city); + expect(newTable.find('tbody tr').text()).toContain(newData.state); + expect(newTable.find('tbody tr').text()).toContain(newData.postalCode); + expect(newTable.find('tbody tr').text()).toContain(newData.country); + + expect(newTable.find('tbody tr').text()).not.toContain(newData.phone); + }); + + it('does not show inCareOf if not provided in the old or new data', () => { + options.showAddressAndPhoneChange = true; + + delete newData.inCareOf; + delete oldData.inCareOf; + + const wrapper = shallow( + , + ); + const oldTable = wrapper.find('#contact_info_Old'); + expect(oldTable.find('tbody tr').text()).not.toContain( + `c/o ${oldData.inCareOf}`, + ); + + const newTable = wrapper.find('#contact_info_New'); + expect(newTable.find('tbody tr').text()).not.toContain( + `c/o ${newData.inCareOf}`, + ); + }); + + it('does not show city if not provided in the old or new data', () => { + options.showAddressAndPhoneChange = true; + + delete newData.city; + delete oldData.city; + + const wrapper = shallow( + , + ); + const oldTable = wrapper.find('#contact_info_Old'); + expect(oldTable.find('tbody tr').text()).not.toContain(oldData.city); + + const newTable = wrapper.find('#contact_info_New'); + expect(newTable.find('tbody tr').text()).not.toContain(newData.city); + }); + + it('does not show country if not provided in the old or new data', () => { + options.showAddressAndPhoneChange = true; + + delete newData.country; + delete oldData.country; + + const wrapper = shallow( + , + ); + const oldTable = wrapper.find('#contact_info_Old'); + expect(oldTable.find('tbody tr').text()).not.toContain(oldData.country); + + const newTable = wrapper.find('#contact_info_New'); + expect(newTable.find('tbody tr').text()).not.toContain(newData.country); + }); +}); diff --git a/shared/src/business/utilities/pdfGenerator/documentTemplates/DocketRecord.jsx b/shared/src/business/utilities/pdfGenerator/documentTemplates/DocketRecord.jsx new file mode 100644 index 00000000000..1843d293d34 --- /dev/null +++ b/shared/src/business/utilities/pdfGenerator/documentTemplates/DocketRecord.jsx @@ -0,0 +1,193 @@ +const React = require('react'); + +const CompressedDocketHeader = require('../components/CompressedDocketHeader.jsx') + .default; +const PrimaryHeader = require('../components/PrimaryHeader.jsx').default; + +const RenderAddress = ({ contact, countryTypes }) => { + const isInternational = contact.countryType === countryTypes.INTERNATIONAL; + + return ( + <> + {contact.inCareOf &&
c/o {contact.inCareOf}
} + {contact.title &&
{contact.title}
} + {contact.address1 &&
{contact.address1}
} + {contact.address2 &&
{contact.address2}
} + {contact.address3 &&
{contact.address3}
} +
+ {contact.city && {contact.city}, } + {contact.state && {contact.state} } + {contact.postalCode && {contact.postalCode}} +
+ {isInternational && {contact.country}} + {contact.phone &&

{contact.phone}

} + + ); +}; + +const RenderContact = ({ + caseTitle, + contact, + countryTypes, + showCaseTitleForPrimary, +}) => { + const name = showCaseTitleForPrimary ? caseTitle : contact.name; + + return ( +
+

{name}

+ +
+ ); +}; + +const RenderPractitioner = ({ + contactPrimary, + contactSecondary, + countryTypes, + practitioner, +}) => { + const { representingPrimary, representingSecondary } = practitioner; + const showRepresentingPrimary = representingPrimary && contactPrimary; + const showRepresentingSecondary = + representingSecondary && contactSecondary && contactSecondary.name; + + return ( +
+

{practitioner.formattedName || practitioner.name}

+ + + {(showRepresentingPrimary || showRepresentingSecondary) && ( +
+ Representing +
+ {showRepresentingPrimary &&
{contactPrimary.name}
} + {showRepresentingSecondary &&
{contactSecondary.name}
} +
+ )} +
+ ); +}; + +const DocketRecord = ({ caseDetail, countryTypes, entries, options }) => { + return ( +
+ + + +
+
{caseDetail.partyType}
+
+ + {caseDetail.contactSecondary && ( + + )} +
+
+ + {caseDetail.privatePractitioners.length > 0 && ( +
+
Petitioner Counsel
+
+ {caseDetail.privatePractitioners.map(practitioner => { + if (practitioner.formattedName) { + return ( + + ); + } + })} +
+
+ )} + + {caseDetail.irsPractitioners.length > 0 && ( +
+
Respondent Counsel
+
+ {caseDetail.irsPractitioners.map(practitioner => { + return ( + + ); + })} +
+
+ )} + + + + + + + + + + + + + + + + {entries && + entries.map(({ document, index, record }) => { + const servedAtFormatted = + document && document.isStatusServed + ? document.servedAtFormatted || '' + : ''; + const documentDateServed = + document && document.isNotServedCourtIssuedDocument + ? 'Not Served' + : servedAtFormatted; + + return ( + + + + + + + + + + + ); + })} + +
No.DateEventFilings and proceedingsFiled byActionServedParties
{index}{record.createdAtFormatted || ''}{record.eventCode || ''} + {record.description}{' '} + {record.filingsAndProceedings && + record.filingsAndProceedings} + {(document && document.filedBy) || ''}{record.action || ''}{documentDateServed}{(document && document.servedPartiesCode) || ''}
+
+ ); +}; + +export default DocketRecord; diff --git a/shared/src/business/utilities/pdfGenerator/documentTemplates/DocketRecord.test.js b/shared/src/business/utilities/pdfGenerator/documentTemplates/DocketRecord.test.js new file mode 100644 index 00000000000..d872c351d80 --- /dev/null +++ b/shared/src/business/utilities/pdfGenerator/documentTemplates/DocketRecord.test.js @@ -0,0 +1,394 @@ +const DocketRecord = require('./DocketRecord.jsx').default; +const React = require('react'); +const { ContactFactory } = require('../../../entities/contacts/ContactFactory'); +const { mount } = require('enzyme'); + +describe('DocketRecord', () => { + let caseDetail; + let contactPrimary; + let contactSecondary; + let entries; + let options; + let privatePractitioner; + let irsPractitioner; + + beforeEach(() => { + options = { + caseCaptionExtension: 'Petitioner(s)', + caseTitle: 'Test Case Title', + docketNumberWithSuffix: '123-45S', + }; + + contactPrimary = { + address1: 'Address 1', + address2: 'Address 2', + address3: 'Address 3', + city: 'City', + country: 'USA', + name: 'Test Petitioner', + phone: '123-124-1234', + postalCode: '12345', + state: 'STATE', + }; + + contactSecondary = { + address1: 'Address 1', + address2: 'Address 2', + address3: 'Address 3', + city: 'City', + country: 'USA', + name: 'Test Petitioner 2', + phone: '123-124-5678', + postalCode: '12345', + state: 'STATE', + }; + + privatePractitioner = { + barNumber: 'PT20001', + contact: { + address1: 'Address 1', + address2: 'Address 2', + address3: 'Address 3', + city: 'City', + country: 'USA', + phone: '234-123-4567', + postalCode: '12345', + state: 'STATE', + }, + formattedName: 'Test Private Practitioner (PT20001)', + name: 'Test Private Practitioner', + }; + + irsPractitioner = { + barNumber: 'PT20002', + contact: { + address1: 'Address 1', + address2: 'Address 2', + address3: 'Address 3', + city: 'City', + country: 'USA', + phone: '234-123-4567', + postalCode: '12345', + state: 'STATE', + }, + name: 'Test IRS Practitioner', + }; + + caseDetail = { + contactPrimary, + irsPractitioners: [], + partyType: 'Petitioner', + privatePractitioners: [], + }; + + entries = [ + { + document: { + filedBy: 'Test Filer', + isNotServedCourtIssuedDocument: false, + isStatusServed: true, + servedAtFormatted: '02/02/20', + servedPartiesCode: 'B', + }, + index: 1, + record: { + action: 'Axun', + createdAtFormatted: '01/01/20', + description: 'Test Description', + eventCode: 'T', + filingsAndProceedings: 'Test Filings And Proceedings', + }, + }, + ]; + }); + + it('renders the primary contact information', () => { + const wrapper = mount( + , + ); + + const contacts = wrapper.find('#petitioner-contacts'); + expect(contacts.find('.party-info-header').text()).toEqual('Petitioner'); + expect(contacts.find('.party-details').length).toEqual(1); + + const contactPrimaryEl = contacts.find('.party-details'); + + expect(contactPrimaryEl.text()).toContain(contactPrimary.name); + expect(contactPrimaryEl.text()).toContain(contactPrimary.address1); + expect(contactPrimaryEl.text()).toContain(contactPrimary.address2); + expect(contactPrimaryEl.text()).toContain(contactPrimary.address3); + expect(contactPrimaryEl.text()).toContain(contactPrimary.city); + expect(contactPrimaryEl.text()).toContain(contactPrimary.state); + expect(contactPrimaryEl.text()).toContain(contactPrimary.postalCode); + expect(contactPrimaryEl.text()).toContain(contactPrimary.phone); + + expect(contactPrimaryEl.text()).not.toContain(contactPrimary.country); + expect(contactPrimaryEl.text()).not.toContain('c/o'); + }); + + it('displays the case title in place of the primary contact name if showCaseTitleForPrimary is true', () => { + caseDetail.showCaseTitleForPrimary = true; + + const wrapper = mount( + , + ); + + const contactPrimaryEl = wrapper.find( + '#petitioner-contacts .party-details', + ); + + expect(contactPrimaryEl.text()).not.toContain(contactPrimary.name); + expect(contactPrimaryEl.text()).toContain(options.caseTitle); + }); + + it('renders the secondary contact information if provided', () => { + caseDetail.contactSecondary = contactSecondary; + + const wrapper = mount( + , + ); + + const contacts = wrapper.find('#petitioner-contacts'); + expect(contacts.find('.party-info-header').text()).toEqual('Petitioner'); + expect(contacts.find('.party-details').length).toEqual(2); + + const contactSecondaryEl = contacts.find('.party-details').at(1); + + expect(contactSecondaryEl.text()).toContain(contactSecondary.name); + expect(contactSecondaryEl.text()).toContain(contactSecondary.address1); + expect(contactSecondaryEl.text()).toContain(contactSecondary.address2); + expect(contactSecondaryEl.text()).toContain(contactSecondary.address3); + expect(contactSecondaryEl.text()).toContain(contactSecondary.city); + expect(contactSecondaryEl.text()).toContain(contactSecondary.state); + expect(contactSecondaryEl.text()).toContain(contactSecondary.postalCode); + expect(contactSecondaryEl.text()).toContain(contactSecondary.phone); + }); + + it("displays a party's country if international", () => { + contactPrimary.countryType = ContactFactory.COUNTRY_TYPES.INTERNATIONAL; + contactPrimary.country = 'The Republic of Texas'; + + const wrapper = mount( + , + ); + + const contactPrimaryEl = wrapper.find( + '#petitioner-contacts .party-details', + ); + + expect(contactPrimaryEl.text()).toContain('The Republic of Texas'); + }); + + it('renders party info in care of if present', () => { + contactPrimary.inCareOf = 'Test Care Of'; + const wrapper = mount( + , + ); + + const contactPrimaryEl = wrapper + .find('#petitioner-contacts') + .find('.party-details') + .at(0); + + expect(contactPrimaryEl.text()).toContain(`c/o ${contactPrimary.inCareOf}`); + }); + + it('renders private practitioner contact information if present', () => { + caseDetail.privatePractitioners = []; // No private practitioners + + let wrapper = mount( + , + ); + + expect(wrapper.find('#private-practitioner-contacts').length).toEqual(0); + + caseDetail.privatePractitioners = [privatePractitioner]; + + wrapper = mount( + , + ); + + const contacts = wrapper.find('#private-practitioner-contacts'); + expect(contacts.find('.party-info-header').text()).toEqual( + 'Petitioner Counsel', + ); + + const contactEl = contacts.find('.party-details'); + + expect(contactEl.text()).toContain(privatePractitioner.formattedName); + expect(contactEl.text()).toContain(privatePractitioner.contact.address1); + expect(contactEl.text()).toContain(privatePractitioner.contact.address2); + expect(contactEl.text()).toContain(privatePractitioner.contact.address3); + expect(contactEl.text()).toContain(privatePractitioner.contact.city); + expect(contactEl.text()).toContain(privatePractitioner.contact.state); + expect(contactEl.text()).toContain(privatePractitioner.contact.postalCode); + expect(contactEl.text()).toContain(privatePractitioner.contact.phone); + + expect(contactEl.text()).not.toContain('Representing'); + }); + + it('displays represented parties with each practitioner', () => { + const privatePractitioner2 = { + ...privatePractitioner, + barNumber: 'PT20002', + representingSecondary: true, + }; + privatePractitioner.representingPrimary = true; + caseDetail.privatePractitioners = [ + privatePractitioner, + privatePractitioner2, + ]; + caseDetail.contactSecondary = contactSecondary; + + const wrapper = mount( + , + ); + + const contacts = wrapper.find('#private-practitioner-contacts'); + expect(contacts.find('.party-info-header').text()).toEqual( + 'Petitioner Counsel', + ); + + expect(contacts.find('.party-details').length).toEqual(2); + + const practitioner1El = contacts.find('.party-details').at(0); + const practitioner2El = contacts.find('.party-details').at(1); + + expect(practitioner1El.text()).toContain('Representing'); + expect(practitioner1El.text()).toContain(contactPrimary.name); + + expect(practitioner2El.text()).toContain('Representing'); + expect(practitioner2El.text()).toContain(contactSecondary.name); + }); + + it('renders irs practitioner contact information if present', () => { + caseDetail.irsPractitioners = []; // No irs practitioners + + let wrapper = mount( + , + ); + + expect(wrapper.find('#irs-practitioner-contacts').length).toEqual(0); + + caseDetail.irsPractitioners = [irsPractitioner]; + + wrapper = mount( + , + ); + + const contacts = wrapper.find('#irs-practitioner-contacts'); + expect(contacts.find('.party-info-header').text()).toEqual( + 'Respondent Counsel', + ); + + const contactEl = contacts.find('.party-details'); + + expect(contactEl.text()).toContain(irsPractitioner.name); + expect(contactEl.text()).toContain(irsPractitioner.contact.address1); + expect(contactEl.text()).toContain(irsPractitioner.contact.address2); + expect(contactEl.text()).toContain(irsPractitioner.contact.address3); + expect(contactEl.text()).toContain(irsPractitioner.contact.city); + expect(contactEl.text()).toContain(irsPractitioner.contact.state); + expect(contactEl.text()).toContain(irsPractitioner.contact.postalCode); + expect(contactEl.text()).toContain(irsPractitioner.contact.phone); + + expect(contactEl.text()).not.toContain('Representing'); + }); + + it('renders a table with docket record data', () => { + const wrapper = mount( + , + ); + + const docketRecord = wrapper.find('#documents'); + expect(docketRecord.find('tbody tr').length).toEqual(entries.length); + + const rowEl = docketRecord.find('tbody tr').at(0); + + expect(rowEl.text()).toContain(entries[0].index); + expect(rowEl.text()).toContain(entries[0].record.createdAtFormatted); + expect(rowEl.text()).toContain(entries[0].record.eventCode); + expect(rowEl.text()).toContain(entries[0].record.description); + expect(rowEl.text()).toContain(entries[0].record.filingsAndProceedings); + expect(rowEl.text()).toContain(entries[0].document.filedBy); + expect(rowEl.text()).toContain(entries[0].record.action); + expect(rowEl.text()).toContain(entries[0].document.servedAtFormatted); + expect(rowEl.text()).toContain(entries[0].document.servedPartiesCode); + }); + + it('displays `Not Served` in the served column if the document is an unserved court-issued document', () => { + entries[0].document.isNotServedCourtIssuedDocument = true; + + const wrapper = mount( + , + ); + + const documentRow = wrapper.find('#documents tbody tr').at(0); + + expect(documentRow.text()).toContain('Not Served'); + + expect(documentRow.text()).not.toContain( + entries[0].document.servedAtFormatted, + ); + }); +}); diff --git a/shared/src/business/utilities/pdfGenerator/documentTemplates/StandingPretrialOrder.jsx b/shared/src/business/utilities/pdfGenerator/documentTemplates/StandingPretrialOrder.jsx new file mode 100644 index 00000000000..0b12bc1e770 --- /dev/null +++ b/shared/src/business/utilities/pdfGenerator/documentTemplates/StandingPretrialOrder.jsx @@ -0,0 +1,356 @@ +const React = require('react'); + +const DocketHeader = require('../components/DocketHeader.jsx').default; +const PrimaryHeader = require('../components/PrimaryHeader.jsx').default; + +const StandingPretrialOrder = ({ footerDate, options, trialInfo }) => { + return ( + <> + + + +

+ + The attached Notice Setting Case for Trial notifies the parties that + this case is calendared for trial at the trial session beginning on + {trialInfo.fullStartDate}. + +

+ +

+ + Communication Between the Parties. + {' '} + The parties shall begin discussing settlement and/or preparation of a + stipulation of facts as soon as practicable. Valuation cases and + reasonable compensation cases are generally susceptible of settlement, + and the Court expects the parties to negotiate in good faith with this + goal in mind. All minor issues should be settled so that the Court can + focus on the issue(s) needing a Court decision. If a party has trouble + communicating with another party or complying with this Order, the + affected party should promptly advise the Court in writing, with a copy + to each other party, or request a conference call for the parties and + the trial Judge. +

+ +

+ Continuances. Continuances + (i.e., postponement softrial) will be granted only in exceptional + circumstances. See Rule 133, Tax Court Rules of Practice and Procedure. + (The Court's Rules are available at{' '} + + www.ustaxcourt.gov + + .) Even joint motions for continuance are not granted automatically. +

+ +

+ Sanctions. The Court may + impose appropriate sanctions, including dismissal, for any unexcused + failure to comply with this Order. See Rule 131(b). Such failure may + also be considered in relation to sanctions against and disciplinary + proceedings involving counsel. See Rule 202(a). +

+ +

+ Electronic Filing (eFiling){' '} + eFiling is required for most documents (except the petition) filed by + parties represented by counsel in cases in which the petition is filed + on or after July 1, 2010. Petitioners not represented by counsel may, + but are not required to, eFile. For more information about eFiling and + the Court's other electronic services, see{' '} + + www.ustaxcourt.gov + + . +

+ +
+

+ To help the efficient disposition of all cases on the trial calendar: +

+ +

+ 1. Stipulation. + It is ORDERED that all facts shall be stipulated (agreed upon in + writing) to the maximum extent possible. All documents and written + evidence shall be marked and stipulated in accordance with Rule 91(b), + unless the evidence is to be used only to impeach(discredit) a + witness. Either party may preserve objections by noting them in the + stipulation. If a complete stipulation of facts is not ready for + submission at the start of the trial or when otherwise ordered by the + Court, and if the Court determines that this is due to lack of + cooperation by either party, the Court may order sanctions against the + uncooperative party. +

+ +

+ 2. Trial Exhibits. + It is ORDERED that any documents or materials which a party expects to + use (except solely for impeachment) if the case is tried, but which + are not stipulated, shall be identified in writing and exchanged by + the parties at least 14 days before the first day of the trial + session. The Court may refuse to receive in evidence any document or + material that is not so stipulated or exchanged, unless the parties + have agreed otherwise or the Court so allows for good cause shown. +

+
+ +

+ Served {footerDate} +

+ +
+

+ 3. Pretrial Memoranda. It + is ORDERED that, unless a basis of settlement (resolution of the + issues) has been reached, each party shall prepare a Pretrial + Memorandum containing the information in the attached form. Each party + shall serve on the other party and file the Pretrial Memorandum not + less than 14 days before the first day of the trial session. +

+

+ 4. Final Status Reports.{' '} + It is ORDERED that, if the status of the case changes from that + reported in a party's Pretrial Memorandum, the party shall submit + to the undersigned and to the other party a Final Status Report + containing the information in the attached form. A Final Status Report + maybe submitted to the Court in paper format, electronically by + following the procedures in the "Final Status Report" tab on + the Court's Website or by fax sent to 202-521-3378. (Only the + Final Status Report maybe sent to this fax number; any other documents + will be discarded.) The report must be received by the Court no later + than 3p.m. eastern time on the last business day (normally Friday) + before the calendar call. The Final Status Report must be promptly + submitted to the opposing party by mail, email, or fax, and a copy of + the report must be given to the opposing party at the calendar call if + the opposing party is present. +

+

+ 5.Witnesses. It is ORDERED + that witnessess hall be identified in the Pretrial Memorandum with a + brief summary of their anticipated testimony. Witnesses who are not + identified will not be permitted to testify at the trial with out a + showing of good cause. +

+

+ 6. Expert Witnesses. It is + ORDERED that unless otherwise permitted by the Court, expert + witnessess hall prepare a written report which shall be submitted + directly to the undersigned and served upon each other party at least + 30 days before the first day of the trial session. An expert + witness's test imony may be excluded for failure to comply with + this Order and Rule 143(g). +

+

+ 7. Settlements. It is + ORDERED that if the parties have reached a basis of settlement, + astipulated decision shall be submitted to the Court prior to or at + the call of the calendar on the first day of the trial session. + Additional time for submitting astipulated decision will be granted + only where it is clear that all parties have approved the settlement. + The parties shall be prepared to state for the record the basis of + settlement and the reasons for delay. The Court will specify the date + by which the stipulated decision and any related settlement documents + will be due. +

+

+ 8. Time of Trial. It is + ORDERED that all parties shall be prepared for trial at anytime during + the trial session unless a specific date has been previously set by + the Court. Your case may or may not be tried on the same date as the + calendar call, and you may need to return to Court on a later date + during the trial session. Thus, it may be beneficial to contact the + Court in advance. Within 2 weeks before the start of the trial + session, the parties may jointly contact the Judge's chamber + store quest a time and date certain for the trial. If practicable, the + Court will attempt to accommodate the request, keeping in mind other + scheduling requirements and the anticipated length of the session. + Parties should jointly inform the Judge as early as possible if they + expect trial to require 3 days or more. +

+

+ 9. Service of Documents.{' '} + It is ORDERED that every pleading, motion, letter, or other document + (with the exception of the petition and the post trial briefs, see + Rule 151(c)) submitted to the Court shall contain a certificate of + service as specified in Rule21(b), which shows that the party has + given a copy of that pleading, motion, letter or other document to all + other parties. +

+
+ +
+

+ (Signed) {trialInfo.judge.name} +
+ Trial Judge +

+
+
+
+ +

+ Trial Calendar: {trialInfo.city}, {trialInfo.state} +
+ + Date: {trialInfo.fullStartDate} + +

+ +

+ PRETRIAL MEMORANDUM FOR (Petitioner/Respondent) +
+ Please type or print legibly +
+ (This form may be expanded as necessary) +

+
+

+ NAME OF CASE: +

+

+ DOCKET NO(S).: +

+
+
+ +

+ ATTORNEYS: +

+
+

+ Petitioner: ____________________________________ +
+ Tel No.: ______________________________________ +

+

+ Respondent: ____________________________________ +
+ Tel No.: ________________________________________ +

+
+
+ +

+ AMOUNTS IN DISPUTE: +

+

+ Year(s)/Period(s) + + Deficiencies/Liabilities + + + Additions/Penalties + +

+

+ STATUS OF CASE: +

+

+ Probable Settlement________ + Probable Trial________ + Definite Trial________ +

+

+ + CURRENT ESTIMATE OF TRIAL TIME: + + __________________________________________ +

+

+ MOTIONS YOUR EXPECT TO MAKE: +
+ (Title and brief description) +

+

+ + STATUS OF STIPULATION OF FACTS: + +

+ +

+ Completed________ + In Process________ +

+

+ ISSUES: +

+ +
+
+ +

+ + WITNESS(ES) YOU EXPECT TO CALL: + +
+ (Name and brief summary of expected testimony) +

+

+ SUMMARY OF FACTS: +
+ (Attach separate pages, if necessary, to inform the Court of facts in + chronological narrative form) +

+ +

+ + BRIEF SYNOPSIS OF LEGAL AUTHORITIES: + +
+ (Attach separate pages, if necessary, to discuss fully your legal + position) +

+ +

+ EVIDENTIARY PROBLEMS: +

+ +
+

+ Date: _________________________ +

+

+ ________________________________________ +
+ Petitioner/ Respondent +

+
+
+ +
+

Trial Judge:

+ +

+ + {trialInfo.judge.name} +
+ United States Tax Court +
+ 400 Second Street, N.W. +
+ Washington, D.C. 20217 +
+ (202) 521-0700 +
+

+
+
+ + ); +}; + +export default StandingPretrialOrder; diff --git a/shared/src/business/utilities/pdfGenerator/documentTemplates/StandingPretrialOrder.test.js b/shared/src/business/utilities/pdfGenerator/documentTemplates/StandingPretrialOrder.test.js new file mode 100644 index 00000000000..1074ba9b2c2 --- /dev/null +++ b/shared/src/business/utilities/pdfGenerator/documentTemplates/StandingPretrialOrder.test.js @@ -0,0 +1,60 @@ +const React = require('react'); +const StandingPretrialOrder = require('./StandingPretrialOrder.jsx').default; +const { mount, shallow } = require('enzyme'); + +describe('StandingPretrialOrder', () => { + let options; + let trialInfo; + + beforeEach(() => { + options = { + caseCaptionExtension: 'Petitioner(s)', + caseTitle: 'Test Petitioner', + docketNumberWithSuffix: '123-45S', + }; + + trialInfo = { + city: 'Some City', + fullStartDate: 'Friday May 8, 2020', + judge: { + name: 'Test Judge', + }, + state: 'TEST STATE', + }; + }); + + it('renders a document header with case information', () => { + const wrapper = mount( + , + ); + + expect(wrapper.find('#caption-title').text()).toEqual(options.caseTitle); + expect(wrapper.find('#caption-extension').text()).toEqual( + options.caseCaptionExtension, + ); + expect(wrapper.find('#docket-number').text()).toEqual( + `Docket Number ${options.docketNumberWithSuffix}`, + ); + }); + + it('renders a document with trial information', () => { + const wrapper = shallow( + , + ); + expect(wrapper.text()).toContain(trialInfo.fullStartDate); + expect(wrapper.text()).toContain(trialInfo.city); + expect(wrapper.text()).toContain(trialInfo.state); + expect(wrapper.text()).toContain(trialInfo.judge.name); + }); + + it('renders a document with a served date', () => { + const wrapper = shallow( + , + ); + expect(wrapper.find('#served-stamp').text()).toEqual('Served 02/02/2020'); + }); +}); diff --git a/shared/src/persistence/dynamo/cases/updateCase.js b/shared/src/persistence/dynamo/cases/updateCase.js index 1d5c3874350..be79a9e5a50 100644 --- a/shared/src/persistence/dynamo/cases/updateCase.js +++ b/shared/src/persistence/dynamo/cases/updateCase.js @@ -3,15 +3,15 @@ const diff = require('diff-arrays-of-objects'); const { updateWorkItemAssociatedJudge, } = require('../workitems/updateWorkItemAssociatedJudge'); -const { - updateWorkItemCaseCaptionNames, -} = require('../workitems/updateWorkItemCaseCaptionNames'); const { updateWorkItemCaseIsInProgress, } = require('../workitems/updateWorkItemCaseIsInProgress'); const { updateWorkItemCaseStatus, } = require('../workitems/updateWorkItemCaseStatus'); +const { + updateWorkItemCaseTitle, +} = require('../workitems/updateWorkItemCaseTitle'); const { updateWorkItemDocketNumberSuffix, } = require('../workitems/updateWorkItemDocketNumberSuffix'); @@ -188,11 +188,9 @@ exports.updateCase = async ({ applicationContext, caseToUpdate }) => { } if (oldCase.caseCaption !== caseToUpdate.caseCaption) { requests.push( - updateWorkItemCaseCaptionNames({ + updateWorkItemCaseTitle({ applicationContext, - caseCaptionNames: Case.getCaseCaptionNames( - caseToUpdate.caseCaption, - ), + caseTitle: Case.getCaseTitle(caseToUpdate.caseCaption), workItemId, }), ); diff --git a/shared/src/persistence/dynamo/cases/updateCase.test.js b/shared/src/persistence/dynamo/cases/updateCase.test.js index 9af0be8e3d1..62570e2e40f 100644 --- a/shared/src/persistence/dynamo/cases/updateCase.test.js +++ b/shared/src/persistence/dynamo/cases/updateCase.test.js @@ -82,7 +82,7 @@ describe('updateCase', () => { applicationContext, caseToUpdate: { associatedJudge: 'Judge Buch', - caseCaption: 'New caption', + caseCaption: 'Johnny Joe Jacobson, Petitioner', caseId: '123', docketNumber: '101-18', docketNumberSuffix: 'W', @@ -110,7 +110,7 @@ describe('updateCase', () => { applicationContext.getDocumentClient().update.mock.calls[1][0], ).toMatchObject({ ExpressionAttributeValues: { - ':caseCaptionNames': 'New caption', + ':caseTitle': 'Johnny Joe Jacobson', }, }); expect( diff --git a/shared/src/persistence/dynamo/users/createUser.js b/shared/src/persistence/dynamo/users/createUser.js index 9b7544daa37..610bd5778a7 100644 --- a/shared/src/persistence/dynamo/users/createUser.js +++ b/shared/src/persistence/dynamo/users/createUser.js @@ -69,6 +69,10 @@ exports.createUserRecords = async ({ applicationContext, user, userId }) => { exports.createUser = async ({ applicationContext, user }) => { let userId; + let userPoolId = + user.role === User.ROLES.irsSuperuser + ? process.env.USER_POOL_IRS_ID + : process.env.USER_POOL_ID; try { const response = await applicationContext @@ -94,7 +98,7 @@ exports.createUser = async ({ applicationContext, user }) => { Value: user.name, }, ], - UserPoolId: process.env.USER_POOL_ID, + UserPoolId: userPoolId, Username: user.email, }) .promise(); @@ -104,7 +108,7 @@ exports.createUser = async ({ applicationContext, user }) => { const response = await applicationContext .getCognito() .adminGetUser({ - UserPoolId: process.env.USER_POOL_ID, + UserPoolId: userPoolId, Username: user.email, }) .promise(); @@ -118,7 +122,7 @@ exports.createUser = async ({ applicationContext, user }) => { Value: user.role, }, ], - UserPoolId: process.env.USER_POOL_ID, + UserPoolId: userPoolId, Username: response.Username, }) .promise(); diff --git a/shared/src/persistence/dynamo/workitems/updateWorkItemCaseCaptionNames.js b/shared/src/persistence/dynamo/workitems/updateWorkItemCaseTitle.js similarity index 64% rename from shared/src/persistence/dynamo/workitems/updateWorkItemCaseCaptionNames.js rename to shared/src/persistence/dynamo/workitems/updateWorkItemCaseTitle.js index 6ed17e011b0..47a6e356b42 100644 --- a/shared/src/persistence/dynamo/workitems/updateWorkItemCaseCaptionNames.js +++ b/shared/src/persistence/dynamo/workitems/updateWorkItemCaseTitle.js @@ -1,8 +1,8 @@ const client = require('../../dynamodbClientService'); -exports.updateWorkItemCaseCaptionNames = async ({ +exports.updateWorkItemCaseTitle = async ({ applicationContext, - caseCaptionNames, + caseTitle, workItemId, }) => { const workItems = await client.query({ @@ -17,22 +17,22 @@ exports.updateWorkItemCaseCaptionNames = async ({ applicationContext, }); - const updateCaseCaptionNames = workItem => { + const updateCaseTitle = workItem => { return client.update({ ExpressionAttributeNames: { - '#caseCaptionNames': 'caseCaptionNames', + '#caseTitle': 'caseTitle', }, ExpressionAttributeValues: { - ':caseCaptionNames': caseCaptionNames, + ':caseTitle': caseTitle, }, Key: { pk: workItem.pk, sk: workItem.sk, }, - UpdateExpression: 'SET #caseCaptionNames = :caseCaptionNames', + UpdateExpression: 'SET #caseTitle = :caseTitle', applicationContext, }); }; - await Promise.all(workItems.map(updateCaseCaptionNames)); + await Promise.all(workItems.map(updateCaseTitle)); }; diff --git a/shared/src/persistence/elasticsearch/bulkIndexRecords.js b/shared/src/persistence/elasticsearch/bulkIndexRecords.js index 0092414613b..2ba55c32bb5 100644 --- a/shared/src/persistence/elasticsearch/bulkIndexRecords.js +++ b/shared/src/persistence/elasticsearch/bulkIndexRecords.js @@ -1,3 +1,5 @@ +const { getIndexNameForRecord } = require('./getIndexNameForRecord'); + exports.bulkIndexRecords = async ({ applicationContext, records }) => { const searchClient = applicationContext.getSearchClient(); @@ -5,10 +7,17 @@ exports.bulkIndexRecords = async ({ applicationContext, records }) => { .map(record => ({ ...record.dynamodb.NewImage, })) - .flatMap(doc => [ - { index: { _id: `${doc.pk.S}_${doc.sk.S}`, _index: 'efcms' } }, - doc, - ]); + .flatMap(doc => { + const index = getIndexNameForRecord(doc); + + if (index) { + return [ + { index: { _id: `${doc.pk.S}_${doc.sk.S}`, _index: index } }, + doc, + ]; + } + }) + .filter(item => item); const response = await searchClient.bulk({ body, diff --git a/shared/src/persistence/elasticsearch/caseAdvancedSearch.js b/shared/src/persistence/elasticsearch/caseAdvancedSearch.js index 21750d40b87..34b6713384c 100644 --- a/shared/src/persistence/elasticsearch/caseAdvancedSearch.js +++ b/shared/src/persistence/elasticsearch/caseAdvancedSearch.js @@ -40,7 +40,7 @@ exports.caseAdvancedSearch = async ({ applicationContext, searchTerms }) => { }, size: 5000, }, - index: 'efcms', + index: 'efcms-case', }, }) ).results; @@ -66,7 +66,7 @@ exports.caseAdvancedSearch = async ({ applicationContext, searchTerms }) => { }, }, }, - index: 'efcms', + index: 'efcms-case', }, }) ).results; diff --git a/shared/src/persistence/elasticsearch/casePublicSearch.js b/shared/src/persistence/elasticsearch/casePublicSearch.js index 9c67e039470..9b4de89239c 100644 --- a/shared/src/persistence/elasticsearch/casePublicSearch.js +++ b/shared/src/persistence/elasticsearch/casePublicSearch.js @@ -51,7 +51,7 @@ exports.casePublicSearch = async ({ }, size: 5000, }, - index: 'efcms', + index: 'efcms-case', }, }) ).results; @@ -76,7 +76,7 @@ exports.casePublicSearch = async ({ }, }, }, - index: 'efcms', + index: 'efcms-case', }, }) ).results; diff --git a/shared/src/persistence/elasticsearch/fetchPendingItems.js b/shared/src/persistence/elasticsearch/fetchPendingItems.js index ad62ebdcc11..e8b63cca987 100644 --- a/shared/src/persistence/elasticsearch/fetchPendingItems.js +++ b/shared/src/persistence/elasticsearch/fetchPendingItems.js @@ -15,7 +15,7 @@ exports.fetchPendingItems = async ({ applicationContext, judge, source }) => { }, size: 5000, }, - index: 'efcms', + index: 'efcms-case', }; if (judge) { diff --git a/shared/src/persistence/elasticsearch/getBlockedCases.js b/shared/src/persistence/elasticsearch/getBlockedCases.js index 7e95d4ba8d5..78924214379 100644 --- a/shared/src/persistence/elasticsearch/getBlockedCases.js +++ b/shared/src/persistence/elasticsearch/getBlockedCases.js @@ -44,7 +44,7 @@ exports.getBlockedCases = async ({ applicationContext, trialLocation }) => { }, size: 5000, }, - index: 'efcms', + index: 'efcms-case', }, }); diff --git a/shared/src/persistence/elasticsearch/getCaseInventoryReport.js b/shared/src/persistence/elasticsearch/getCaseInventoryReport.js index e23e6620bdf..c37168a8562 100644 --- a/shared/src/persistence/elasticsearch/getCaseInventoryReport.js +++ b/shared/src/persistence/elasticsearch/getCaseInventoryReport.js @@ -49,7 +49,7 @@ exports.getCaseInventoryReport = async ({ size, sort: [{ 'sortableDocketNumber.N.keyword': { order: 'asc' } }], }, - index: 'efcms', + index: 'efcms-case', }; if (associatedJudge) { diff --git a/shared/src/persistence/elasticsearch/getIndexMappingFields.js b/shared/src/persistence/elasticsearch/getIndexMappingFields.js new file mode 100644 index 00000000000..1ab27018cbd --- /dev/null +++ b/shared/src/persistence/elasticsearch/getIndexMappingFields.js @@ -0,0 +1,9 @@ +exports.getIndexMappingFields = async ({ applicationContext, index }) => { + const searchClient = applicationContext.getSearchClient(); + + const indexMapping = await searchClient.indices.getMapping({ + index, + }); + + return indexMapping.efcms.mappings.properties; +}; diff --git a/shared/src/persistence/elasticsearch/getIndexMappingLimit.js b/shared/src/persistence/elasticsearch/getIndexMappingLimit.js new file mode 100644 index 00000000000..dd28577a04f --- /dev/null +++ b/shared/src/persistence/elasticsearch/getIndexMappingLimit.js @@ -0,0 +1,9 @@ +exports.getIndexMappingLimit = async ({ applicationContext, index }) => { + const searchClient = applicationContext.getSearchClient(); + + const indexSettings = await searchClient.indices.getSettings({ + index, + }); + + return indexSettings.efcms.settings.index.mapping.total_fields.limit; +}; diff --git a/shared/src/persistence/elasticsearch/getIndexNameForRecord.js b/shared/src/persistence/elasticsearch/getIndexNameForRecord.js new file mode 100644 index 00000000000..616acfa8a28 --- /dev/null +++ b/shared/src/persistence/elasticsearch/getIndexNameForRecord.js @@ -0,0 +1,32 @@ +exports.getIndexNameForRecord = record => { + let index = null; + + const userEntityNames = [ + 'User', + 'PrivatePractitioner', + 'IrsPractitioner', + 'Practitioner', + ]; + + const isRecordOfType = (record, type) => { + if (record.entityName && record.entityName.S) { + if (type === 'User' && userEntityNames.includes(record.entityName.S)) { + return true; + } + + if (record.entityName.S === type) { + return true; + } + } + }; + + if (isRecordOfType(record, 'Case')) { + index = 'efcms-case'; + } else if (isRecordOfType(record, 'Document')) { + index = 'efcms-document'; + } else if (isRecordOfType(record, 'User')) { + index = 'efcms-user'; + } + + return index; +}; diff --git a/shared/src/persistence/elasticsearch/getIndexNameForRecord.test.js b/shared/src/persistence/elasticsearch/getIndexNameForRecord.test.js new file mode 100644 index 00000000000..8a69246ee06 --- /dev/null +++ b/shared/src/persistence/elasticsearch/getIndexNameForRecord.test.js @@ -0,0 +1,76 @@ +const { getIndexNameForRecord } = require('./getIndexNameForRecord'); + +describe('getIndexNameForRecord', () => { + it('returns null as a default', () => { + const record = {}; + + const result = getIndexNameForRecord(record); + expect(result).toEqual(null); + }); + + it('returns efcms-case for Case records', () => { + const record = { + entityName: { + S: 'Case', + }, + }; + + const result = getIndexNameForRecord(record); + expect(result).toEqual('efcms-case'); + }); + + it('returns efcms-document for Document records', () => { + const record = { + entityName: { + S: 'Document', + }, + }; + + const result = getIndexNameForRecord(record); + expect(result).toEqual('efcms-document'); + }); + + it('returns efcms-user for User records', () => { + const record = { + entityName: { + S: 'User', + }, + }; + + const result = getIndexNameForRecord(record); + expect(result).toEqual('efcms-user'); + }); + + it('returns efcms-user for Practitioner records', () => { + const record = { + entityName: { + S: 'Practitioner', + }, + }; + + const result = getIndexNameForRecord(record); + expect(result).toEqual('efcms-user'); + }); + + it('returns efcms-user for PrivatePractitioner records', () => { + const record = { + entityName: { + S: 'PrivatePractitioner', + }, + }; + + const result = getIndexNameForRecord(record); + expect(result).toEqual('efcms-user'); + }); + + it('returns efcms-user for IrsPractitioner records', () => { + const record = { + entityName: { + S: 'IrsPractitioner', + }, + }; + + const result = getIndexNameForRecord(record); + expect(result).toEqual('efcms-user'); + }); +}); diff --git a/shared/src/persistence/elasticsearch/getPractitionersByName.js b/shared/src/persistence/elasticsearch/getPractitionersByName.js index 1d14d697d3c..03d3ee616cb 100644 --- a/shared/src/persistence/elasticsearch/getPractitionersByName.js +++ b/shared/src/persistence/elasticsearch/getPractitionersByName.js @@ -66,7 +66,7 @@ exports.getPractitionersByName = async ({ applicationContext, name }) => { }, size: 5000, }, - index: 'efcms', + index: 'efcms-user', }, }) ).results; @@ -88,7 +88,7 @@ exports.getPractitionersByName = async ({ applicationContext, name }) => { }, size: 5000, }, - index: 'efcms', + index: 'efcms-user', }, }) ).results; diff --git a/shared/src/persistence/elasticsearch/indexRecord.js b/shared/src/persistence/elasticsearch/indexRecord.js index b47e59a81d7..11253fd4e93 100644 --- a/shared/src/persistence/elasticsearch/indexRecord.js +++ b/shared/src/persistence/elasticsearch/indexRecord.js @@ -1,4 +1,5 @@ const AWS = require('aws-sdk'); +const { getIndexNameForRecord } = require('./getIndexNameForRecord'); exports.indexRecord = async ({ applicationContext, @@ -7,14 +8,17 @@ exports.indexRecord = async ({ record, }) => { const searchClient = applicationContext.getSearchClient(); + const index = getIndexNameForRecord(fullRecord); - const body = isAlreadyMarshalled - ? fullRecord - : { ...AWS.DynamoDB.Converter.marshall(fullRecord) }; + if (index) { + const body = isAlreadyMarshalled + ? fullRecord + : { ...AWS.DynamoDB.Converter.marshall(fullRecord) }; - await searchClient.index({ - body, - id: `${record.recordPk}_${record.recordSk}`, - index: 'efcms', - }); + await searchClient.index({ + body, + id: `${record.recordPk}_${record.recordSk}`, + index, + }); + } }; diff --git a/shared/src/persistence/elasticsearch/orderKeywordSearch.js b/shared/src/persistence/elasticsearch/orderKeywordSearch.js index b18b00c6264..73a7bf1f9f9 100644 --- a/shared/src/persistence/elasticsearch/orderKeywordSearch.js +++ b/shared/src/persistence/elasticsearch/orderKeywordSearch.js @@ -12,16 +12,21 @@ exports.orderKeywordSearch = async ({ }) => { const sourceFields = [ 'caseCaption', - 'documentContents', - 'docketNumber', - 'documentTitle', - 'docketNumberSuffix', + 'caseId', 'contactPrimary', 'contactSecondary', + 'docketNumber', + 'docketNumberSuffix', + 'documentContents', + 'numberOfPages', + 'documentId', + 'documentTitle', 'filingDate', + 'irsPractitioners', + 'isSealed', + 'privatePractitioners', + 'sealedDate', 'signedJudgeName', - 'caseId', - 'documentId', ]; const queryParams = [ @@ -84,8 +89,8 @@ exports.orderKeywordSearch = async ({ if (startDate && endDate) { queryParams.push({ range: { - 'receivedAt.S': { - format: 'yyyy-MM-dd', + 'filingDate.S': { + format: 'strict_date_time', // ISO-8601 time stamp gte: startDate, lte: endDate, }, @@ -112,7 +117,7 @@ exports.orderKeywordSearch = async ({ }, size: 5000, }, - index: 'efcms', + index: 'efcms-document', }; const { results } = await search({ diff --git a/shared/src/persistence/elasticsearch/orderKeywordSearch.test.js b/shared/src/persistence/elasticsearch/orderKeywordSearch.test.js index 1ecfecab0ba..75405b274b3 100644 --- a/shared/src/persistence/elasticsearch/orderKeywordSearch.test.js +++ b/shared/src/persistence/elasticsearch/orderKeywordSearch.test.js @@ -133,19 +133,19 @@ describe('orderKeywordSearch', () => { it('does a date range search for filing / received date', async () => { await orderKeywordSearch({ applicationContext, - endDate: '2020-02-20', + endDate: '2020-02-21T04:59:59.999Z', orderEventCodes, - startDate: '2020-02-20', + startDate: '2020-02-20T05:00:00.000Z', }); expect(searchStub.mock.calls[0][0].body.query.bool.must).toEqual([ ...baseQueryParams, { range: { - 'receivedAt.S': { - format: 'yyyy-MM-dd', - gte: '2020-02-20', - lte: '2020-02-20', + 'filingDate.S': { + format: 'strict_date_time', + gte: '2020-02-20T05:00:00.000Z', + lte: '2020-02-21T04:59:59.999Z', }, }, }, @@ -156,7 +156,7 @@ describe('orderKeywordSearch', () => { await orderKeywordSearch({ applicationContext, orderEventCodes, - startDate: '2020-02-20', + startDate: '2020-02-20T00:00:00.000Z', }); expect(searchStub.mock.calls[0][0].body.query.bool.must).toEqual( @@ -167,7 +167,7 @@ describe('orderKeywordSearch', () => { it('does a NOT search for date range if just given endDate', async () => { await orderKeywordSearch({ applicationContext, - endDate: '2020-02-20', + endDate: '2020-02-20T04:59:59.999Z', orderEventCodes, }); diff --git a/shared/src/persistence/s3/getDocument.js b/shared/src/persistence/s3/getDocument.js index d05673d03a0..12d07ff06e3 100644 --- a/shared/src/persistence/s3/getDocument.js +++ b/shared/src/persistence/s3/getDocument.js @@ -1,3 +1,5 @@ +const { getPdfFromUrl } = require('./getPdfFromUrl'); + const getDownloadPolicy = async ({ applicationContext, caseId, @@ -23,26 +25,27 @@ exports.getDocument = async ({ caseId, documentId, protocol, + useTempBucket, }) => { // TODO: Fix protocol flag if (protocol === 'S3') { // TODO: should this be in the persistence gateway? const S3 = applicationContext.getStorageClient(); - return S3.getObject({ - Bucket: applicationContext.environment.documentsBucketName, - Key: documentId, - }); + return ( + await S3.getObject({ + Bucket: useTempBucket + ? applicationContext.getTempDocumentsBucketName() + : applicationContext.getDocumentsBucketName(), + Key: documentId, + }).promise() + ).Body; } else { const url = await getDownloadPolicy({ applicationContext, caseId, documentId, }); - const { data: fileBlob } = await applicationContext.getHttpClient()({ - method: 'GET', - responseType: 'blob', - url, - }); - return new Blob([fileBlob], { type: 'application/pdf' }); + + return await getPdfFromUrl({ applicationContext, url }); } }; diff --git a/shared/src/persistence/s3/getDocument.test.js b/shared/src/persistence/s3/getDocument.test.js index 7130a270876..8f4c9a385aa 100644 --- a/shared/src/persistence/s3/getDocument.test.js +++ b/shared/src/persistence/s3/getDocument.test.js @@ -2,29 +2,41 @@ const { applicationContext, } = require('../../business/test/createTestApplicationContext'); const { getDocument } = require('./getDocument'); - +const { getPdfFromUrl } = require('./getPdfFromUrl'); const BLOB_DATA = 'abc'; +jest.mock('./getPdfFromUrl', () => ({ + getPdfFromUrl: jest.fn().mockReturnValue({ + name: 'mockfile.pdf', + }), +})); describe('getDocument', () => { - it('returns the expected file Blob which is returned from persistence', async () => { + it('should return a file from the provided url when protocol is not provided', async () => { + const mockPdfUrl = 'www.example.com'; applicationContext.getHttpClient.mockImplementation(() => { - const fun = () => ({ + const httpClient = () => ({ data: BLOB_DATA, }); - fun.get = () => ({ - data: 'http://localhost', + httpClient.get = () => ({ + data: { url: mockPdfUrl }, }); - return fun; + return httpClient; }); const result = await getDocument({ applicationContext, }); - expect(result).toEqual(new Blob([BLOB_DATA], { type: 'application/pdf' })); + expect(getPdfFromUrl.mock.calls[0][0]).toMatchObject({ url: mockPdfUrl }); + expect(result).toEqual({ name: 'mockfile.pdf' }); }); it('calls S3.getObject when S3 protocol is set', async () => { + applicationContext.getStorageClient.mockReturnValue({ + getObject: jest.fn().mockReturnValue({ + promise: () => ({ Body: null }), + }), + }); await getDocument({ applicationContext, protocol: 'S3', @@ -32,4 +44,44 @@ describe('getDocument', () => { expect(applicationContext.getStorageClient().getObject).toHaveBeenCalled(); }); + + it('retrieves from the temp bucket when S3 protocol is set and useTempBucket is true', async () => { + const tempBucketName = 'tempBucket'; + applicationContext.getTempDocumentsBucketName.mockReturnValue( + tempBucketName, + ); + applicationContext.getStorageClient().getObject.mockReturnValue({ + promise: async () => ({ + Body: '', + }), + }); + + await getDocument({ + applicationContext, + protocol: 'S3', + useTempBucket: true, + }); + + expect( + applicationContext.getStorageClient().getObject, + ).toHaveBeenCalledWith({ Bucket: tempBucketName }); + }); + + it('retrieves from the documents bucket by default when S3 protocol is set', async () => { + applicationContext.getStorageClient().getObject.mockReturnValue({ + promise: async () => ({ + Body: '', + }), + }); + + await getDocument({ + applicationContext, + protocol: 'S3', + }); + + // expect( + // applicationContext.getStorageClient().getObject, + // ).toHaveBeenCalledWith({ Bucket: 'DocumentBucketName' }); + expect(); + }); }); diff --git a/shared/src/persistence/s3/getPdfFromUrl.js b/shared/src/persistence/s3/getPdfFromUrl.js new file mode 100644 index 00000000000..0e17550c78e --- /dev/null +++ b/shared/src/persistence/s3/getPdfFromUrl.js @@ -0,0 +1,9 @@ +exports.getPdfFromUrl = async ({ applicationContext, url }) => { + const { data: fileBlob } = await applicationContext.getHttpClient()({ + method: 'GET', + responseType: 'blob', + url, + }); + + return new Blob([fileBlob], { type: 'application/pdf' }); +}; diff --git a/shared/src/persistence/s3/getPdfFromUrl.test.js b/shared/src/persistence/s3/getPdfFromUrl.test.js new file mode 100644 index 00000000000..52199ec1bf5 --- /dev/null +++ b/shared/src/persistence/s3/getPdfFromUrl.test.js @@ -0,0 +1,27 @@ +const { + applicationContext, +} = require('../../business/test/createTestApplicationContext'); +const { getPdfFromUrl } = require('./getPdfFromUrl'); + +describe('getPdfFromUrl', () => { + it('should return the file from the provided url in persistence', async () => { + const mockPdfUrl = 'www.example.com'; + const BLOB_DATA = 'abc'; + applicationContext.getHttpClient.mockImplementation(() => { + const httpClient = () => ({ + data: BLOB_DATA, + }); + httpClient.get = () => ({ + data: { url: mockPdfUrl }, + }); + + return httpClient; + }); + + const result = await getPdfFromUrl({ + applicationContext, + }); + + expect(result).toEqual(new Blob([BLOB_DATA], { type: 'application/pdf' })); + }); +}); diff --git a/shared/src/persistence/s3/getUploadPolicy.js b/shared/src/persistence/s3/getUploadPolicy.js index 7f2def9aaca..ed8cc569390 100644 --- a/shared/src/persistence/s3/getUploadPolicy.js +++ b/shared/src/persistence/s3/getUploadPolicy.js @@ -1,4 +1,4 @@ -exports.MAX_FILE_SIZE_MB = 500; // megabytes +exports.MAX_FILE_SIZE_MB = 250; // megabytes exports.MAX_FILE_SIZE_BYTES = exports.MAX_FILE_SIZE_MB * 1024 * 1024; // bytes -> megabytes /** diff --git a/shared/src/persistence/s3/zipDocuments.js b/shared/src/persistence/s3/zipDocuments.js index a4a41024dac..0e6b2917196 100644 --- a/shared/src/persistence/s3/zipDocuments.js +++ b/shared/src/persistence/s3/zipDocuments.js @@ -41,15 +41,15 @@ exports.zipDocuments = ({ Bucket: destinationBucket, Key: zipName, }; - s3Client.upload(params, function () { - resolve(); - }); + s3Client.upload(params, () => resolve()); pass.on('error', reject); return pass; }; + const passThrough = uploadFromStream(s3Client); + s3Zip .setArchiverOptions({ gzip: false }) .archive( @@ -67,6 +67,6 @@ exports.zipDocuments = ({ extraFiles, extraFileNames, ) - .pipe(uploadFromStream(s3Client)); + .pipe(passThrough); }); }; diff --git a/shared/src/persistence/s3/zipDocuments.test.js b/shared/src/persistence/s3/zipDocuments.test.js index 4833ea16b60..5c4ebe06110 100644 --- a/shared/src/persistence/s3/zipDocuments.test.js +++ b/shared/src/persistence/s3/zipDocuments.test.js @@ -11,24 +11,14 @@ describe('zipDocuments', () => { return fs.readFileSync(testAssetsPath + name); }; - const s3ClientMock = { - getObject: () => { - return { - createReadStream: () => { - return { - on: () => null, - pipe: () => null, - promise: async () => ({ - Body: testAsset('sample.pdf'), - }), - }; - }, - }; - }, - upload: () => null, - }; - - applicationContext.getStorageClient.mockImplementation(s3ClientMock); + beforeAll(() => { + const s3ClientMock = { + upload: (params, cb) => { + return cb(true); + }, + }; + applicationContext.getStorageClient.mockReturnValue(s3ClientMock); + }); it('calls the s3 archive returning a promise', async () => { const zipProcess = zipDocuments({ diff --git a/shared/src/proxies/courtIssuedOrder/createCourtIssuedOrderPdfFromHtmlProxy.js b/shared/src/proxies/courtIssuedOrder/createCourtIssuedOrderPdfFromHtmlProxy.js index 990284b3821..cda5976b036 100644 --- a/shared/src/proxies/courtIssuedOrder/createCourtIssuedOrderPdfFromHtmlProxy.js +++ b/shared/src/proxies/courtIssuedOrder/createCourtIssuedOrderPdfFromHtmlProxy.js @@ -21,11 +21,5 @@ exports.createCourtIssuedOrderPdfFromHtmlInteractor = ({ htmlString, }, endpoint: '/api/court-issued-order', - headers: { - Accept: 'application/pdf', - }, - options: { - responseType: 'blob', - }, }); }; diff --git a/shared/src/proxies/generateDocketRecordPdfProxy.js b/shared/src/proxies/generateDocketRecordPdfProxy.js index be655941e20..5beda882821 100644 --- a/shared/src/proxies/generateDocketRecordPdfProxy.js +++ b/shared/src/proxies/generateDocketRecordPdfProxy.js @@ -21,9 +21,5 @@ exports.generateDocketRecordPdfInteractor = ({ docketRecordSort, }, endpoint: '/api/docket-record-pdf', - headers: { - Accept: 'application/pdf', - }, - options: { responseType: 'blob' }, }); }; diff --git a/shared/src/proxies/generatePrintableFilingReceiptProxy.js b/shared/src/proxies/generatePrintableFilingReceiptProxy.js index 75bc53b745c..1e042a749d8 100644 --- a/shared/src/proxies/generatePrintableFilingReceiptProxy.js +++ b/shared/src/proxies/generatePrintableFilingReceiptProxy.js @@ -5,17 +5,20 @@ const { post } = require('./requests'); * * @param {object} providers the providers object * @param {object} providers.applicationContext the application context - * @param {string} providers.documents the documents filed + * @param {string} providers.caseId the id of the case in which the documents were filed + * @param {object} providers.documentsFiled the documents filed * @returns {Promise<*>} the promise of the api call */ exports.generatePrintableFilingReceiptInteractor = ({ applicationContext, - documents, + caseId, + documentsFiled, }) => { return post({ applicationContext, body: { - documents, + caseId, + documentsFiled, }, endpoint: '/documents/filing-receipt-pdf', }); diff --git a/shared/src/proxies/public/generatePublicDocketRecordPdfProxy.js b/shared/src/proxies/public/generatePublicDocketRecordPdfProxy.js index 5ed80c4b791..55c51406326 100644 --- a/shared/src/proxies/public/generatePublicDocketRecordPdfProxy.js +++ b/shared/src/proxies/public/generatePublicDocketRecordPdfProxy.js @@ -18,9 +18,5 @@ exports.generatePublicDocketRecordPdfInteractor = ({ caseId, }, endpoint: `/public-api/cases/${caseId}/generate-docket-record`, - headers: { - Accept: 'application/pdf', - }, - options: { responseType: 'blob' }, }); }; diff --git a/shared/src/proxies/serveCourtIssuedDocumentProxy.js b/shared/src/proxies/serveCourtIssuedDocumentProxy.js index 1957d5bce05..796a35f0117 100644 --- a/shared/src/proxies/serveCourtIssuedDocumentProxy.js +++ b/shared/src/proxies/serveCourtIssuedDocumentProxy.js @@ -18,9 +18,5 @@ exports.serveCourtIssuedDocumentInteractor = ({ applicationContext, body: {}, endpoint: `/case-documents/${caseId}/${documentId}/serve-court-issued`, - headers: { - Accept: 'application/pdf', - }, - options: { responseType: 'blob' }, }); }; diff --git a/shared/src/proxies/trialSessions/generateTrialCalendarPdfProxy.js b/shared/src/proxies/trialSessions/generateTrialCalendarPdfProxy.js index 52b9ba1995d..79dc1242b90 100644 --- a/shared/src/proxies/trialSessions/generateTrialCalendarPdfProxy.js +++ b/shared/src/proxies/trialSessions/generateTrialCalendarPdfProxy.js @@ -18,9 +18,5 @@ exports.generateTrialCalendarPdfInteractor = ({ trialSessionId, }, endpoint: '/reports/trial-calendar-pdf', - headers: { - Accept: 'application/pdf', - }, - options: { responseType: 'blob' }, }); }; diff --git a/shared/src/proxies/trialSessions/runTrialSessionPlanningReportProxy.js b/shared/src/proxies/trialSessions/runTrialSessionPlanningReportProxy.js index c37bd86b6b1..372e406efc2 100644 --- a/shared/src/proxies/trialSessions/runTrialSessionPlanningReportProxy.js +++ b/shared/src/proxies/trialSessions/runTrialSessionPlanningReportProxy.js @@ -19,11 +19,5 @@ exports.runTrialSessionPlanningReportInteractor = ({ year, }, endpoint: '/reports/planning-report', - headers: { - Accept: 'application/pdf', - }, - options: { - responseType: 'blob', - }, }); }; diff --git a/shared/src/test/mockCase.js b/shared/src/test/mockCase.js index a38c1b1f72e..4bcdba6d96b 100644 --- a/shared/src/test/mockCase.js +++ b/shared/src/test/mockCase.js @@ -58,7 +58,14 @@ exports.MOCK_CASE_WITHOUT_PENDING = { caseId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', caseType: 'Other', contactPrimary: { + address1: '123 Main St', + city: 'Somewhere', + countryType: 'domestic', + email: 'petitioner@example.com', name: 'Test Petitioner', + phone: '1234567', + postalCode: '12345', + state: 'TN', title: 'Executor', }, docketNumber: '101-18', @@ -102,7 +109,14 @@ exports.MOCK_CASE_WITHOUT_PENDING = { exports.MOCK_CASE_WITHOUT_NOTICE = { caseId: 'c54ba5a9-b37b-479d-9201-067ec6e335bb', contactPrimary: { + address1: '123 Main St', + city: 'Somewhere', + countryType: 'domestic', + email: 'petitioner@example.com', name: 'Test Petitioner', + phone: '1234567', + postalCode: '12345', + state: 'TN', title: 'Executor', }, docketNumber: '101-18', diff --git a/shared/src/tools/generateMarkdownSchema.js b/shared/src/tools/generateMarkdownSchema.js index 217f324d39d..16f97f85fff 100644 --- a/shared/src/tools/generateMarkdownSchema.js +++ b/shared/src/tools/generateMarkdownSchema.js @@ -53,7 +53,7 @@ const { CaseDeadline } = require('../business/entities/CaseDeadline'); const { DocketRecord } = require('../business/entities/DocketRecord'); const { Document } = require('../business/entities/Document'); -exports.generateJsonFromSchema = (schema, entityName) => { +const generateJsonFromSchema = (schema, entityName) => { let described = schema.describe ? schema.describe().keys : schema; const fields = Object.keys(described); @@ -98,7 +98,6 @@ exports.generateJsonFromSchema = (schema, entityName) => { }); switch (type) { - default: case 'date': case 'boolean': case 'number': @@ -108,11 +107,22 @@ exports.generateJsonFromSchema = (schema, entityName) => { case 'string': if (rules && rules.length) { rules.forEach(({ args, name }) => { + let key, value; switch (name) { case 'pattern': result.push({ h5: 'Regex Pattern' }); result.push({ p: `\`${args.regex}\`` }); break; + case 'min': + [key, value] = Object.entries(args)[0]; + result.push({ h5: `Minimum ${key}` }); + result.push({ p: `\`${value}\`` }); + break; + case 'max': + [key, value] = Object.entries(args)[0]; + result.push({ h5: `Maximum ${key}` }); + result.push({ p: `\`${value}\`` }); + break; } }); } @@ -186,6 +196,8 @@ exports.generateJsonFromSchema = (schema, entityName) => { }); }); break; + default: + console.warn(`generateMarkdown: Unrecognized type "${type}"`); } return result; @@ -198,13 +210,15 @@ exports.generateJsonFromSchema = (schema, entityName) => { return jsonResult; }; -exports.generateMarkdownSchema = (entity, entityName) => { - const json = exports.generateJsonFromSchema(entity.getSchema(), entityName); +const generateMarkdownSchema = (entity, entityName) => { + const json = generateJsonFromSchema(entity.getSchema(), entityName); fs.writeFileSync(`./docs/entities/${entityName}.md`, json2md(json)); }; -exports.generateMarkdownSchema( +module.exports = { generateJsonFromSchema, generateMarkdownSchema }; + +generateMarkdownSchema( getNextFriendForIncompetentPersonContact({ countryType: 'domestic', isPaper: true, @@ -212,7 +226,7 @@ exports.generateMarkdownSchema( 'contacts/NextFriendForIncompetentPersonContact', ); -exports.generateMarkdownSchema( +generateMarkdownSchema( getNextFriendForMinorContact({ countryType: 'domestic', isPaper: true, @@ -220,7 +234,7 @@ exports.generateMarkdownSchema( 'contacts/NextFriendForMinorContact', ); -exports.generateMarkdownSchema( +generateMarkdownSchema( getPartnershipAsTaxMattersPartnerPrimaryContact({ countryType: 'domestic', isPaper: true, @@ -228,7 +242,7 @@ exports.generateMarkdownSchema( 'contacts/PartnershipAsTaxMattersPartnerContact', ); -exports.generateMarkdownSchema( +generateMarkdownSchema( getPartnershipBBAPrimaryContact({ countryType: 'domestic', isPaper: true, @@ -236,7 +250,7 @@ exports.generateMarkdownSchema( 'contacts/PartnershipBBAPrimaryContact', ); -exports.generateMarkdownSchema( +generateMarkdownSchema( getPartnershipOtherThanTaxMattersPrimaryContact({ countryType: 'domestic', isPaper: true, @@ -244,7 +258,7 @@ exports.generateMarkdownSchema( 'contacts/PartnershipOtherThanTaxMattersPrimaryContact', ); -exports.generateMarkdownSchema( +generateMarkdownSchema( getPetitionerConservatorContact({ countryType: 'domestic', isPaper: true, @@ -252,7 +266,7 @@ exports.generateMarkdownSchema( 'contacts/PetitionerConservatorContact', ); -exports.generateMarkdownSchema( +generateMarkdownSchema( getPetitionerCorporationContact({ countryType: 'domestic', isPaper: true, @@ -260,7 +274,7 @@ exports.generateMarkdownSchema( 'contacts/PetitionerCorporationContact', ); -exports.generateMarkdownSchema( +generateMarkdownSchema( getPetitionerCustodianContact({ countryType: 'domestic', isPaper: true, @@ -268,7 +282,7 @@ exports.generateMarkdownSchema( 'contacts/PetitionerCustodianContact', ); -exports.generateMarkdownSchema( +generateMarkdownSchema( getPetitionerDeceasedSpouseContact({ countryType: 'domestic', isPaper: true, @@ -276,7 +290,7 @@ exports.generateMarkdownSchema( 'contacts/PetitionerDeceasedSpouseContact', ); -exports.generateMarkdownSchema( +generateMarkdownSchema( getPetitionerEstateWithExecutorPrimaryContact({ countryType: 'domestic', isPaper: true, @@ -284,7 +298,7 @@ exports.generateMarkdownSchema( 'contacts/PetitionerEstateWithExecutorPrimaryContact', ); -exports.generateMarkdownSchema( +generateMarkdownSchema( getPetitionerGuardianContact({ countryType: 'domestic', isPaper: true, @@ -292,7 +306,7 @@ exports.generateMarkdownSchema( 'contacts/PetitionerGuardianContact', ); -exports.generateMarkdownSchema( +generateMarkdownSchema( getPetitionerIntermediaryContact({ countryType: 'domestic', isPaper: true, @@ -300,7 +314,7 @@ exports.generateMarkdownSchema( 'contacts/PetitionerIntermediaryContact', ); -exports.generateMarkdownSchema( +generateMarkdownSchema( getPetitionerPrimaryContact({ countryType: 'domestic', isPaper: true, @@ -308,7 +322,7 @@ exports.generateMarkdownSchema( 'contacts/PetitionerPrimaryContact', ); -exports.generateMarkdownSchema( +generateMarkdownSchema( getPetitionerSpouseContact({ countryType: 'domestic', isPaper: true, @@ -316,7 +330,7 @@ exports.generateMarkdownSchema( 'contacts/PetitionerSpouseContact', ); -exports.generateMarkdownSchema( +generateMarkdownSchema( getPetitionerTrustContact({ countryType: 'domestic', isPaper: true, @@ -324,7 +338,7 @@ exports.generateMarkdownSchema( 'contacts/PetitionerTrustContact', ); -exports.generateMarkdownSchema( +generateMarkdownSchema( getSurvivingSpouseContact({ countryType: 'domestic', isPaper: true, @@ -332,7 +346,7 @@ exports.generateMarkdownSchema( 'contacts/SurvivingSpouseContact', ); -exports.generateMarkdownSchema(Case, 'Case'); -exports.generateMarkdownSchema(CaseDeadline, 'CaseDeadline'); -exports.generateMarkdownSchema(DocketRecord, 'DocketRecord'); -exports.generateMarkdownSchema(Document, 'Document'); +generateMarkdownSchema(Case, 'Case'); +generateMarkdownSchema(CaseDeadline, 'CaseDeadline'); +generateMarkdownSchema(DocketRecord, 'DocketRecord'); +generateMarkdownSchema(Document, 'Document'); diff --git a/shared/src/utilities/JoiValidationDecorator.js b/shared/src/utilities/JoiValidationDecorator.js index ee20189f57d..72e567494a3 100644 --- a/shared/src/utilities/JoiValidationDecorator.js +++ b/shared/src/utilities/JoiValidationDecorator.js @@ -1,4 +1,5 @@ const joi = require('@hapi/joi'); +const { isEmpty } = require('lodash'); /** * @@ -102,13 +103,11 @@ function getFormattedValidationErrors(entity) { * * @param {Function} entityConstructor the entity constructor * @param {object} schema the joi validation schema - * @param {Function} customValidate a custom validation function * @param {object} errorToMessageMap the map of error fields and messages */ exports.joiValidationDecorator = function ( entityConstructor, schema, - customValidate, errorToMessageMap = {}, ) { if (!schema.validate && typeof schema === 'object') { @@ -128,14 +127,8 @@ exports.joiValidationDecorator = function ( }; entityConstructor.prototype.isValid = function isValid() { - return ( - !!schema.validate(this, { allowUnknown: true }).error === false && - (customValidate ? customValidate.call(this) : true) - ); - }; - - entityConstructor.prototype.getValidationError = function getValidationError() { - return schema.validate(this, { allowUnknown: true }).error; + const validationErrors = this.getFormattedValidationErrors(); + return isEmpty(validationErrors); }; entityConstructor.prototype.validate = function validate() { @@ -143,7 +136,9 @@ exports.joiValidationDecorator = function ( throw new Error( `The ${ entityConstructor.validationName || '' - } entity was invalid ${this.getValidationError()}`, + } entity was invalid ${JSON.stringify( + this.getFormattedValidationErrors(), + )}`, ); } return this; @@ -170,14 +165,6 @@ exports.joiValidationDecorator = function ( return errors; }; - entityConstructor.prototype.validateWithError = function validate(error) { - if (!this.isValid()) { - error.message = `${error.message} ${this.getValidationError()}`; - throw error; - } - return this; - }; - const toRawObjectPrototype = function () { return toRawObject(this); }; diff --git a/shared/src/utilities/JoiValidationDecorator.test.js b/shared/src/utilities/JoiValidationDecorator.test.js index c3e23226cd7..a7f2dc93afd 100644 --- a/shared/src/utilities/JoiValidationDecorator.test.js +++ b/shared/src/utilities/JoiValidationDecorator.test.js @@ -24,7 +24,6 @@ joiValidationDecorator( hasNickname: joi.boolean().required(), name: joi.string().required(), }), - undefined, MockEntity1.errorToMessageMap, ); @@ -44,11 +43,24 @@ const MockEntity2Schema = joi.object().keys({ obj1: joi.object().keys({ foo: joi.string().required() }).required(), }); -joiValidationDecorator(MockEntity2, MockEntity2Schema, undefined, { +joiValidationDecorator(MockEntity2, MockEntity2Schema, { arry1: 'That is required', foo: 'lend me some sugar', }); +const MockEntity3 = function (raw) { + this.anotherItem = raw.anotherItem; + this.mockEntity2 = new MockEntity2(raw.mockEntity2); +}; + +const MockEntity3Schema = joi.object().keys({ + anotherItem: joi.string().required(), +}); + +joiValidationDecorator(MockEntity3, MockEntity3Schema, { + anotherItem: 'Another item is required', +}); + describe('Joi Validation Decorator', () => { describe('validation errors with arrays', () => { it('returns validation errors', () => { @@ -81,6 +93,23 @@ describe('Joi Validation Decorator', () => { expect(joiGeneratedMessageNotFromErrorToMessageMap).toBeDefined(); }); + it('should correctly validate nested entities', () => { + const invalidEntity = new MockEntity3({ + anotherItem: 'this is another item', + }); + const errors = invalidEntity.getFormattedValidationErrors(); + expect(errors).toEqual({ + mockEntity2: { + arry1: 'That is required', + favoriteNumber: '"favoriteNumber" is required', + hasNickname: '"hasNickname" is required', + name: '"name" is required', + obj1: '"obj1" is required', + }, + }); + expect(invalidEntity.isValid()).toBe(false); + }); + it('should correctly return strings as items in an array of strings', () => { const obj = new MockEntity2({ arry1: [{ baz: 'foz', foo: 'bar' }], @@ -148,7 +177,7 @@ describe('Joi Validation Decorator', () => { } expect(error).toBeDefined(); - expect(error.message).toContain('ValidationError'); + expect(error.message).toContain('The MockEntity1 entity was invalid'); }); it('should return an empty array when calling validateRawCollection with an empty collection', () => { diff --git a/shared/src/utilities/dateSchema.js b/shared/src/utilities/dateSchema.js new file mode 100644 index 00000000000..13925c2f153 --- /dev/null +++ b/shared/src/utilities/dateSchema.js @@ -0,0 +1,8 @@ +const joi = require('@hapi/joi').extend(require('@hapi/joi-date')); +const { FORMATS } = require('../business/utilities/DateHandler'); + +exports.getTimestampSchema = () => { + // eslint-disable-next-line spellcheck/spell-checker + // TODO: remove FORMATS.YYYYMMDD from valid timestamp formats after devex task + return joi.date().iso().format([FORMATS.ISO, FORMATS.YYYYMMDD]); +}; diff --git a/shared/src/utilities/dateSchema.test.js b/shared/src/utilities/dateSchema.test.js new file mode 100644 index 00000000000..f8a99f13f8d --- /dev/null +++ b/shared/src/utilities/dateSchema.test.js @@ -0,0 +1,42 @@ +const { + createISODateString, + FORMATS, +} = require('../business/utilities/DateHandler'); +const { getTimestampSchema } = require('./dateSchema'); + +describe('joi validation of ISO-8601 timestamps', () => { + const schema = getTimestampSchema(); + + it(`validates ISO string generated by DateHandler which uses format ${FORMATS.ISO}`, () => { + const isoTimestamp = createISODateString(); // matches desired FORMATS.ISO + const results = schema.validate(isoTimestamp); + expect(results.error).toBeUndefined(); + }); + + it(`validates ISO string which uses format ${FORMATS.YYYYMMDD}`, () => { + const shortIsoTimestamp = '2020-05-04'; + const results = schema.validate(shortIsoTimestamp); + expect(results.error).toBeUndefined(); + }); + + describe('identifies as invalid a list of date formats which conform to ISO-8601 but are not valid for our application', () => { + const iso8601Invalid = [ + // '2020-05-03', // TODO: this will soon become invalid also. + '2020-05-04T19:40:23+00:00', + '20200504T194023Z', + '2020-W19', + '2020-W19-1', + '--05-04', + '2020068', + '2020-05-04 24:00:00:00.000', + '20130208T080910.123', + '2013-02-08 09:30:26.123+07', + ]; + for (const isoExample of iso8601Invalid) { + it(`detects ${isoExample} as invalid`, () => { + const result = schema.validate(isoExample); + expect(result.error.toString()).toMatch('ValidationError'); + }); + } + }); +}); diff --git a/web-api/check-elasticsearch-mappings.js b/web-api/check-elasticsearch-mappings.js deleted file mode 100644 index 4643f211d76..00000000000 --- a/web-api/check-elasticsearch-mappings.js +++ /dev/null @@ -1,75 +0,0 @@ -(async () => { - const AWS = require('aws-sdk'); - AWS.config.region = 'us-east-1'; - - const connectionClass = require('http-aws-es'); - const elasticsearch = require('elasticsearch'); - - AWS.config.httpOptions.timeout = 300000; - - const { EnvironmentCredentials } = AWS; - - const environment = { - elasticsearchEndpoint: process.env.ELASTICSEARCH_ENDPOINT, - region: 'us-east-1', - }; - - let searchClientCache; - if (process.env.ELASTICSEARCH_ENDPOINT.includes('localhost')) { - searchClientCache = new elasticsearch.Client({ - host: process.env.ELASTICSEARCH_ENDPOINT, - }); - } else { - searchClientCache = new elasticsearch.Client({ - amazonES: { - credentials: new EnvironmentCredentials('AWS'), - region: environment.region, - }, - apiVersion: '7.1', - connectionClass: connectionClass, - host: { - host: environment.elasticsearchEndpoint, - port: 443, - protocol: 'https', - }, - log: 'warning', - }); - } - - /** - * recursively searches the provided object for the provided key - * and returns the count of instances of that key - * - * @param {object} object the object to search - * @param {string} key the key to search for - * @returns {number} the total number of key matches - */ - function countValues(object, key) { - let count = 0; - Object.keys(object).some(function (k) { - if (k === key) { - count++; - } - if (object[k] && typeof object[k] === 'object') { - const countToAdd = countValues(object[k], key); - count = count + countToAdd; - } - }); - return count; - } - - const indexMapping = await searchClientCache.indices.getMapping({ - index: 'efcms', - }); - const fields = indexMapping.efcms.mappings.properties; - - let totalTypes = 0; - for (let field of Object.keys(fields)) { - const typeMatches = countValues(fields[field], 'type'); - if (typeMatches > 50) { - console.log('Mapping for object higher than 50:', field, typeMatches); - } - totalTypes += typeMatches; - } - console.log('Total mappings:', totalTypes); -})(); diff --git a/web-api/check-elasticsearch-mappings.sh b/web-api/check-elasticsearch-mappings.sh deleted file mode 100755 index e1b9aa60477..00000000000 --- a/web-api/check-elasticsearch-mappings.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash -e -ENV=$1 - -if [ $ENV == 'local' ] ; then - ELASTICSEARCH_ENDPOINT="localhost:9200" - export ELASTICSEARCH_ENDPOINT -else - pushd ./web-api/terraform/main - ../bin/deploy-init.sh "${1}" - ELASTICSEARCH_ENDPOINT="$(terraform output elasticsearch_endpoint)" - export ELASTICSEARCH_ENDPOINT - popd -fi - -node ./web-api/check-elasticsearch-mappings.js \ No newline at end of file diff --git a/web-api/delete-elasticsearch-index.js b/web-api/delete-elasticsearch-index.js index 0170fd4fd67..6cf4abfd23c 100644 --- a/web-api/delete-elasticsearch-index.js +++ b/web-api/delete-elasticsearch-index.js @@ -1,14 +1,27 @@ (async () => { const AWS = require('aws-sdk'); + const { + elasticsearchIndexes, + } = require('./elasticsearch/elasticsearch-indexes'); AWS.config.region = 'us-east-1'; - const elasticsearch = require('elasticsearch'); const connectionClass = require('http-aws-es'); + const elasticsearch = require('elasticsearch'); AWS.config.httpOptions.timeout = 300000; const { EnvironmentCredentials } = AWS; + // eslint-disable-next-line spellcheck/spell-checker + /* + Supported versions can be found at + https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/what-is-amazon-elasticsearch-service.html#aes-choosing-version + Changes to the API version ought to also be reflected in + - elasticsearch.tf + - delete-elasticsearch-index.js + */ + const ELASTICSEARCH_API_VERSION = '7.4'; + const environment = { elasticsearchEndpoint: process.env.ELASTICSEARCH_ENDPOINT, region: 'us-east-1', @@ -19,7 +32,7 @@ credentials: new EnvironmentCredentials('AWS'), region: environment.region, }, - apiVersion: '7.1', + apiVersion: ELASTICSEARCH_API_VERSION, connectionClass: connectionClass, host: { host: environment.elasticsearchEndpoint, @@ -29,17 +42,22 @@ log: 'warning', }); - try { - const indexExists = await searchClientCache.indices.exists({ - body: {}, - index: 'efcms', - }); - if (indexExists) { - searchClientCache.indices.delete({ - index: 'efcms', - }); - } - } catch (e) { - console.log(e); - } + // TODO: DRY up index names array + await Promise.all( + elasticsearchIndexes.map(async index => { + try { + const indexExists = await searchClientCache.indices.exists({ + body: {}, + index, + }); + if (indexExists) { + searchClientCache.indices.delete({ + index, + }); + } + } catch (e) { + console.log(e); + } + }), + ); })(); diff --git a/web-api/deploy-diff.sh b/web-api/deploy-diff.sh deleted file mode 100755 index 44a697e3c5a..00000000000 --- a/web-api/deploy-diff.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -STAGE=$1 -CHECK_PATH=$2 -CURRENT_SHA="${CIRCLE_SHA1:-`git rev-parse HEAD`}" - -DEPLOYED_SHA=`curl https://ui-$STAGE.$EFCMS_DOMAIN | awk '/meta name/{ gsub(/.*meta revision=\042|\042.*/,"");print }'`; - -if [[ -z $DEPLOYED_SHA ]]; then - echo "true" -elif git diff --name-only $CURRENT_SHA $DEPLOYED_SHA | grep -q $CHECK_PATH; then - echo "true" -else - echo "false" -fi diff --git a/web-api/elasticsearch/elasticsearch-index-settings.js b/web-api/elasticsearch/elasticsearch-index-settings.js index e2fc0e862a2..238345abe4c 100644 --- a/web-api/elasticsearch/elasticsearch-index-settings.js +++ b/web-api/elasticsearch/elasticsearch-index-settings.js @@ -1,16 +1,24 @@ (async () => { const AWS = require('aws-sdk'); + const { elasticsearchIndexes } = require('./elasticsearch-indexes'); AWS.config.region = 'us-east-1'; const connectionClass = require('http-aws-es'); const elasticsearch = require('elasticsearch'); - const settings = require('./elasticsearch-settings'); - - const index = 'efcms'; + const { mappings, settings } = require('./elasticsearch-settings'); AWS.config.httpOptions.timeout = 300000; - const { EnvironmentCredentials } = AWS; + // eslint-disable-next-line spellcheck/spell-checker + /* + Supported versions can be found at + https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/what-is-amazon-elasticsearch-service.html#aes-choosing-version + Changes to the API version ought to also be reflected in + - elasticsearch.tf + - delete-elasticsearch-index.js + */ + const ELASTICSEARCH_API_VERSION = '7.4'; + const environment = { elasticsearchEndpoint: process.env.ELASTICSEARCH_ENDPOINT, region: 'us-east-1', @@ -21,7 +29,7 @@ credentials: new EnvironmentCredentials('AWS'), region: environment.region, }, - apiVersion: '7.1', + apiVersion: ELASTICSEARCH_API_VERSION, connectionClass: connectionClass, host: { host: environment.elasticsearchEndpoint, @@ -31,25 +39,30 @@ log: 'warning', }); - try { - const indexExists = await searchClientCache.indices.exists({ - body: {}, - index, - }); - if (!indexExists) { - searchClientCache.indices.create({ - body: { - settings, - }, - index, - }); - } else { - searchClientCache.indices.putSettings({ - body: { 'index.mapping.total_fields.limit': '4000' }, - index, - }); - } - } catch (e) { - console.log(e); - } + await Promise.all( + elasticsearchIndexes.map(async index => { + try { + const indexExists = await searchClientCache.indices.exists({ + body: {}, + index, + }); + if (!indexExists) { + searchClientCache.indices.create({ + body: { + mappings, + settings, + }, + index, + }); + } else { + searchClientCache.indices.putSettings({ + body: { 'index.mapping.total_fields.limit': '1000' }, + index, + }); + } + } catch (e) { + console.log(e); + } + }), + ); })(); diff --git a/web-api/elasticsearch/elasticsearch-indexes.js b/web-api/elasticsearch/elasticsearch-indexes.js new file mode 100644 index 00000000000..fc089f05dd5 --- /dev/null +++ b/web-api/elasticsearch/elasticsearch-indexes.js @@ -0,0 +1 @@ +exports.elasticsearchIndexes = ['efcms-case', 'efcms-document', 'efcms-user']; diff --git a/web-api/elasticsearch/elasticsearch-settings.js b/web-api/elasticsearch/elasticsearch-settings.js index 4b6661dbf26..c64e5897bed 100644 --- a/web-api/elasticsearch/elasticsearch-settings.js +++ b/web-api/elasticsearch/elasticsearch-settings.js @@ -2,75 +2,66 @@ /* considerations: possibly customize the stop-word list to exclude words like "tax", "court", "irs"? - utilize word-stemming so that a search for "beginning" stems to "begin" which would match "begins", "beginner", "began" etc? - special tokenizer that can identify and match exact docket numbers so that "193-22" is treated as a single searchable token - - https://stackoverflow.com/questions/30517904/elasticsearch-exact-matches-on-analyzed-fields?rq=1 - https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query-phrase.html - - Provide 'slop' as a proximity query. - https://www.elastic.co/guide/en/elasticsearch/guide/current/_closer_is_better.html - - Stop-words - https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-stop-analyzer.html - - Combine stemming with exact search: - https://www.elastic.co/guide/en/elasticsearch/reference/current/mixing-exact-search-with-stemming.html - - simple_query_string syntax (for future queries): - https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-simple-query-string-query.html test 'asciifolding' by putting the following into an Order contents: Déjà vu then search for "deja" to see if the order is returned. */ module.exports = { - index: { - analysis: { - analyzer: { - ustc_analyzer: { - default: { - type: 'simple', + mappings: { + properties: { + 'documentContents.S': { + analyzer: 'ustc_analyzer', + type: 'text', + }, + 'documentTitle.S': { + analyzer: 'ustc_analyzer', + type: 'text', + }, + }, + }, + settings: { + index: { + analysis: { + analyzer: { + ustc_analyzer: { + default: { + type: 'simple', + }, + default_search: { + type: 'stop', + }, + filter: [ + 'lowercase', + 'asciifolding', + 'english', + 'ustc_stop', + 'filter_stemmer', + 'filter_shingle', + ], + tokenizer: 'standard', + }, + }, + filter: { + english: { stopwords: '_english_', type: 'stop' }, + filter_shingle: { + max_shingle_size: 3, + min_shingle_size: 2, + output_unigrams: true, + type: 'shingle', + }, + filter_stemmer: { + language: '_english_', + type: 'porter_stem', }, - default_search: { + ustc_stop: { + stopwords: ['tax', 'court'], type: 'stop', }, - filter: [ - 'lowercase', - 'asciifolding', - 'english', - 'ustc_stop', - 'filter_stemmer', - 'filter_shingle', - ], - tokenizer: 'standard', - }, - }, - filter: { - english: { stopwords: '_english_', type: 'stop' }, - filter_shingle: { - max_shingle_size: 3, - min_shingle_size: 2, - output_unigrams: true, - type: 'shingle', - }, - filter_stemmer: { - language: '_english_', - type: 'porter_stem', - }, - ustc_stop: { - stopwords: [ - 'tax', - 'court', - 'alwaysskipthisword', - 'alwaysskipthistoo', - ], - type: 'stop', }, }, + 'mapping.total_fields.limit': '4000', + number_of_replicas: 1, + number_of_shards: 5, }, - 'mapping.total_fields.limit': '4000', - // mappings: {} // TBD - number_of_replicas: 1, - number_of_shards: 5, }, }; diff --git a/web-api/reindex-dynamodb-records.js b/web-api/reindex-dynamodb-records.js new file mode 100644 index 00000000000..2263e0cde4f --- /dev/null +++ b/web-api/reindex-dynamodb-records.js @@ -0,0 +1,60 @@ +const AWS = require('aws-sdk'); +const { chunk } = require('lodash'); +const args = process.argv.slice(2); + +if (args.length < 1) { + console.error('must provide an environment to reindex: [dev, stg, prod]'); + process.exit(1); +} + +const sleep = time => { + return new Promise(resolve => { + setTimeout(resolve, time); + }); +}; +const env = args[0]; + +const documentClient = new AWS.DynamoDB.DocumentClient({ + endpoint: 'dynamodb.us-east-1.amazonaws.com', + region: 'us-east-1', +}); + +(async function () { + let hasMoreResults = true; + let lastKey = null; + let count = 0; + while (hasMoreResults) { + hasMoreResults = false; + + await documentClient + .scan({ + ExclusiveStartKey: lastKey, + TableName: `efcms-${env}`, + }) + .promise() + .then(async results => { + hasMoreResults = !!results.LastEvaluatedKey; + lastKey = results.LastEvaluatedKey; + + const chunks = chunk(results.Items, 25); + for (let c of chunks) { + count += 25; + console.log(`reindexing chunk: ${count} total reindexed`); + + await documentClient + .batchWrite({ + RequestItems: { + [`efcms-${env}`]: c.map(item => ({ + PutRequest: { + Item: { ...item, indexedTimestamp: Date.now() }, + }, + })), + }, + }) + .promise(); + + await sleep(3000); + } + }); + } +})(); diff --git a/web-api/run-serverless.sh b/web-api/run-serverless.sh index 5d4272025f2..a6d5b068cba 100755 --- a/web-api/run-serverless.sh +++ b/web-api/run-serverless.sh @@ -17,6 +17,10 @@ USER_POOL_ID=$(aws cognito-idp list-user-pools --query "UserPools[?Name == 'efcm USER_POOL_ID="${USER_POOL_ID%\"}" USER_POOL_ID="${USER_POOL_ID#\"}" +USER_POOL_IRS_ID=$(aws cognito-idp list-user-pools --query "UserPools[?Name == 'efcms-irs-${slsStage}'].Id | [0]" --max-results 30 --region "us-east-1") +USER_POOL_IRS_ID="${USER_POOL_IRS_ID%\"}" +USER_POOL_IRS_ID="${USER_POOL_IRS_ID#\"}" + ACCOUNT_ID=$(aws sts get-caller-identity --query "Account") # remove quotes surrounding string ACCOUNT_ID="${ACCOUNT_ID%\"}" @@ -53,6 +57,7 @@ set -- \ --stage "${slsStage}" \ --stageColor "${NEW_COLOR}" \ --userPoolId "${USER_POOL_ID}" \ + --userPoolIrsId "${USER_POOL_IRS_ID}" \ --dynamo_stream_arn="${DYNAMO_STREAM_ARN}" \ --elasticsearch_endpoint="${ELASTICSEARCH_ENDPOINT}" \ --verbose \ diff --git a/web-api/runtimes/clamav/build.sh b/web-api/runtimes/clamav/build.sh index e2aa4483fdc..84a5f472dcf 100755 --- a/web-api/runtimes/clamav/build.sh +++ b/web-api/runtimes/clamav/build.sh @@ -1,4 +1,5 @@ #!/bin/bash + docker build -t clamav -f Dockerfile . docker run --name clamav clamav docker cp clamav:/home/build/clamav_lambda_layer.tar.gz . diff --git a/web-api/seed-elasticsearch.sh b/web-api/seed-elasticsearch.sh index 4e8290c4d51..5ba100d01ac 100755 --- a/web-api/seed-elasticsearch.sh +++ b/web-api/seed-elasticsearch.sh @@ -1,4 +1,6 @@ #!/bin/bash -curl -X DELETE "localhost:9200/efcms" +curl -X DELETE "localhost:9200/efcms-case" +curl -X DELETE "localhost:9200/efcms-document" +curl -X DELETE "localhost:9200/efcms-user" ELASTICSEARCH_PORT=9200 ELASTICSEARCH_PROTOCOL="http" node ./web-api/elasticsearch/elasticsearch-index-settings.js diff --git a/web-api/serverless-api.yml b/web-api/serverless-api.yml index a76013cf126..e63810e1c33 100644 --- a/web-api/serverless-api.yml +++ b/web-api/serverless-api.yml @@ -10,9 +10,13 @@ plugins: - serverless-plugin-tracing - serverless-latest-layer-version - serverless-jetpack + - serverless-log-forwarding # - serverless-plugin-warmup custom: + logForwarding: + destinationARN: arn:aws:lambda:${opt:region}:${opt:accountId}:function:log_forwarder_${opt:stage} + filterPattern: 'ERROR' #warmup: #enabled: true @@ -155,7 +159,7 @@ functions: handler: web-api/${self:provider.dir}/apiHandlers.getNotificationsLambda events: - http: - path: notifications + path: /notifications method: get cors: ui-${self:provider.stage}.ef-cms.${opt:domain} authorizer: @@ -172,17 +176,25 @@ functions: handler: web-api/${self:provider.dir}/apiHandlers.swaggerLambda events: - http: - path: swagger + path: /swagger method: get cors: ui-${self:provider.stage}.ef-cms.${opt:domain} + authorizer: + type: COGNITO_USER_POOLS + authorizerId: + Ref: ApiGatewayAuthorizer swaggerJson: handler: web-api/${self:provider.dir}/apiHandlers.swaggerJsonLambda events: - http: - path: swagger.json + path: /swagger.json method: get cors: ui-${self:provider.stage}.ef-cms.${opt:domain} + authorizer: + type: COGNITO_USER_POOLS + authorizerId: + Ref: ApiGatewayAuthorizer createCourtIssuedOrderPdfFromHtml: handler: web-api/${self:provider.dir}/apiHandlers.createCourtIssuedOrderPdfFromHtmlLambda @@ -192,7 +204,7 @@ functions: timeout: 900 events: - http: - path: court-issued-order + path: /court-issued-order method: post cors: ui-${self:provider.stage}.ef-cms.${opt:domain} authorizer: @@ -208,7 +220,7 @@ functions: timeout: 900 events: - http: - path: docket-record-pdf + path: /docket-record-pdf method: post cors: ui-${self:provider.stage}.ef-cms.${opt:domain} authorizer: diff --git a/web-api/serverless-case-deadlines.yml b/web-api/serverless-case-deadlines.yml index aab0c31774c..b3044ec136d 100644 --- a/web-api/serverless-case-deadlines.yml +++ b/web-api/serverless-case-deadlines.yml @@ -8,9 +8,13 @@ plugins: - serverless-plugin-tracing - serverless-latest-layer-version - serverless-jetpack + - serverless-log-forwarding # - serverless-plugin-warmup custom: + logForwarding: + destinationARN: arn:aws:lambda:${opt:region}:${opt:accountId}:function:log_forwarder_${opt:stage} + filterPattern: 'ERROR' #warmup: #enabled: true diff --git a/web-api/serverless-case-documents.yml b/web-api/serverless-case-documents.yml index c2fc3308463..f706ed1a2ac 100644 --- a/web-api/serverless-case-documents.yml +++ b/web-api/serverless-case-documents.yml @@ -8,9 +8,13 @@ plugins: - serverless-plugin-tracing - serverless-latest-layer-version - serverless-jetpack + - serverless-log-forwarding # - serverless-plugin-warmup custom: + logForwarding: + destinationARN: arn:aws:lambda:${opt:region}:${opt:accountId}:function:log_forwarder_${opt:stage} + filterPattern: 'ERROR' #warmup: #enabled: true @@ -217,6 +221,9 @@ functions: path: /{caseId}/{documentId} method: delete cors: ui-${self:provider.stage}.ef-cms.${opt:domain} + authorizer: + arn: arn:aws:lambda:${opt:region}:${opt:accountId}:function:cognito_authorizer_lambda_${opt:stage} + managedExternally: true fileExternalDocument: handler: web-api/${self:provider.dir}/caseDocumentsHandlers.fileExternalDocumentToCaseLambda @@ -268,6 +275,10 @@ functions: updateDocketEntryMeta: handler: web-api/${self:provider.dir}/caseDocumentsHandlers.updateDocketEntryMetaLambda + layers: + - arn:aws:lambda:${opt:region}:${opt:accountId}:layer:${opt:stage}-puppeteer:latest + memorySize: 3008 + timeout: 900 events: - http: path: /{caseId}/docket-entry-meta @@ -371,6 +382,11 @@ functions: path: /{caseId}/{documentId}/document-download-url method: get cors: ui-${self:provider.stage}.ef-cms.${opt:domain} + authorizer: + arn: arn:aws:lambda:${opt:region}:${opt:accountId}:function:cognito_authorizer_lambda_${opt:stage} + managedExternally: true + identitySource: method.request.querystring.token + type: request orderAdvancedSearch: handler: web-api/${self:provider.dir}/caseDocumentsHandlers.orderAdvancedSearchLambda diff --git a/web-api/serverless-case-meta.yml b/web-api/serverless-case-meta.yml index ae796dcb3f0..e37c0abe2a5 100644 --- a/web-api/serverless-case-meta.yml +++ b/web-api/serverless-case-meta.yml @@ -9,9 +9,13 @@ plugins: - serverless-plugin-tracing - serverless-latest-layer-version - serverless-jetpack + - serverless-log-forwarding # - serverless-plugin-warmup custom: + logForwarding: + destinationARN: arn:aws:lambda:${opt:region}:${opt:accountId}:function:log_forwarder_${opt:stage} + filterPattern: 'ERROR' #warmup: #enabled: true diff --git a/web-api/serverless-case-notes.yml b/web-api/serverless-case-notes.yml index efda1f5b998..d2a9aac2178 100644 --- a/web-api/serverless-case-notes.yml +++ b/web-api/serverless-case-notes.yml @@ -8,9 +8,13 @@ plugins: - serverless-plugin-tracing - serverless-latest-layer-version - serverless-jetpack + - serverless-log-forwarding # - serverless-plugin-warmup custom: + logForwarding: + destinationARN: arn:aws:lambda:${opt:region}:${opt:accountId}:function:log_forwarder_${opt:stage} + filterPattern: 'ERROR' #warmup: #enabled: true diff --git a/web-api/serverless-case-parties.yml b/web-api/serverless-case-parties.yml index a99e6841726..a8d2e50c8e4 100644 --- a/web-api/serverless-case-parties.yml +++ b/web-api/serverless-case-parties.yml @@ -9,9 +9,13 @@ plugins: - serverless-plugin-tracing - serverless-latest-layer-version - serverless-jetpack + - serverless-log-forwarding # - serverless-plugin-warmup custom: + logForwarding: + destinationARN: arn:aws:lambda:${opt:region}:${opt:accountId}:function:log_forwarder_${opt:stage} + filterPattern: 'ERROR' #warmup: #enabled: true diff --git a/web-api/serverless-cases.yml b/web-api/serverless-cases.yml index e9bbe542c82..a78eb30b63f 100644 --- a/web-api/serverless-cases.yml +++ b/web-api/serverless-cases.yml @@ -9,9 +9,13 @@ plugins: - serverless-plugin-tracing - serverless-latest-layer-version - serverless-jetpack + - serverless-log-forwarding # - serverless-plugin-warmup custom: + logForwarding: + destinationARN: arn:aws:lambda:${opt:region}:${opt:accountId}:function:log_forwarder_${opt:stage} + filterPattern: 'ERROR' #warmup: #enabled: true @@ -213,9 +217,8 @@ functions: caseId: true cors: ui-${self:provider.stage}.ef-cms.${opt:domain} authorizer: - type: COGNITO_USER_POOLS - authorizerId: - Ref: ApiGatewayAuthorizer + arn: arn:aws:lambda:${opt:region}:${opt:accountId}:function:cognito_authorizer_lambda_${opt:stage} + managedExternally: true caseAdvancedSearch: handler: web-api/${self:provider.dir}/casesHandlers.caseAdvancedSearchLambda @@ -225,9 +228,8 @@ functions: method: get cors: ui-${self:provider.stage}.ef-cms.${opt:domain} authorizer: - type: COGNITO_USER_POOLS - authorizerId: - Ref: ApiGatewayAuthorizer + arn: arn:aws:lambda:${opt:region}:${opt:accountId}:function:cognito_authorizer_lambda_${opt:stage} + managedExternally: true getConsolidatedCasesByCase: handler: web-api/${self:provider.dir}/casesHandlers.getConsolidatedCasesByCaseLambda diff --git a/web-api/serverless-clamav.yml b/web-api/serverless-clamav.yml index d63c875a9df..34cde870a95 100644 --- a/web-api/serverless-clamav.yml +++ b/web-api/serverless-clamav.yml @@ -26,11 +26,23 @@ provider: serverSideEncryption: AES256 layers: - clamav: - name: ${self:provider.stage}-clamav + av: + name: ${self:provider.stage}-av compatibleRuntimes: - nodejs12.x path: web-api/runtimes/clamav package: exclude: - clamav_lambda_layer.tar.gz + - var/lib/clamav/main.cvd + avm: + name: ${self:provider.stage}-avm + compatibleRuntimes: + - nodejs12.x + path: web-api/runtimes/clamav/ + package: + exclude: + - ./** + include: + - var/lib/clamav/main.cvd + excludeDevDependencies: true diff --git a/web-api/serverless-documents.yml b/web-api/serverless-documents.yml index d08f3f2cc41..1dc9a2d1bb4 100644 --- a/web-api/serverless-documents.yml +++ b/web-api/serverless-documents.yml @@ -9,9 +9,13 @@ plugins: - serverless-plugin-tracing - serverless-latest-layer-version - serverless-jetpack + - serverless-log-forwarding # - serverless-plugin-warmup custom: + logForwarding: + destinationARN: arn:aws:lambda:${opt:region}:${opt:accountId}:function:log_forwarder_${opt:stage} + filterPattern: 'ERROR' #warmup: #enabled: true @@ -156,6 +160,10 @@ functions: path: /{documentId}/validate method: post cors: ui-${self:provider.stage}.ef-cms.${opt:domain} + authorizer: + type: COGNITO_USER_POOLS + authorizerId: + Ref: ApiGatewayAuthorizer alarms: - errorExceptions @@ -182,16 +190,25 @@ functions: path: /filing-receipt-pdf method: post cors: ui-${self:provider.stage}.ef-cms.${opt:domain} + authorizer: + type: COGNITO_USER_POOLS + authorizerId: + Ref: ApiGatewayAuthorizer virusScan: handler: web-api/${self:provider.dir}/documentsHandlers.virusScanPdfLambda memorySize: 3008 timeout: 900 layers: - - arn:aws:lambda:${opt:region}:${opt:accountId}:layer:${opt:stage}-clamav:latest + - arn:aws:lambda:${opt:region}:${opt:accountId}:layer:${opt:stage}-av:latest + - arn:aws:lambda:${opt:region}:${opt:accountId}:layer:${opt:stage}-avm:latest events: - http: path: /{documentId}/virus-scan method: post cors: ui-${self:provider.stage}.ef-cms.${opt:domain} async: true + authorizer: + type: COGNITO_USER_POOLS + authorizerId: + Ref: ApiGatewayAuthorizer diff --git a/web-api/serverless-migrate.yml b/web-api/serverless-migrate.yml index e7dd55276b4..9e283411891 100644 --- a/web-api/serverless-migrate.yml +++ b/web-api/serverless-migrate.yml @@ -8,8 +8,12 @@ plugins: - serverless-plugin-tracing - serverless-latest-layer-version - serverless-jetpack + - serverless-log-forwarding custom: + logForwarding: + destinationARN: arn:aws:lambda:${opt:region}:${opt:accountId}:function:log_forwarder_${opt:stage} + filterPattern: 'ERROR' jetpack: mode: npm lockfile: ../package-lock.json diff --git a/web-api/serverless-notifications.yml b/web-api/serverless-notifications.yml index c32156634cf..23d27687778 100644 --- a/web-api/serverless-notifications.yml +++ b/web-api/serverless-notifications.yml @@ -10,8 +10,12 @@ plugins: - serverless-plugin-tracing - serverless-latest-layer-version - serverless-jetpack + - serverless-log-forwarding custom: + logForwarding: + destinationARN: arn:aws:lambda:${opt:region}:${opt:accountId}:function:log_forwarder_${opt:stage} + filterPattern: 'ERROR' jetpack: mode: npm lockfile: ../package-lock.json @@ -114,45 +118,18 @@ package: excludeDevDependencies: true -resources: - Resources: - ##### - # This Authorizer is used for validating the JWT token before invoking the lambda - ##### - # ApiGatewayAuthorizer: - # Type: AWS::ApiGateway::Authorizer - # Properties: - # Name: CognitoUserPool - # Type: COGNITO_USER_POOLS - # IdentitySource: method.request.header.Authorization - # RestApiId: - # Ref: ApiGatewayRestApi - # ProviderARNs: - # - arn:aws:cognito-idp:${opt:region}:${opt:accountId}:userpool/${self:provider.environment.USER_POOL_ID} - ##### - # Begin Stage for API Gateway Logging - ##### - # ApiGatewayStage: - # Type: AWS::ApiGateway::Stage - # Properties: - # DeploymentId: - # Ref: __deployment__ - # RestApiId: - # Ref: ApiGatewayRestApi - # StageName: ${opt:stage} - # MethodSettings: - # - DataTraceEnabled: true - # HttpMethod: '*' - # LoggingLevel: INFO - # ResourcePath: '/*' - # MetricsEnabled: true - functions: connectHandler: handler: web-api/${self:provider.dir}/notificationHandlers.connectLambda events: - websocket: route: $connect + authorizer: + arn: arn:aws:lambda:${opt:region}:${opt:accountId}:function:cognito_authorizer_lambda_${opt:stage} + managedExternally: true + identitySource: + - route.request.querystring.token + type: request disconnectHandler: handler: web-api/${self:provider.dir}/notificationHandlers.disconnectLambda diff --git a/web-api/serverless-practitioners.yml b/web-api/serverless-practitioners.yml index 61bc6d83bb4..fcb31f3769a 100644 --- a/web-api/serverless-practitioners.yml +++ b/web-api/serverless-practitioners.yml @@ -9,9 +9,13 @@ plugins: - serverless-plugin-tracing - serverless-latest-layer-version - serverless-jetpack + - serverless-log-forwarding # - serverless-plugin-warmup custom: + logForwarding: + destinationARN: arn:aws:lambda:${opt:region}:${opt:accountId}:function:log_forwarder_${opt:stage} + filterPattern: 'ERROR' #warmup: #enabled: true diff --git a/web-api/serverless-public-api.yml b/web-api/serverless-public-api.yml index 87949ca67b7..9681efa4b9c 100644 --- a/web-api/serverless-public-api.yml +++ b/web-api/serverless-public-api.yml @@ -9,8 +9,12 @@ plugins: - serverless-plugin-tracing - serverless-latest-layer-version - serverless-jetpack + - serverless-log-forwarding custom: + logForwarding: + destinationARN: arn:aws:lambda:${opt:region}:${opt:accountId}:function:log_forwarder_${opt:stage} + filterPattern: 'ERROR' jetpack: mode: npm lockfile: ../package-lock.json diff --git a/web-api/serverless-reports.yml b/web-api/serverless-reports.yml index 16923c4e8ee..88855c7f512 100644 --- a/web-api/serverless-reports.yml +++ b/web-api/serverless-reports.yml @@ -9,9 +9,13 @@ plugins: - serverless-plugin-tracing - serverless-latest-layer-version - serverless-jetpack + - serverless-log-forwarding # - serverless-plugin-warmup custom: + logForwarding: + destinationARN: arn:aws:lambda:${opt:region}:${opt:accountId}:function:log_forwarder_${opt:stage} + filterPattern: 'ERROR' #warmup: #enabled: true @@ -196,7 +200,7 @@ functions: handler: web-api/${self:provider.dir}/reportsHandlers.fetchPendingItemsLambda events: - http: - path: pending-items + path: /pending-items method: get cors: ui-${self:provider.stage}.ef-cms.${opt:domain} authorizer: @@ -212,7 +216,7 @@ functions: timeout: 900 events: - http: - path: pending-report + path: /pending-report method: get cors: ui-${self:provider.stage}.ef-cms.${opt:domain} authorizer: @@ -228,7 +232,7 @@ functions: timeout: 900 events: - http: - path: trial-calendar-pdf + path: /trial-calendar-pdf method: post cors: ui-${self:provider.stage}.ef-cms.${opt:domain} authorizer: diff --git a/web-api/serverless-sections.yml b/web-api/serverless-sections.yml index a0250419c85..7d948d97472 100644 --- a/web-api/serverless-sections.yml +++ b/web-api/serverless-sections.yml @@ -9,9 +9,13 @@ plugins: - serverless-plugin-tracing - serverless-latest-layer-version - serverless-jetpack + - serverless-log-forwarding # - serverless-plugin-warmup custom: + logForwarding: + destinationARN: arn:aws:lambda:${opt:region}:${opt:accountId}:function:log_forwarder_${opt:stage} + filterPattern: 'ERROR' #warmup: #enabled: true @@ -205,9 +209,8 @@ functions: method: get cors: ui-${self:provider.stage}.ef-cms.${opt:domain} authorizer: - type: COGNITO_USER_POOLS - authorizerId: - Ref: ApiGatewayAuthorizer + arn: arn:aws:lambda:${opt:region}:${opt:accountId}:function:cognito_authorizer_lambda_${opt:stage} + managedExternally: true getDocumentQCInboxForSection: handler: web-api/${self:provider.dir}/sectionsHandlers.getDocumentQCInboxForSectionLambda diff --git a/web-api/serverless-streams.yml b/web-api/serverless-streams.yml index c22ab125e5a..d560a64e7f0 100644 --- a/web-api/serverless-streams.yml +++ b/web-api/serverless-streams.yml @@ -10,8 +10,12 @@ plugins: - serverless-plugin-tracing - serverless-latest-layer-version - serverless-jetpack + - serverless-log-forwarding custom: + logForwarding: + destinationARN: arn:aws:lambda:${opt:region}:${opt:accountId}:function:log_forwarder_${opt:stage} + filterPattern: 'ERROR' jetpack: mode: npm lockfile: ../package-lock.json diff --git a/web-api/serverless-trial-sessions.yml b/web-api/serverless-trial-sessions.yml index 9138351cced..325781be542 100644 --- a/web-api/serverless-trial-sessions.yml +++ b/web-api/serverless-trial-sessions.yml @@ -9,9 +9,13 @@ plugins: - serverless-plugin-tracing - serverless-latest-layer-version - serverless-jetpack + - serverless-log-forwarding # - serverless-plugin-warmup custom: + logForwarding: + destinationARN: arn:aws:lambda:${opt:region}:${opt:accountId}:function:log_forwarder_${opt:stage} + filterPattern: 'ERROR' #warmup: #enabled: true @@ -301,6 +305,10 @@ functions: method: get async: true cors: ui-${self:provider.stage}.ef-cms.${opt:domain} + authorizer: + type: COGNITO_USER_POOLS + authorizerId: + Ref: ApiGatewayAuthorizer removeCaseFromTrial: handler: web-api/${self:provider.dir}/trialSessionsHandlers.removeCaseFromTrialLambda diff --git a/web-api/serverless-users.yml b/web-api/serverless-users.yml index 14ed28b0af2..9f1bd58722f 100644 --- a/web-api/serverless-users.yml +++ b/web-api/serverless-users.yml @@ -9,9 +9,13 @@ plugins: - serverless-plugin-tracing - serverless-latest-layer-version - serverless-jetpack + - serverless-log-forwarding # - serverless-plugin-warmup custom: + logForwarding: + destinationARN: arn:aws:lambda:${opt:region}:${opt:accountId}:function:log_forwarder_${opt:stage} + filterPattern: 'ERROR' #warmup: #enabled: true @@ -84,6 +88,7 @@ provider: dynamodbEndpoint: dynamodb.${opt:region}.amazonaws.com masterRegion: us-east-1 userPoolId: us-east-1_7uRkF0Axn + userPoolIrsId: us-east-1_7uRkF0Axn masterDynamodbEndpoint: dynamodb.us-east-1.amazonaws.com deploymentBucket: name: ${env:SLS_DEPLOYMENT_BUCKET} @@ -102,6 +107,7 @@ provider: MASTER_REGION: ${self:provider.masterRegion} STAGE: ${self:custom.stage} USER_POOL_ID: ${opt:userPoolId, self:provider.userPoolId} + USER_POOL_IRS_ID: ${opt:userPoolIrsId, self:provider.userPoolIrsId} NODE_ENV: ${self:custom.vars.nodeEnv} CLAMAV_DEF_DIR: ${self:custom.vars.clamavDefDir, self:provider.clamavDefDir} EMAIL_SERVED_TEMPLATE: case_served_${opt:stage} @@ -158,9 +164,8 @@ functions: method: get cors: ui-${self:provider.stage}.ef-cms.${opt:domain} authorizer: - type: COGNITO_USER_POOLS - authorizerId: - Ref: ApiGatewayAuthorizer + arn: arn:aws:lambda:${opt:region}:${opt:accountId}:function:cognito_authorizer_lambda_${opt:stage} + managedExternally: true getUserById: handler: web-api/${self:provider.dir}/usersHandlers.getUserByIdLambda diff --git a/web-api/serverless-work-items.yml b/web-api/serverless-work-items.yml index 420ecc736c9..998eee35b96 100644 --- a/web-api/serverless-work-items.yml +++ b/web-api/serverless-work-items.yml @@ -9,9 +9,13 @@ plugins: - serverless-plugin-tracing - serverless-latest-layer-version - serverless-jetpack + - serverless-log-forwarding # - serverless-plugin-warmup custom: + logForwarding: + destinationARN: arn:aws:lambda:${opt:region}:${opt:accountId}:function:log_forwarder_${opt:stage} + filterPattern: 'ERROR' #warmup: #enabled: true @@ -204,3 +208,7 @@ functions: path: /{workItemId}/read method: post cors: ui-${self:provider.stage}.ef-cms.${opt:domain} + authorizer: + type: COGNITO_USER_POOLS + authorizerId: + Ref: ApiGatewayAuthorizer diff --git a/web-api/setup-irs-user.sh b/web-api/setup-irs-user.sh index 23afd3b6d68..a1f8b342879 100755 --- a/web-api/setup-irs-user.sh +++ b/web-api/setup-irs-user.sh @@ -30,38 +30,6 @@ generate_post_data() { EOF } -createIrsAccount() { - email=$1 - role=$2 - section=$3 - name=$4 - - curl --header "Content-Type: application/json" \ - --header "Authorization: Bearer ${adminToken}" \ - --request POST \ - --data "$(generate_post_data "${email}" "${role}" "${section}" "${name}")" \ - "https://${restApiId}.execute-api.us-east-1.amazonaws.com/${ENV}" - - response=$(aws cognito-idp admin-initiate-auth \ - --user-pool-id "${USER_POOL_ID}" \ - --client-id "${CLIENT_ID}" \ - --region "${REGION}" \ - --auth-flow ADMIN_NO_SRP_AUTH \ - --auth-parameters USERNAME="${email}"',PASSWORD="Testing1234$"') - - session=$(echo "${response}" | jq -r ".Session") - - if [ "$session" != "null" ]; then - aws cognito-idp admin-respond-to-auth-challenge \ - --user-pool-id "${USER_POOL_ID}" \ - --client-id "${CLIENT_ID}" \ - --region "${REGION}" \ - --challenge-name NEW_PASSWORD_REQUIRED \ - --challenge-responses 'NEW_PASSWORD="Testing1234$",'USERNAME="${email}" \ - --session="${session}" - fi -} - response=$(aws cognito-idp admin-initiate-auth \ --user-pool-id "${USER_POOL_ID}" \ --client-id "${CLIENT_ID}" \ @@ -70,4 +38,8 @@ response=$(aws cognito-idp admin-initiate-auth \ --auth-parameters USERNAME="ustcadmin@example.com"',PASSWORD'="${USTC_ADMIN_PASS}") adminToken=$(echo "${response}" | jq -r ".AuthenticationResult.IdToken") -createIrsAccount "service.agent.test@irs.gov" "irsSuperuser" "irsSuperuser" "IRS Superuser" +curl --header "Content-Type: application/json" \ + --header "Authorization: Bearer ${adminToken}" \ + --request POST \ + --data "$(generate_post_data "service.agent.test@irs.gov" "irsSuperuser" "irsSuperuser" "IRS Superuser")" \ + "https://${restApiId}.execute-api.us-east-1.amazonaws.com/${ENV}" diff --git a/web-api/src/apiHandlers.js b/web-api/src/apiHandlers.js index b4cb426203b..8de26f2c334 100644 --- a/web-api/src/apiHandlers.js +++ b/web-api/src/apiHandlers.js @@ -5,8 +5,6 @@ module.exports = { .createCourtIssuedOrderPdfFromHtmlLambda, generateDocketRecordPdfLambda: require('./cases/generateDocketRecordPdfLambda') .generateDocketRecordPdfLambda, - generatePdfFromHtmlLambda: require('./cases/generatePdfFromHtmlLambda') - .generatePdfFromHtmlLambda, getNotificationsLambda: require('./users/getNotificationsLambda') .getNotificationsLambda, swaggerJsonLambda: require('./swagger/swaggerJsonLambda').swaggerJsonLambda, diff --git a/web-api/src/applicationContext.js b/web-api/src/applicationContext.js index dac288d3a62..fc4a2464aff 100644 --- a/web-api/src/applicationContext.js +++ b/web-api/src/applicationContext.js @@ -13,6 +13,7 @@ const barNumberGenerator = require('../../shared/src/persistence/dynamo/users/ba const connectionClass = require('http-aws-es'); const docketNumberGenerator = require('../../shared/src/persistence/dynamo/cases/docketNumberGenerator'); const elasticsearch = require('elasticsearch'); +const elasticsearchIndexes = require('../elasticsearch/elasticsearch-indexes'); const util = require('util'); const { addCaseToTrialSessionInteractor, @@ -62,12 +63,6 @@ const { const { caseAdvancedSearchInteractor, } = require('../../shared/src/business/useCases/caseAdvancedSearchInteractor'); -const { - CaseExternalIncomplete, -} = require('../../shared/src/business/entities/cases/CaseExternalIncomplete'); -const { - CaseInternal, -} = require('../../shared/src/business/entities/cases/CaseInternal'); const { casePublicSearch: casePublicSearchPersistence, } = require('../../shared/src/persistence/elasticsearch/casePublicSearch'); @@ -75,8 +70,10 @@ const { casePublicSearchInteractor, } = require('../../shared/src/business/useCases/public/casePublicSearchInteractor'); const { - CaseSearch, -} = require('../../shared/src/business/entities/cases/CaseSearch'); + changeOfAddress, + docketRecord, + standingPretrialOrder, +} = require('../../shared/src/business/utilities/documentGenerators'); const { checkForReadyForTrialCasesInteractor, } = require('../../shared/src/business/useCases/checkForReadyForTrialCasesInteractor'); @@ -96,8 +93,8 @@ const { completeWorkItemInteractor, } = require('../../shared/src/business/useCases/workitems/completeWorkItemInteractor'); const { - ContactFactory, -} = require('../../shared/src/business/entities/contacts/ContactFactory'); + countPagesInDocument, +} = require('../../shared/src/business/useCaseHelper/countPagesInDocument'); const { createCase, } = require('../../shared/src/persistence/dynamo/cases/createCase'); @@ -218,12 +215,6 @@ const { const { deleteWorkItemFromSection, } = require('../../shared/src/persistence/dynamo/workitems/deleteWorkItemFromSection'); -const { - DocketRecord, -} = require('../../shared/src/business/entities/DocketRecord'); -const { - ExternalDocumentFactory, -} = require('../../shared/src/business/entities/externalDocument/ExternalDocumentFactory'); const { fetchPendingItems, } = require('../../shared/src/business/useCaseHelper/pendingItems/fetchPendingItems'); @@ -433,6 +424,12 @@ const { const { getInboxMessagesForUserInteractor, } = require('../../shared/src/business/useCases/workitems/getInboxMessagesForUserInteractor'); +const { + getIndexMappingFields, +} = require('../../shared/src/persistence/elasticsearch/getIndexMappingFields'); +const { + getIndexMappingLimit, +} = require('../../shared/src/persistence/elasticsearch/getIndexMappingLimit'); const { getInternalUsers, } = require('../../shared/src/persistence/dynamo/users/getInternalUsers'); @@ -562,6 +559,9 @@ const { const { indexRecord, } = require('../../shared/src/persistence/elasticsearch/indexRecord'); +const { + IrsPractitioner, +} = require('../../shared/src/business/entities/IrsPractitioner'); const { isAuthorized, ROLE_PERMISSIONS, @@ -587,9 +587,15 @@ const { const { orderPublicSearchInteractor, } = require('../../shared/src/business/useCases/public/orderPublicSearchInteractor'); +const { + Practitioner, +} = require('../../shared/src/business/entities/Practitioner'); const { prioritizeCaseInteractor, } = require('../../shared/src/business/useCases/prioritizeCaseInteractor'); +const { + PrivatePractitioner, +} = require('../../shared/src/business/entities/PrivatePractitioner'); const { processStreamRecordsInteractor, } = require('../../shared/src/business/useCases/processStreamRecordsInteractor'); @@ -623,6 +629,9 @@ const { const { saveDocumentFromLambda, } = require('../../shared/src/persistence/s3/saveDocumentFromLambda'); +const { + saveFileAndGenerateUrl, +} = require('../../shared/src/business/useCaseHelper/saveFileAndGenerateUrl'); const { saveIntermediateDocketEntryInteractor, } = require('../../shared/src/business/useCases/editDocketEntry/saveIntermediateDocketEntryInteractor'); @@ -813,11 +822,13 @@ const { zipDocuments, } = require('../../shared/src/persistence/s3/zipDocuments'); const { Case } = require('../../shared/src/business/entities/cases/Case'); +const { Document } = require('../../shared/src/business/entities/Document'); const { exec } = require('child_process'); +const { getDocument } = require('../../shared/src/persistence/s3/getDocument'); const { Order } = require('../../shared/src/business/entities/orders/Order'); const { User } = require('../../shared/src/business/entities/User'); + const { v4: uuidv4 } = require('uuid'); -const { WorkItem } = require('../../shared/src/business/entities/WorkItem'); // increase the timeout for zip uploads to S3 AWS.config.httpOptions.timeout = 300000; @@ -848,6 +859,20 @@ const environment = { let user; +const initHoneybadger = () => { + if (process.env.NODE_ENV === 'production') { + const apiKey = process.env.CIRCLE_HONEYBADGER_API_KEY; + if (apiKey) { + const config = { + apiKey, + environment: 'api', + }; + Honeybadger.configure(config); + return Honeybadger; + } + } +}; + const getCurrentUser = () => { return user; }; @@ -861,7 +886,12 @@ let sesCache; let searchClientCache; const entitiesByName = { - Case: Case, + Case, + Document, + IrsPractitioner, + Practitioner, + PrivatePractitioner, + User, }; module.exports = (appContextUser = {}) => { @@ -871,7 +901,7 @@ module.exports = (appContextUser = {}) => { barNumberGenerator, docketNumberGenerator, environment, - getCaseCaptionNames: Case.getCaseCaptionNames, + getCaseTitle: Case.getCaseTitle, getChromiumBrowser, getCognito: () => { if (environment.stage === 'local') { @@ -921,9 +951,15 @@ module.exports = (appContextUser = {}) => { } return dynamoClientCache[type]; }, + getDocumentGenerators: () => ({ + changeOfAddress, + docketRecord, + standingPretrialOrder, + }), getDocumentsBucketName: () => { return environment.documentsBucketName; }, + getElasticsearchIndexes: () => elasticsearchIndexes, getEmailClient: () => { if (!sesCache) { sesCache = new SES({ @@ -935,18 +971,6 @@ module.exports = (appContextUser = {}) => { getEntityByName: name => { return entitiesByName[name]; }, - getEntityConstructors: () => ({ - Case, - CaseExternal: CaseExternalIncomplete, - CaseInternal: CaseInternal, - CaseSearch, - ContactFactory, - DocketRecord, - ExternalDocumentFactory, - TrialSession, - User, - WorkItem, - }), getMigrations: () => ({ migrateCaseInteractor, }), @@ -978,7 +1002,6 @@ module.exports = (appContextUser = {}) => { associateUserWithCase, associateUserWithCasePending, bulkIndexRecords, - caseAdvancedSearch, casePublicSearch: casePublicSearchPersistence, createCase, @@ -1018,6 +1041,7 @@ module.exports = (appContextUser = {}) => { getCasesByCaseIds, getCasesByLeadCaseId, getCasesByUser, + getDocument, getDocumentQCInboxForSection, getDocumentQCInboxForUser, getDocumentQCServedForSection, @@ -1028,6 +1052,8 @@ module.exports = (appContextUser = {}) => { getEligibleCasesForTrialSession, getInboxMessagesForSection, getInboxMessagesForUser, + getIndexMappingFields, + getIndexMappingLimit, getInternalUsers, getPractitionerByBarNumber, getPractitionersByName, @@ -1144,12 +1170,14 @@ module.exports = (appContextUser = {}) => { getUseCaseHelpers: () => { return { appendPaperServiceAddressPageToPdf, + countPagesInDocument, fetchPendingItems, generateCaseConfirmationPdf, generateCaseInventoryReportPdf, generatePaperServiceAddressPagePdf, generatePendingReportPdf, getCaseInventoryReport, + saveFileAndGenerateUrl, sendServedPartiesEmails, updateCaseAutomaticBlock, }; @@ -1170,6 +1198,7 @@ module.exports = (appContextUser = {}) => { checkForReadyForTrialCasesInteractor, completeDocketEntryQCInteractor, completeWorkItemInteractor, + createCaseDeadlineInteractor, createCaseFromPaperInteractor, createCaseInteractor, @@ -1307,20 +1336,7 @@ module.exports = (appContextUser = {}) => { setServiceIndicatorsForCase, }; }, - initHoneybadger: () => { - if (process.env.NODE_ENV === 'production') { - const apiKey = process.env.CIRCLE_HONEYBADGER_API_KEY; - - if (apiKey) { - const config = { - apiKey, - environment: 'api', - }; - Honeybadger.configure(config); - return Honeybadger; - } - } - }, + initHoneybadger, isAuthorized, isAuthorizedForWorkItems: () => isAuthorized(user, ROLE_PERMISSIONS.WORKITEM), @@ -1342,6 +1358,19 @@ module.exports = (appContextUser = {}) => { console.timeEnd(key); }, }, + notifyHoneybadger: async message => { + const honeybadger = initHoneybadger(); + + const notifyAsync = message => { + return new Promise(resolve => { + honeybadger.notify(message, null, null, resolve); + }); + }; + + if (honeybadger) { + await notifyAsync(message); + } + }, runVirusScan: async ({ filePath }) => { return execPromise( `clamscan ${ diff --git a/web-api/src/cases/generatePdfFromHtmlLambda.js b/web-api/src/cases/generatePdfFromHtmlLambda.js deleted file mode 100644 index 5aa42a5b8a0..00000000000 --- a/web-api/src/cases/generatePdfFromHtmlLambda.js +++ /dev/null @@ -1,27 +0,0 @@ -const { genericHandler } = require('../genericHandler'); - -/** - * used for generating a printable PDF of a docket record - * - * @param {object} event the AWS event object - * @returns {Promise<*|undefined>} the api gateway response object containing the statusCode, body, and headers - */ -exports.generatePdfFromHtmlLambda = event => - genericHandler(event, async ({ applicationContext }) => { - const { - contentHtml, - displayHeaderFooter, - docketNumber, - headerHtml, - } = JSON.parse(event.body); - - return await applicationContext - .getUseCases() - .generatePdfFromHtmlInteractor({ - applicationContext, - contentHtml, - displayHeaderFooter, - docketNumber, - headerHtml, - }); - }); diff --git a/web-api/src/documents/generatePrintableFilingReceiptLambda.js b/web-api/src/documents/generatePrintableFilingReceiptLambda.js index 670aeb56706..eb66555a6c2 100644 --- a/web-api/src/documents/generatePrintableFilingReceiptLambda.js +++ b/web-api/src/documents/generatePrintableFilingReceiptLambda.js @@ -8,12 +8,10 @@ const { genericHandler } = require('../genericHandler'); */ exports.generatePrintableFilingReceiptLambda = event => genericHandler(event, async ({ applicationContext }) => { - const { documents } = JSON.parse(event.body); - return await applicationContext .getUseCases() .generatePrintableFilingReceiptInteractor({ applicationContext, - documents, + ...JSON.parse(event.body), }); }); diff --git a/web-api/src/documents/getDocumentDownloadUrlLambda.js b/web-api/src/documents/getDocumentDownloadUrlLambda.js index 6c758900cd5..6e816f9d785 100644 --- a/web-api/src/documents/getDocumentDownloadUrlLambda.js +++ b/web-api/src/documents/getDocumentDownloadUrlLambda.js @@ -14,7 +14,6 @@ exports.getDocumentDownloadUrlLambda = event => redirect(event, async () => { const user = getUserFromAuthHeader(event); const applicationContext = createApplicationContext(user); - const honeybadger = applicationContext.initHoneybadger(); try { const results = await applicationContext .getUseCases() @@ -28,7 +27,7 @@ exports.getDocumentDownloadUrlLambda = event => return results; } catch (e) { applicationContext.logger.error(e); - honeybadger && honeybadger.notify(e); + await applicationContext.notifyHoneybadger(e); throw e; } }); diff --git a/web-api/src/genericHandler.js b/web-api/src/genericHandler.js index 6bd52248105..3e10b013a45 100644 --- a/web-api/src/genericHandler.js +++ b/web-api/src/genericHandler.js @@ -8,21 +8,25 @@ exports.dataSecurityFilter = (data, { applicationContext }) => { const entityConstructor = applicationContext.getEntityByName( data[0].entityName, ); - returnData = data.map( - result => - new entityConstructor(result, { - applicationContext, - filtered: true, - }), - ); + if (entityConstructor) { + returnData = data.map( + result => + new entityConstructor(result, { + applicationContext, + filtered: true, + }), + ); + } } else if (data && data.entityName) { const entityConstructor = applicationContext.getEntityByName( data.entityName, ); - returnData = new entityConstructor(data, { - applicationContext, - filtered: true, - }); + if (entityConstructor) { + returnData = new entityConstructor(data, { + applicationContext, + filtered: true, + }); + } } return returnData; }; @@ -41,7 +45,6 @@ exports.genericHandler = (event, cb, options = {}) => { const user = options.user || getUserFromAuthHeader(event); const applicationContext = options.applicationContext || createApplicationContext(user); // This is mostly for testing purposes - const honeybadger = applicationContext.initHoneybadger(); const { isPublicUser, @@ -84,7 +87,7 @@ exports.genericHandler = (event, cb, options = {}) => { if (!e.skipLogging) { // we don't want email alerts to be sent out just because someone searched for a non-existing case applicationContext.logger.error(e); - honeybadger && honeybadger.notify(e); + await applicationContext.notifyHoneybadger(e); } throw e; } diff --git a/web-api/src/genericHandler.test.js b/web-api/src/genericHandler.test.js index 9978e8dd3ca..3ea4387359a 100644 --- a/web-api/src/genericHandler.test.js +++ b/web-api/src/genericHandler.test.js @@ -58,7 +58,7 @@ describe('genericHandler', () => { expect(response.statusCode).toEqual('400'); expect(JSON.parse(response.body)).toEqual('Test Error'); expect(applicationContext.logger.error).toHaveBeenCalled(); - expect(applicationContext.initHoneybadger().notify).toHaveBeenCalled(); + expect(applicationContext.notifyHoneybadger).toHaveBeenCalled(); }); it('defaults the options param to an empty object if not provided', async () => { @@ -83,7 +83,7 @@ describe('genericHandler', () => { expect(response.statusCode).toEqual('400'); expect(JSON.parse(response.body)).toEqual('Test Error'); expect(applicationContext.logger.error).not.toHaveBeenCalled(); - expect(applicationContext.initHoneybadger().notify).not.toHaveBeenCalled(); + expect(applicationContext.notifyHoneybadger).not.toHaveBeenCalled(); }); it('can take a user override in the options param', async () => { @@ -233,6 +233,21 @@ describe('genericHandler', () => { }); }); + it('returns data without passing through entity constructor if entityName is not present in getEntityConstructors', () => { + applicationContext.getEntityByName.mockImplementation(() => null); + const data = { + entityName: 'MockEntity2', + private: 'private', + public: 'public', + }; + const result = dataSecurityFilter(data, { applicationContext }); + expect(result).toEqual({ + entityName: 'MockEntity2', + private: 'private', + public: 'public', + }); + }); + it('returns array data after passing through entity constructor if entityName is present on array element', () => { const data = [ { @@ -249,5 +264,34 @@ describe('genericHandler', () => { const result = dataSecurityFilter(data, { applicationContext }); expect(result).toEqual([{ public: 'public' }, { public: 'public' }]); }); + + it('returns array data after passing through entity constructor if entityName is present on array element', () => { + applicationContext.getEntityByName.mockImplementation(() => null); + const data = [ + { + entityName: 'MockEntity2', + private: 'private', + public: 'public', + }, + { + entityName: 'MockEntity2', + private: 'private', + public: 'public', + }, + ]; + const result = dataSecurityFilter(data, { applicationContext }); + expect(result).toEqual([ + { + entityName: 'MockEntity2', + private: 'private', + public: 'public', + }, + { + entityName: 'MockEntity2', + private: 'private', + public: 'public', + }, + ]); + }); }); }); diff --git a/web-api/src/public-api/getPublicDocumentDownloadUrlLambda.js b/web-api/src/public-api/getPublicDocumentDownloadUrlLambda.js index c43ef843c24..497cb249f27 100644 --- a/web-api/src/public-api/getPublicDocumentDownloadUrlLambda.js +++ b/web-api/src/public-api/getPublicDocumentDownloadUrlLambda.js @@ -10,7 +10,6 @@ const { redirect } = require('../middleware/apiGatewayHelper'); exports.getPublicDocumentDownloadUrlLambda = event => redirect(event, async () => { const applicationContext = createApplicationContext({}); - const honeybadger = applicationContext.initHoneybadger(); try { const results = await applicationContext .getUseCases() @@ -23,7 +22,7 @@ exports.getPublicDocumentDownloadUrlLambda = event => return results; } catch (e) { applicationContext.logger.error(e); - honeybadger && honeybadger.notify(e); + await applicationContext.notifyHoneybadger(e); throw e; } }); diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/0048b9e5-15e8-4315-8b9c-8a2e181205e4._S3rver_metadata.json b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/0048b9e5-15e8-4315-8b9c-8a2e181205e4._S3rver_metadata.json new file mode 100644 index 00000000000..d61de8aaa51 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/0048b9e5-15e8-4315-8b9c-8a2e181205e4._S3rver_metadata.json @@ -0,0 +1 @@ +{ "content-type": "application/pdf" } diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/0048b9e5-15e8-4315-8b9c-8a2e181205e4._S3rver_object b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/0048b9e5-15e8-4315-8b9c-8a2e181205e4._S3rver_object new file mode 100644 index 00000000000..b562e8cb6a9 Binary files /dev/null and b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/0048b9e5-15e8-4315-8b9c-8a2e181205e4._S3rver_object differ diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/0048b9e5-15e8-4315-8b9c-8a2e181205e4._S3rver_object.md5 b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/0048b9e5-15e8-4315-8b9c-8a2e181205e4._S3rver_object.md5 new file mode 100644 index 00000000000..76dc73b22b1 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/0048b9e5-15e8-4315-8b9c-8a2e181205e4._S3rver_object.md5 @@ -0,0 +1 @@ +853df0ac3ebd6343be5490072eb870d6 \ No newline at end of file diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/06f60736-5f37-4590-b62a-5c7edf84ffc6._S3rver_metadata.json b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/06f60736-5f37-4590-b62a-5c7edf84ffc6._S3rver_metadata.json new file mode 100644 index 00000000000..d61de8aaa51 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/06f60736-5f37-4590-b62a-5c7edf84ffc6._S3rver_metadata.json @@ -0,0 +1 @@ +{ "content-type": "application/pdf" } diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/06f60736-5f37-4590-b62a-5c7edf84ffc6._S3rver_object b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/06f60736-5f37-4590-b62a-5c7edf84ffc6._S3rver_object new file mode 100644 index 00000000000..b562e8cb6a9 Binary files /dev/null and b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/06f60736-5f37-4590-b62a-5c7edf84ffc6._S3rver_object differ diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/06f60736-5f37-4590-b62a-5c7edf84ffc6._S3rver_object.md5 b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/06f60736-5f37-4590-b62a-5c7edf84ffc6._S3rver_object.md5 new file mode 100644 index 00000000000..76dc73b22b1 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/06f60736-5f37-4590-b62a-5c7edf84ffc6._S3rver_object.md5 @@ -0,0 +1 @@ +853df0ac3ebd6343be5490072eb870d6 \ No newline at end of file diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/1a92894e-83a5-48ba-9994-3ada44235deb._S3rver_metadata.json b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/1a92894e-83a5-48ba-9994-3ada44235deb._S3rver_metadata.json new file mode 100644 index 00000000000..d61de8aaa51 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/1a92894e-83a5-48ba-9994-3ada44235deb._S3rver_metadata.json @@ -0,0 +1 @@ +{ "content-type": "application/pdf" } diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/1a92894e-83a5-48ba-9994-3ada44235deb._S3rver_object b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/1a92894e-83a5-48ba-9994-3ada44235deb._S3rver_object new file mode 100644 index 00000000000..b562e8cb6a9 Binary files /dev/null and b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/1a92894e-83a5-48ba-9994-3ada44235deb._S3rver_object differ diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/1a92894e-83a5-48ba-9994-3ada44235deb._S3rver_object.md5 b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/1a92894e-83a5-48ba-9994-3ada44235deb._S3rver_object.md5 new file mode 100644 index 00000000000..76dc73b22b1 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/1a92894e-83a5-48ba-9994-3ada44235deb._S3rver_object.md5 @@ -0,0 +1 @@ +853df0ac3ebd6343be5490072eb870d6 \ No newline at end of file diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/1c56d0fc-b01b-4bc7-830f-0c25b4e6b803._S3rver_metadata.json b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/1c56d0fc-b01b-4bc7-830f-0c25b4e6b803._S3rver_metadata.json new file mode 100644 index 00000000000..d61de8aaa51 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/1c56d0fc-b01b-4bc7-830f-0c25b4e6b803._S3rver_metadata.json @@ -0,0 +1 @@ +{ "content-type": "application/pdf" } diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/1c56d0fc-b01b-4bc7-830f-0c25b4e6b803._S3rver_object b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/1c56d0fc-b01b-4bc7-830f-0c25b4e6b803._S3rver_object new file mode 100644 index 00000000000..b562e8cb6a9 Binary files /dev/null and b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/1c56d0fc-b01b-4bc7-830f-0c25b4e6b803._S3rver_object differ diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/1c56d0fc-b01b-4bc7-830f-0c25b4e6b803._S3rver_object.md5 b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/1c56d0fc-b01b-4bc7-830f-0c25b4e6b803._S3rver_object.md5 new file mode 100644 index 00000000000..76dc73b22b1 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/1c56d0fc-b01b-4bc7-830f-0c25b4e6b803._S3rver_object.md5 @@ -0,0 +1 @@ +853df0ac3ebd6343be5490072eb870d6 \ No newline at end of file diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/28caad58-df69-4a4d-af15-6554aee7fbd6._S3rver_metadata.json b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/28caad58-df69-4a4d-af15-6554aee7fbd6._S3rver_metadata.json new file mode 100644 index 00000000000..d61de8aaa51 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/28caad58-df69-4a4d-af15-6554aee7fbd6._S3rver_metadata.json @@ -0,0 +1 @@ +{ "content-type": "application/pdf" } diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/28caad58-df69-4a4d-af15-6554aee7fbd6._S3rver_object b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/28caad58-df69-4a4d-af15-6554aee7fbd6._S3rver_object new file mode 100644 index 00000000000..b562e8cb6a9 Binary files /dev/null and b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/28caad58-df69-4a4d-af15-6554aee7fbd6._S3rver_object differ diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/28caad58-df69-4a4d-af15-6554aee7fbd6._S3rver_object.md5 b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/28caad58-df69-4a4d-af15-6554aee7fbd6._S3rver_object.md5 new file mode 100644 index 00000000000..76dc73b22b1 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/28caad58-df69-4a4d-af15-6554aee7fbd6._S3rver_object.md5 @@ -0,0 +1 @@ +853df0ac3ebd6343be5490072eb870d6 \ No newline at end of file diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/2cca1543-21b2-4783-a1de-eeaaf269d32c._S3rver_metadata.json b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/2cca1543-21b2-4783-a1de-eeaaf269d32c._S3rver_metadata.json new file mode 100644 index 00000000000..d61de8aaa51 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/2cca1543-21b2-4783-a1de-eeaaf269d32c._S3rver_metadata.json @@ -0,0 +1 @@ +{ "content-type": "application/pdf" } diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/2cca1543-21b2-4783-a1de-eeaaf269d32c._S3rver_object b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/2cca1543-21b2-4783-a1de-eeaaf269d32c._S3rver_object new file mode 100644 index 00000000000..b562e8cb6a9 Binary files /dev/null and b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/2cca1543-21b2-4783-a1de-eeaaf269d32c._S3rver_object differ diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/2cca1543-21b2-4783-a1de-eeaaf269d32c._S3rver_object.md5 b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/2cca1543-21b2-4783-a1de-eeaaf269d32c._S3rver_object.md5 new file mode 100644 index 00000000000..76dc73b22b1 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/2cca1543-21b2-4783-a1de-eeaaf269d32c._S3rver_object.md5 @@ -0,0 +1 @@ +853df0ac3ebd6343be5490072eb870d6 \ No newline at end of file diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/2da6d239-555a-40e8-af81-1949c8270cd7._S3rver_metadata.json b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/2da6d239-555a-40e8-af81-1949c8270cd7._S3rver_metadata.json new file mode 100644 index 00000000000..d61de8aaa51 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/2da6d239-555a-40e8-af81-1949c8270cd7._S3rver_metadata.json @@ -0,0 +1 @@ +{ "content-type": "application/pdf" } diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/2da6d239-555a-40e8-af81-1949c8270cd7._S3rver_object b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/2da6d239-555a-40e8-af81-1949c8270cd7._S3rver_object new file mode 100644 index 00000000000..b562e8cb6a9 Binary files /dev/null and b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/2da6d239-555a-40e8-af81-1949c8270cd7._S3rver_object differ diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/2da6d239-555a-40e8-af81-1949c8270cd7._S3rver_object.md5 b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/2da6d239-555a-40e8-af81-1949c8270cd7._S3rver_object.md5 new file mode 100644 index 00000000000..76dc73b22b1 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/2da6d239-555a-40e8-af81-1949c8270cd7._S3rver_object.md5 @@ -0,0 +1 @@ +853df0ac3ebd6343be5490072eb870d6 \ No newline at end of file diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/337b0684-0a8e-43fd-a9e5-3a01c8158cc8._S3rver_metadata.json b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/337b0684-0a8e-43fd-a9e5-3a01c8158cc8._S3rver_metadata.json new file mode 100644 index 00000000000..d61de8aaa51 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/337b0684-0a8e-43fd-a9e5-3a01c8158cc8._S3rver_metadata.json @@ -0,0 +1 @@ +{ "content-type": "application/pdf" } diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/337b0684-0a8e-43fd-a9e5-3a01c8158cc8._S3rver_object b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/337b0684-0a8e-43fd-a9e5-3a01c8158cc8._S3rver_object new file mode 100644 index 00000000000..b562e8cb6a9 Binary files /dev/null and b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/337b0684-0a8e-43fd-a9e5-3a01c8158cc8._S3rver_object differ diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/337b0684-0a8e-43fd-a9e5-3a01c8158cc8._S3rver_object.md5 b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/337b0684-0a8e-43fd-a9e5-3a01c8158cc8._S3rver_object.md5 new file mode 100644 index 00000000000..76dc73b22b1 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/337b0684-0a8e-43fd-a9e5-3a01c8158cc8._S3rver_object.md5 @@ -0,0 +1 @@ +853df0ac3ebd6343be5490072eb870d6 \ No newline at end of file diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/3adb712b-d0c5-40e8-98c1-d2f38757e27a._S3rver_metadata.json b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/3adb712b-d0c5-40e8-98c1-d2f38757e27a._S3rver_metadata.json new file mode 100644 index 00000000000..d61de8aaa51 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/3adb712b-d0c5-40e8-98c1-d2f38757e27a._S3rver_metadata.json @@ -0,0 +1 @@ +{ "content-type": "application/pdf" } diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/3adb712b-d0c5-40e8-98c1-d2f38757e27a._S3rver_object b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/3adb712b-d0c5-40e8-98c1-d2f38757e27a._S3rver_object new file mode 100644 index 00000000000..b562e8cb6a9 Binary files /dev/null and b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/3adb712b-d0c5-40e8-98c1-d2f38757e27a._S3rver_object differ diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/3adb712b-d0c5-40e8-98c1-d2f38757e27a._S3rver_object.md5 b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/3adb712b-d0c5-40e8-98c1-d2f38757e27a._S3rver_object.md5 new file mode 100644 index 00000000000..76dc73b22b1 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/3adb712b-d0c5-40e8-98c1-d2f38757e27a._S3rver_object.md5 @@ -0,0 +1 @@ +853df0ac3ebd6343be5490072eb870d6 \ No newline at end of file diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/3afdcbdd-2ee9-41dd-83ff-8b0ffb7d7d6a._S3rver_metadata.json b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/3afdcbdd-2ee9-41dd-83ff-8b0ffb7d7d6a._S3rver_metadata.json new file mode 100644 index 00000000000..d61de8aaa51 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/3afdcbdd-2ee9-41dd-83ff-8b0ffb7d7d6a._S3rver_metadata.json @@ -0,0 +1 @@ +{ "content-type": "application/pdf" } diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/3afdcbdd-2ee9-41dd-83ff-8b0ffb7d7d6a._S3rver_object b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/3afdcbdd-2ee9-41dd-83ff-8b0ffb7d7d6a._S3rver_object new file mode 100644 index 00000000000..b562e8cb6a9 Binary files /dev/null and b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/3afdcbdd-2ee9-41dd-83ff-8b0ffb7d7d6a._S3rver_object differ diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/3afdcbdd-2ee9-41dd-83ff-8b0ffb7d7d6a._S3rver_object.md5 b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/3afdcbdd-2ee9-41dd-83ff-8b0ffb7d7d6a._S3rver_object.md5 new file mode 100644 index 00000000000..76dc73b22b1 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/3afdcbdd-2ee9-41dd-83ff-8b0ffb7d7d6a._S3rver_object.md5 @@ -0,0 +1 @@ +853df0ac3ebd6343be5490072eb870d6 \ No newline at end of file diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/3cf1f474-1dcd-47aa-8455-8f9a93d80183._S3rver_metadata.json b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/3cf1f474-1dcd-47aa-8455-8f9a93d80183._S3rver_metadata.json new file mode 100644 index 00000000000..d61de8aaa51 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/3cf1f474-1dcd-47aa-8455-8f9a93d80183._S3rver_metadata.json @@ -0,0 +1 @@ +{ "content-type": "application/pdf" } diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/3cf1f474-1dcd-47aa-8455-8f9a93d80183._S3rver_object b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/3cf1f474-1dcd-47aa-8455-8f9a93d80183._S3rver_object new file mode 100644 index 00000000000..b562e8cb6a9 Binary files /dev/null and b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/3cf1f474-1dcd-47aa-8455-8f9a93d80183._S3rver_object differ diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/3cf1f474-1dcd-47aa-8455-8f9a93d80183._S3rver_object.md5 b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/3cf1f474-1dcd-47aa-8455-8f9a93d80183._S3rver_object.md5 new file mode 100644 index 00000000000..76dc73b22b1 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/3cf1f474-1dcd-47aa-8455-8f9a93d80183._S3rver_object.md5 @@ -0,0 +1 @@ +853df0ac3ebd6343be5490072eb870d6 \ No newline at end of file diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/4d736f72-6312-4f7f-886e-210a0074fdc3._S3rver_metadata.json b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/4d736f72-6312-4f7f-886e-210a0074fdc3._S3rver_metadata.json new file mode 100644 index 00000000000..d61de8aaa51 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/4d736f72-6312-4f7f-886e-210a0074fdc3._S3rver_metadata.json @@ -0,0 +1 @@ +{ "content-type": "application/pdf" } diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/4d736f72-6312-4f7f-886e-210a0074fdc3._S3rver_object b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/4d736f72-6312-4f7f-886e-210a0074fdc3._S3rver_object new file mode 100644 index 00000000000..b562e8cb6a9 Binary files /dev/null and b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/4d736f72-6312-4f7f-886e-210a0074fdc3._S3rver_object differ diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/4d736f72-6312-4f7f-886e-210a0074fdc3._S3rver_object.md5 b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/4d736f72-6312-4f7f-886e-210a0074fdc3._S3rver_object.md5 new file mode 100644 index 00000000000..76dc73b22b1 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/4d736f72-6312-4f7f-886e-210a0074fdc3._S3rver_object.md5 @@ -0,0 +1 @@ +853df0ac3ebd6343be5490072eb870d6 \ No newline at end of file diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/562b0a52-7960-4674-acb7-22b65cd1cf2b._S3rver_metadata.json b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/562b0a52-7960-4674-acb7-22b65cd1cf2b._S3rver_metadata.json new file mode 100644 index 00000000000..d61de8aaa51 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/562b0a52-7960-4674-acb7-22b65cd1cf2b._S3rver_metadata.json @@ -0,0 +1 @@ +{ "content-type": "application/pdf" } diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/562b0a52-7960-4674-acb7-22b65cd1cf2b._S3rver_object b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/562b0a52-7960-4674-acb7-22b65cd1cf2b._S3rver_object new file mode 100644 index 00000000000..b562e8cb6a9 Binary files /dev/null and b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/562b0a52-7960-4674-acb7-22b65cd1cf2b._S3rver_object differ diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/562b0a52-7960-4674-acb7-22b65cd1cf2b._S3rver_object.md5 b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/562b0a52-7960-4674-acb7-22b65cd1cf2b._S3rver_object.md5 new file mode 100644 index 00000000000..76dc73b22b1 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/562b0a52-7960-4674-acb7-22b65cd1cf2b._S3rver_object.md5 @@ -0,0 +1 @@ +853df0ac3ebd6343be5490072eb870d6 \ No newline at end of file diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/596223c1-527b-46b4-98b0-1b10455e9495._S3rver_metadata.json b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/596223c1-527b-46b4-98b0-1b10455e9495._S3rver_metadata.json new file mode 100644 index 00000000000..d61de8aaa51 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/596223c1-527b-46b4-98b0-1b10455e9495._S3rver_metadata.json @@ -0,0 +1 @@ +{ "content-type": "application/pdf" } diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/596223c1-527b-46b4-98b0-1b10455e9495._S3rver_object b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/596223c1-527b-46b4-98b0-1b10455e9495._S3rver_object new file mode 100644 index 00000000000..b562e8cb6a9 Binary files /dev/null and b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/596223c1-527b-46b4-98b0-1b10455e9495._S3rver_object differ diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/596223c1-527b-46b4-98b0-1b10455e9495._S3rver_object.md5 b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/596223c1-527b-46b4-98b0-1b10455e9495._S3rver_object.md5 new file mode 100644 index 00000000000..76dc73b22b1 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/596223c1-527b-46b4-98b0-1b10455e9495._S3rver_object.md5 @@ -0,0 +1 @@ +853df0ac3ebd6343be5490072eb870d6 \ No newline at end of file diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/59ccf18f-5bac-48b0-a8e0-9c9e1d995b62._S3rver_metadata.json b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/59ccf18f-5bac-48b0-a8e0-9c9e1d995b62._S3rver_metadata.json new file mode 100644 index 00000000000..d61de8aaa51 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/59ccf18f-5bac-48b0-a8e0-9c9e1d995b62._S3rver_metadata.json @@ -0,0 +1 @@ +{ "content-type": "application/pdf" } diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/59ccf18f-5bac-48b0-a8e0-9c9e1d995b62._S3rver_object b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/59ccf18f-5bac-48b0-a8e0-9c9e1d995b62._S3rver_object new file mode 100644 index 00000000000..b562e8cb6a9 Binary files /dev/null and b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/59ccf18f-5bac-48b0-a8e0-9c9e1d995b62._S3rver_object differ diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/59ccf18f-5bac-48b0-a8e0-9c9e1d995b62._S3rver_object.md5 b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/59ccf18f-5bac-48b0-a8e0-9c9e1d995b62._S3rver_object.md5 new file mode 100644 index 00000000000..76dc73b22b1 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/59ccf18f-5bac-48b0-a8e0-9c9e1d995b62._S3rver_object.md5 @@ -0,0 +1 @@ +853df0ac3ebd6343be5490072eb870d6 \ No newline at end of file diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/6d83425c-8ef3-4c66-b776-6c7957c53f4d._S3rver_metadata.json b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/6d83425c-8ef3-4c66-b776-6c7957c53f4d._S3rver_metadata.json new file mode 100644 index 00000000000..d61de8aaa51 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/6d83425c-8ef3-4c66-b776-6c7957c53f4d._S3rver_metadata.json @@ -0,0 +1 @@ +{ "content-type": "application/pdf" } diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/6d83425c-8ef3-4c66-b776-6c7957c53f4d._S3rver_object b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/6d83425c-8ef3-4c66-b776-6c7957c53f4d._S3rver_object new file mode 100644 index 00000000000..b562e8cb6a9 Binary files /dev/null and b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/6d83425c-8ef3-4c66-b776-6c7957c53f4d._S3rver_object differ diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/6d83425c-8ef3-4c66-b776-6c7957c53f4d._S3rver_object.md5 b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/6d83425c-8ef3-4c66-b776-6c7957c53f4d._S3rver_object.md5 new file mode 100644 index 00000000000..76dc73b22b1 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/6d83425c-8ef3-4c66-b776-6c7957c53f4d._S3rver_object.md5 @@ -0,0 +1 @@ +853df0ac3ebd6343be5490072eb870d6 \ No newline at end of file diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/9de27a7d-7c6b-434b-803b-7655f82d5e07._S3rver_metadata.json b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/9de27a7d-7c6b-434b-803b-7655f82d5e07._S3rver_metadata.json new file mode 100644 index 00000000000..d61de8aaa51 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/9de27a7d-7c6b-434b-803b-7655f82d5e07._S3rver_metadata.json @@ -0,0 +1 @@ +{ "content-type": "application/pdf" } diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/9de27a7d-7c6b-434b-803b-7655f82d5e07._S3rver_object b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/9de27a7d-7c6b-434b-803b-7655f82d5e07._S3rver_object new file mode 100644 index 00000000000..b562e8cb6a9 Binary files /dev/null and b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/9de27a7d-7c6b-434b-803b-7655f82d5e07._S3rver_object differ diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/9de27a7d-7c6b-434b-803b-7655f82d5e07._S3rver_object.md5 b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/9de27a7d-7c6b-434b-803b-7655f82d5e07._S3rver_object.md5 new file mode 100644 index 00000000000..76dc73b22b1 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/9de27a7d-7c6b-434b-803b-7655f82d5e07._S3rver_object.md5 @@ -0,0 +1 @@ +853df0ac3ebd6343be5490072eb870d6 \ No newline at end of file diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/abba69d5-a96a-423c-937f-b4d1c5442bf4._S3rver_metadata.json b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/abba69d5-a96a-423c-937f-b4d1c5442bf4._S3rver_metadata.json new file mode 100644 index 00000000000..d61de8aaa51 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/abba69d5-a96a-423c-937f-b4d1c5442bf4._S3rver_metadata.json @@ -0,0 +1 @@ +{ "content-type": "application/pdf" } diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/abba69d5-a96a-423c-937f-b4d1c5442bf4._S3rver_object b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/abba69d5-a96a-423c-937f-b4d1c5442bf4._S3rver_object new file mode 100644 index 00000000000..b562e8cb6a9 Binary files /dev/null and b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/abba69d5-a96a-423c-937f-b4d1c5442bf4._S3rver_object differ diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/abba69d5-a96a-423c-937f-b4d1c5442bf4._S3rver_object.md5 b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/abba69d5-a96a-423c-937f-b4d1c5442bf4._S3rver_object.md5 new file mode 100644 index 00000000000..76dc73b22b1 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/abba69d5-a96a-423c-937f-b4d1c5442bf4._S3rver_object.md5 @@ -0,0 +1 @@ +853df0ac3ebd6343be5490072eb870d6 \ No newline at end of file diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/ac62f25a-49f9-46a5-aed7-d6b955a2dc34._S3rver_metadata.json b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/ac62f25a-49f9-46a5-aed7-d6b955a2dc34._S3rver_metadata.json new file mode 100644 index 00000000000..d61de8aaa51 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/ac62f25a-49f9-46a5-aed7-d6b955a2dc34._S3rver_metadata.json @@ -0,0 +1 @@ +{ "content-type": "application/pdf" } diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/ac62f25a-49f9-46a5-aed7-d6b955a2dc34._S3rver_object b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/ac62f25a-49f9-46a5-aed7-d6b955a2dc34._S3rver_object new file mode 100644 index 00000000000..b562e8cb6a9 Binary files /dev/null and b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/ac62f25a-49f9-46a5-aed7-d6b955a2dc34._S3rver_object differ diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/ac62f25a-49f9-46a5-aed7-d6b955a2dc34._S3rver_object.md5 b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/ac62f25a-49f9-46a5-aed7-d6b955a2dc34._S3rver_object.md5 new file mode 100644 index 00000000000..76dc73b22b1 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/ac62f25a-49f9-46a5-aed7-d6b955a2dc34._S3rver_object.md5 @@ -0,0 +1 @@ +853df0ac3ebd6343be5490072eb870d6 \ No newline at end of file diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/af6f67db-3160-4562-ac36-5481ab091952._S3rver_metadata.json b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/af6f67db-3160-4562-ac36-5481ab091952._S3rver_metadata.json new file mode 100644 index 00000000000..d61de8aaa51 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/af6f67db-3160-4562-ac36-5481ab091952._S3rver_metadata.json @@ -0,0 +1 @@ +{ "content-type": "application/pdf" } diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/af6f67db-3160-4562-ac36-5481ab091952._S3rver_object b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/af6f67db-3160-4562-ac36-5481ab091952._S3rver_object new file mode 100644 index 00000000000..b562e8cb6a9 Binary files /dev/null and b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/af6f67db-3160-4562-ac36-5481ab091952._S3rver_object differ diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/af6f67db-3160-4562-ac36-5481ab091952._S3rver_object.md5 b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/af6f67db-3160-4562-ac36-5481ab091952._S3rver_object.md5 new file mode 100644 index 00000000000..76dc73b22b1 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/af6f67db-3160-4562-ac36-5481ab091952._S3rver_object.md5 @@ -0,0 +1 @@ +853df0ac3ebd6343be5490072eb870d6 \ No newline at end of file diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/af9e2d43-1255-4e3d-80d0-63f0aedfab5a._S3rver_metadata.json b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/af9e2d43-1255-4e3d-80d0-63f0aedfab5a._S3rver_metadata.json new file mode 100644 index 00000000000..d61de8aaa51 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/af9e2d43-1255-4e3d-80d0-63f0aedfab5a._S3rver_metadata.json @@ -0,0 +1 @@ +{ "content-type": "application/pdf" } diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/af9e2d43-1255-4e3d-80d0-63f0aedfab5a._S3rver_object b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/af9e2d43-1255-4e3d-80d0-63f0aedfab5a._S3rver_object new file mode 100644 index 00000000000..b562e8cb6a9 Binary files /dev/null and b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/af9e2d43-1255-4e3d-80d0-63f0aedfab5a._S3rver_object differ diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/af9e2d43-1255-4e3d-80d0-63f0aedfab5a._S3rver_object.md5 b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/af9e2d43-1255-4e3d-80d0-63f0aedfab5a._S3rver_object.md5 new file mode 100644 index 00000000000..76dc73b22b1 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/af9e2d43-1255-4e3d-80d0-63f0aedfab5a._S3rver_object.md5 @@ -0,0 +1 @@ +853df0ac3ebd6343be5490072eb870d6 \ No newline at end of file diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/cb323daf-c541-4645-bb44-232255d03d40._S3rver_metadata.json b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/cb323daf-c541-4645-bb44-232255d03d40._S3rver_metadata.json new file mode 100644 index 00000000000..d61de8aaa51 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/cb323daf-c541-4645-bb44-232255d03d40._S3rver_metadata.json @@ -0,0 +1 @@ +{ "content-type": "application/pdf" } diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/cb323daf-c541-4645-bb44-232255d03d40._S3rver_object b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/cb323daf-c541-4645-bb44-232255d03d40._S3rver_object new file mode 100644 index 00000000000..b562e8cb6a9 Binary files /dev/null and b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/cb323daf-c541-4645-bb44-232255d03d40._S3rver_object differ diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/cb323daf-c541-4645-bb44-232255d03d40._S3rver_object.md5 b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/cb323daf-c541-4645-bb44-232255d03d40._S3rver_object.md5 new file mode 100644 index 00000000000..76dc73b22b1 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/cb323daf-c541-4645-bb44-232255d03d40._S3rver_object.md5 @@ -0,0 +1 @@ +853df0ac3ebd6343be5490072eb870d6 \ No newline at end of file diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/d854a954-7332-4e92-93bd-dc28c9fea0a5._S3rver_metadata.json b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/d854a954-7332-4e92-93bd-dc28c9fea0a5._S3rver_metadata.json new file mode 100644 index 00000000000..d61de8aaa51 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/d854a954-7332-4e92-93bd-dc28c9fea0a5._S3rver_metadata.json @@ -0,0 +1 @@ +{ "content-type": "application/pdf" } diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/d854a954-7332-4e92-93bd-dc28c9fea0a5._S3rver_object b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/d854a954-7332-4e92-93bd-dc28c9fea0a5._S3rver_object new file mode 100644 index 00000000000..b562e8cb6a9 Binary files /dev/null and b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/d854a954-7332-4e92-93bd-dc28c9fea0a5._S3rver_object differ diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/d854a954-7332-4e92-93bd-dc28c9fea0a5._S3rver_object.md5 b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/d854a954-7332-4e92-93bd-dc28c9fea0a5._S3rver_object.md5 new file mode 100644 index 00000000000..76dc73b22b1 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/d854a954-7332-4e92-93bd-dc28c9fea0a5._S3rver_object.md5 @@ -0,0 +1 @@ +853df0ac3ebd6343be5490072eb870d6 \ No newline at end of file diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/dc2664a1-f552-418f-bcc7-8a67f4246568._S3rver_metadata.json b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/dc2664a1-f552-418f-bcc7-8a67f4246568._S3rver_metadata.json new file mode 100644 index 00000000000..d61de8aaa51 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/dc2664a1-f552-418f-bcc7-8a67f4246568._S3rver_metadata.json @@ -0,0 +1 @@ +{ "content-type": "application/pdf" } diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/dc2664a1-f552-418f-bcc7-8a67f4246568._S3rver_object b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/dc2664a1-f552-418f-bcc7-8a67f4246568._S3rver_object new file mode 100644 index 00000000000..b562e8cb6a9 Binary files /dev/null and b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/dc2664a1-f552-418f-bcc7-8a67f4246568._S3rver_object differ diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/dc2664a1-f552-418f-bcc7-8a67f4246568._S3rver_object.md5 b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/dc2664a1-f552-418f-bcc7-8a67f4246568._S3rver_object.md5 new file mode 100644 index 00000000000..76dc73b22b1 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/dc2664a1-f552-418f-bcc7-8a67f4246568._S3rver_object.md5 @@ -0,0 +1 @@ +853df0ac3ebd6343be5490072eb870d6 \ No newline at end of file diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/f6f9ce81-8b65-433c-8c7b-f0ffa7a74068._S3rver_metadata.json b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/f6f9ce81-8b65-433c-8c7b-f0ffa7a74068._S3rver_metadata.json new file mode 100644 index 00000000000..d61de8aaa51 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/f6f9ce81-8b65-433c-8c7b-f0ffa7a74068._S3rver_metadata.json @@ -0,0 +1 @@ +{ "content-type": "application/pdf" } diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/f6f9ce81-8b65-433c-8c7b-f0ffa7a74068._S3rver_object b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/f6f9ce81-8b65-433c-8c7b-f0ffa7a74068._S3rver_object new file mode 100644 index 00000000000..b562e8cb6a9 Binary files /dev/null and b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/f6f9ce81-8b65-433c-8c7b-f0ffa7a74068._S3rver_object differ diff --git a/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/f6f9ce81-8b65-433c-8c7b-f0ffa7a74068._S3rver_object.md5 b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/f6f9ce81-8b65-433c-8c7b-f0ffa7a74068._S3rver_object.md5 new file mode 100644 index 00000000000..76dc73b22b1 --- /dev/null +++ b/web-api/storage/fixtures/s3/noop-documents-local-us-east-1/f6f9ce81-8b65-433c-8c7b-f0ffa7a74068._S3rver_object.md5 @@ -0,0 +1 @@ +853df0ac3ebd6343be5490072eb870d6 \ No newline at end of file diff --git a/web-api/storage/fixtures/seed/101-19.json b/web-api/storage/fixtures/seed/101-19.json index 7e43db36cc3..dfc562d20c4 100755 --- a/web-api/storage/fixtures/seed/101-19.json +++ b/web-api/storage/fixtures/seed/101-19.json @@ -99,7 +99,7 @@ "assigneeName": null, "caseId": "2fa6da8d-4328-4a20-a5d7-b76637e1dc02", "gsi1pk": "work-item|2611344f-f7bf-4f47-8ba0-60c70cb25446", - "caseCaptionNames": "Brett Osborne", + "caseTitle": "Brett Osborne", "messages": [ { "createdAt": "2019-03-01T21:40:46.415Z", @@ -140,7 +140,7 @@ "assigneeName": null, "caseId": "2fa6da8d-4328-4a20-a5d7-b76637e1dc02", "gsi1pk": "work-item|2611344f-f7bf-4f47-8ba0-60c70cb25446", - "caseCaptionNames": "Brett Osborne", + "caseTitle": "Brett Osborne", "messages": [ { "createdAt": "2019-03-01T21:40:46.415Z", @@ -160,6 +160,7 @@ }, { "documentType": "Petition", + "entityName": "Document", "filingDate": "2019-03-01T21:40:46.415Z", "workItems": [ { @@ -175,7 +176,7 @@ "userId": "7805d1ab-18d0-43ec-bafb-654e83405416", "filedBy": "Test Petitioner" }, - "caseCaptionNames": "Brett Osborne", + "caseTitle": "Brett Osborne", "section": "petitions", "workItemId": "2611344f-f7bf-4f47-8ba0-60c70cb25446", "isInitializeCase": true, @@ -232,6 +233,7 @@ "sk": "document|25100ec6-eeeb-4e88-872f-c99fad1fe6c7", "signedAt": "2019-10-07T14:29:30.288Z", "documentId": "25100ec6-eeeb-4e88-872f-c99fad1fe6c7", + "entityName": "Document", "signedByUserId": "1805d1ab-18d0-43ec-bafb-654e83405416", "pk": "case|2fa6da8d-4328-4a20-a5d7-b76637e1dc02", "documentTitle": "Order of Dismissal for Lack of Jurisdiction", @@ -249,6 +251,7 @@ "processingStatus": "complete", "filedBy": "Test Petitioner", "caseId": "2fa6da8d-4328-4a20-a5d7-b76637e1dc02", + "entityName": "Document", "sk": "document|b1aa4aa2-c214-424c-8870-d0049c5744d8", "documentId": "b1aa4aa2-c214-424c-8870-d0049c5744d8", "pk": "case|2fa6da8d-4328-4a20-a5d7-b76637e1dc02" diff --git a/web-api/storage/fixtures/seed/101-20.json b/web-api/storage/fixtures/seed/101-20.json index 860b913fa2e..ce24f604924 100644 --- a/web-api/storage/fixtures/seed/101-20.json +++ b/web-api/storage/fixtures/seed/101-20.json @@ -79,6 +79,7 @@ }, { "documentType": "Statement of Taxpayer Identification", + "entityName": "Document", "filingDate": "2020-01-02T16:05:45.980Z", "practitioner": [], "partyPrimary": true, @@ -98,6 +99,7 @@ }, { "documentType": "Petition", + "entityName": "Document", "filingDate": "2020-01-02T16:05:45.979Z", "practitioner": [], "partyPrimary": true, @@ -121,7 +123,7 @@ "receivedAt": "2020-01-02T16:05:45.979Z", "userId": "7805d1ab-18d0-43ec-bafb-654e83405416" }, - "caseCaptionNames": "Bill Burr", + "caseTitle": "Bill Burr", "section": "petitions", "workItemId": "c4b34a7e-2b0a-4b6b-a406-b53b19d08cc4", "isInitializeCase": true, diff --git a/web-api/storage/fixtures/seed/102-19.json b/web-api/storage/fixtures/seed/102-19.json index 9a236798d2f..bc86472afb7 100755 --- a/web-api/storage/fixtures/seed/102-19.json +++ b/web-api/storage/fixtures/seed/102-19.json @@ -109,7 +109,7 @@ "assigneeName": null, "caseId": "fa1179bd-04f5-4934-a716-964d8d7babc6", "sk": "work-item|4df3fa30-a1ad-45e1-ae1e-05256c538e72", - "caseCaptionNames": "Selma Horn & Cairo Harris", + "caseTitle": "Selma Horn & Cairo Harris", "messages": [ { "createdAt": "2019-03-01T21:42:29.073Z", @@ -149,7 +149,7 @@ "assigneeName": null, "caseId": "fa1179bd-04f5-4934-a716-964d8d7babc6", "gsi1pk": "work-item|4df3fa30-a1ad-45e1-ae1e-05256c538e72", - "caseCaptionNames": "Selma Horn & Cairo Harris", + "caseTitle": "Selma Horn & Cairo Harris", "messages": [ { "createdAt": "2019-03-01T21:42:29.073Z", @@ -187,7 +187,7 @@ "createdAt": "2019-03-01T21:42:29.073Z", "assigneeName": null, "caseId": "fa1179bd-04f5-4934-a716-964d8d7babc6", - "caseCaptionNames": "Selma Horn & Cairo Harris", + "caseTitle": "Selma Horn & Cairo Harris", "messages": [ { "createdAt": "2019-03-01T21:42:29.073Z", @@ -207,6 +207,7 @@ }, { "documentType": "Petition", + "entityName": "Document", "filingDate": "2019-03-01T21:42:29.073Z", "workItems": [ { @@ -222,7 +223,7 @@ "userId": "7805d1ab-18d0-43ec-bafb-654e83405416", "filedBy": "Test Petitioner" }, - "caseCaptionNames": "Selma Horn & Cairo Harris", + "caseTitle": "Selma Horn & Cairo Harris", "section": "petitions", "workItemId": "4df3fa30-a1ad-45e1-ae1e-05256c538e72", "isInitializeCase": true, diff --git a/web-api/storage/fixtures/seed/102-20.json b/web-api/storage/fixtures/seed/102-20.json index 8124f749eea..093b667923a 100644 --- a/web-api/storage/fixtures/seed/102-20.json +++ b/web-api/storage/fixtures/seed/102-20.json @@ -19,7 +19,7 @@ "filingDate": "2020-01-21T16:41:39.481Z", "userId": "7805d1ab-18d0-43ec-bafb-654e83405416" }, - "caseCaptionNames": "Eve Brewer", + "caseTitle": "Eve Brewer", "section": "petitions", "workItemId": "77d8449a-ffe1-48e5-b056-a6112a819a4b", "isInitializeCase": true, @@ -80,7 +80,7 @@ "filingDate": "2020-01-21T16:41:39.481Z", "userId": "7805d1ab-18d0-43ec-bafb-654e83405416" }, - "caseCaptionNames": "Eve Brewer", + "caseTitle": "Eve Brewer", "section": "petitions", "workItemId": "77d8449a-ffe1-48e5-b056-a6112a819a4b", "isInitializeCase": true, @@ -226,6 +226,7 @@ }, { "documentType": "Statement of Taxpayer Identification", + "entityName": "Document", "filingDate": "2020-01-21T16:41:39.483Z", "practitioner": [], "partyPrimary": true, @@ -245,6 +246,7 @@ }, { "documentType": "Petition", + "entityName": "Document", "filingDate": "2020-01-21T16:41:39.481Z", "practitioner": [], "partyPrimary": true, @@ -268,7 +270,7 @@ "receivedAt": "2020-01-21T16:41:39.481Z", "userId": "7805d1ab-18d0-43ec-bafb-654e83405416" }, - "caseCaptionNames": "Eve Brewer", + "caseTitle": "Eve Brewer", "section": "petitions", "workItemId": "77d8449a-ffe1-48e5-b056-a6112a819a4b", "isInitializeCase": true, diff --git a/web-api/storage/fixtures/seed/103-19.json b/web-api/storage/fixtures/seed/103-19.json index d5d095c42f2..b6673829560 100755 --- a/web-api/storage/fixtures/seed/103-19.json +++ b/web-api/storage/fixtures/seed/103-19.json @@ -120,7 +120,7 @@ "createdAt": "2019-03-01T22:53:50.098Z", "assigneeName": null, "caseId": "491b05b4-483f-4b85-8dd7-2dd4c069eb50", - "caseCaptionNames": "Samson Workman", + "caseTitle": "Samson Workman", "messages": [ { "createdAt": "2019-03-01T22:53:50.098Z", @@ -159,7 +159,7 @@ "createdAt": "2019-03-01T22:53:50.098Z", "assigneeName": null, "caseId": "491b05b4-483f-4b85-8dd7-2dd4c069eb50", - "caseCaptionNames": "Samson Workman", + "caseTitle": "Samson Workman", "messages": [ { "createdAt": "2019-03-01T22:53:50.098Z", @@ -198,7 +198,7 @@ "createdAt": "2019-03-01T22:54:06.000Z", "assigneeName": null, "caseId": "491b05b4-483f-4b85-8dd7-2dd4c069eb50", - "caseCaptionNames": "Samson Workman", + "caseTitle": "Samson Workman", "messages": [ { "createdAt": "2019-03-01T22:54:06.000Z", @@ -236,7 +236,7 @@ "createdAt": "2019-03-01T22:54:06.000Z", "assigneeName": null, "caseId": "491b05b4-483f-4b85-8dd7-2dd4c069eb50", - "caseCaptionNames": "Samson Workman", + "caseTitle": "Samson Workman", "messages": [ { "createdAt": "2019-03-01T22:54:06.000Z", @@ -277,7 +277,7 @@ "assigneeName": "Judge Armen", "caseId": "491b05b4-483f-4b85-8dd7-2dd4c069eb50", "sk": "work-item|8686ddef-c74d-4d26-8748-6b22914c7687", - "caseCaptionNames": "Samson Workman", + "caseTitle": "Samson Workman", "messages": [ { "createdAt": "2019-08-08T14:33:24.183Z", @@ -317,7 +317,7 @@ "assigneeName": "Judge Armen", "caseId": "491b05b4-483f-4b85-8dd7-2dd4c069eb50", "sk": "2019-08-08T14:33:24.183Z", - "caseCaptionNames": "Samson Workman", + "caseTitle": "Samson Workman", "messages": [ { "createdAt": "2019-08-08T14:33:24.183Z", @@ -339,7 +339,7 @@ "caseStatus": "New", "caseIsInProgress": false, "gsi1pk": "work-item|8686ddef-c74d-4d26-8748-6b22914c7687", - "caseCaptionNames": "Samson Workman", + "caseTitle": "Samson Workman", "document": { "createdAt": "2019-03-01T22:54:05.993Z", "filingDate": "2019-03-01T22:54:05.993Z", @@ -394,7 +394,7 @@ "sentBySection": "petitions", "isQC": false, "createdAt": "2019-08-08T14:33:24.183Z", - "caseCaptionNames": "Samson Workman", + "caseTitle": "Samson Workman", "assigneeName": "Judge Armen", "caseId": "491b05b4-483f-4b85-8dd7-2dd4c069eb50", "sk": "work-item|8686ddef-c74d-4d26-8748-6b22914c7687", @@ -434,7 +434,7 @@ "sentBySection": "petitions", "isQC": false, "createdAt": "2019-08-08T14:33:24.183Z", - "caseCaptionNames": "Samson Workman", + "caseTitle": "Samson Workman", "assigneeName": "Judge Armen", "caseId": "491b05b4-483f-4b85-8dd7-2dd4c069eb50", "sk": "2019-08-08T14:33:24.183Z", @@ -482,6 +482,7 @@ }, { "documentType": "Statement of Taxpayer Identification", + "entityName": "Document", "filingDate": "2019-08-14T20:35:52.915Z", "workItems": [], "pending": false, @@ -497,6 +498,7 @@ }, { "documentType": "Petition", + "entityName": "Document", "filingDate": "2019-08-14T20:35:52.915Z", "workItems": [ { @@ -512,7 +514,7 @@ "userId": "7805d1ab-18d0-43ec-bafb-654e83405416", "filedBy": "Test Petitioner" }, - "caseCaptionNames": "Samson Workman", + "caseTitle": "Samson Workman", "section": "petitions", "workItemId": "9055257a-0a95-4b80-a728-5bb754c60e59", "isInitializeCase": true, @@ -551,6 +553,7 @@ "attachments": true, "serviceDate": null, "documentType": "Simultaneous Answering Brief", + "entityName": "Document", "filingDate": "2020-03-06T20:04:07.354Z", "partyPrimary": true, "pending": false, @@ -599,7 +602,7 @@ "category": "Simultaneous Brief", "docketNumber": "103-19" }, - "caseCaptionNames": "Samson Workman", + "caseTitle": "Samson Workman", "isRead": true, "section": "docket", "workItemId": "c716022f-f0f8-4988-b75a-1ec3b501a9c7", @@ -637,6 +640,7 @@ }, { "documentType": "Answer", + "entityName": "Document", "filingDate": "2019-08-14T20:35:52.915Z", "workItems": [ { @@ -652,7 +656,7 @@ "userId": "5805d1ab-18d0-43ec-bafb-654e83405416", "filedBy": "Test Respondent" }, - "caseCaptionNames": "Samson Workman", + "caseTitle": "Samson Workman", "section": "docket", "workItemId": "337f4e0d-cf5e-4c4f-b373-5256edbbbdf2", "assigneeId": null, diff --git a/web-api/storage/fixtures/seed/103-20.json b/web-api/storage/fixtures/seed/103-20.json index 5386e563255..9e2cac32a87 100644 --- a/web-api/storage/fixtures/seed/103-20.json +++ b/web-api/storage/fixtures/seed/103-20.json @@ -84,7 +84,7 @@ "relationship": "primaryDocument", "docketNumber": "103-20" }, - "caseCaptionNames": "Reuben Blair", + "caseTitle": "Reuben Blair", "section": "docket", "trialDate": "2020-11-27T05:00:00.000Z", "workItemId": "2a3955ca-baad-4ca7-be23-d862d2ef5310", @@ -147,7 +147,7 @@ "relationship": "primaryDocument", "docketNumber": "103-20" }, - "caseCaptionNames": "Reuben Blair", + "caseTitle": "Reuben Blair", "section": "docket", "trialDate": "2020-11-27T05:00:00.000Z", "workItemId": "2a3955ca-baad-4ca7-be23-d862d2ef5310", @@ -192,7 +192,7 @@ "userId": "7805d1ab-18d0-43ec-bafb-654e83405416" }, "gsi1pk": "work-item|1c7acdf5-480d-404a-9e3a-5d5ccc8068c2", - "caseCaptionNames": "Reuben Blair", + "caseTitle": "Reuben Blair", "section": "petitions", "trialDate": "2020-11-27T05:00:00.000Z", "workItemId": "1c7acdf5-480d-404a-9e3a-5d5ccc8068c2", @@ -328,6 +328,7 @@ ], "attachments": false, "documentType": "Administrative Record", + "entityName": "Document", "filingDate": "2020-01-23T21:45:34.520Z", "partyPrimary": true, "pending": false, @@ -373,7 +374,7 @@ "relationship": "primaryDocument", "docketNumber": "103-20" }, - "caseCaptionNames": "Reuben Blair", + "caseTitle": "Reuben Blair", "section": "docket", "trialDate": "2020-11-27T05:00:00.000Z", "workItemId": "2a3955ca-baad-4ca7-be23-d862d2ef5310", @@ -415,6 +416,7 @@ } ], "documentType": "Notice of Trial", + "entityName": "Document", "filingDate": "2020-01-23T21:45:14.136Z", "workItems": [], "pending": false, @@ -434,6 +436,7 @@ }, { "documentType": "Petition", + "entityName": "Document", "filingDate": "2020-01-23T21:44:54.043Z", "practitioner": [], "partyPrimary": true, @@ -457,7 +460,7 @@ "receivedAt": "2020-01-23T21:44:54.043Z", "userId": "7805d1ab-18d0-43ec-bafb-654e83405416" }, - "caseCaptionNames": "Reuben Blair", + "caseTitle": "Reuben Blair", "section": "petitions", "workItemId": "1c7acdf5-480d-404a-9e3a-5d5ccc8068c2", "isInitializeCase": true, @@ -495,6 +498,7 @@ }, { "documentType": "Statement of Taxpayer Identification", + "entityName": "Document", "filingDate": "2020-01-23T21:44:54.044Z", "practitioner": [], "partyPrimary": true, diff --git a/web-api/storage/fixtures/seed/104-19.json b/web-api/storage/fixtures/seed/104-19.json index 517f4f886fc..a032c825d9b 100755 --- a/web-api/storage/fixtures/seed/104-19.json +++ b/web-api/storage/fixtures/seed/104-19.json @@ -121,7 +121,7 @@ "createdAt": "2019-03-05T17:34:13.490Z", "assigneeName": null, "caseId": "5f6e8b8e-4fac-4fd7-bf3c-42f0d7c3ca05", - "caseCaptionNames": "Mufutau Wade", + "caseTitle": "Mufutau Wade", "messages": [ { "createdAt": "2019-03-05T17:34:13.490Z", @@ -161,7 +161,7 @@ "createdAt": "2019-03-05T17:34:13.490Z", "assigneeName": null, "caseId": "5f6e8b8e-4fac-4fd7-bf3c-42f0d7c3ca05", - "caseCaptionNames": "Mufutau Wade", + "caseTitle": "Mufutau Wade", "messages": [ { "createdAt": "2019-03-05T17:34:13.490Z", @@ -217,6 +217,7 @@ }, { "documentType": "Ownership Disclosure Statement", + "entityName": "Document", "filingDate": "2019-03-05T17:34:13.491Z", "workItems": [], "pending": false, @@ -232,6 +233,7 @@ }, { "documentType": "Statement of Taxpayer Identification", + "entityName": "Document", "filingDate": "2019-03-05T17:34:13.491Z", "workItems": [], "pending": false, @@ -247,6 +249,7 @@ }, { "documentType": "Petition", + "entityName": "Document", "filingDate": "2019-03-05T17:34:13.490Z", "workItems": [ { @@ -262,7 +265,7 @@ "userId": "7805d1ab-18d0-43ec-bafb-654e83405416", "filedBy": "Test Petitioner" }, - "caseCaptionNames": "Mufutau Wade", + "caseTitle": "Mufutau Wade", "section": "petitions", "workItemId": "e4d306f3-3d36-4e27-ac22-0f6e8b31b940", "isInitializeCase": true, diff --git a/web-api/storage/fixtures/seed/104-20.json b/web-api/storage/fixtures/seed/104-20.json index 281b9201208..7b7cadeb7c6 100644 --- a/web-api/storage/fixtures/seed/104-20.json +++ b/web-api/storage/fixtures/seed/104-20.json @@ -27,11 +27,12 @@ ], "attachments": false, "documentType": "ODD - Order of Dismissal and Decision Entered,", - "filingDate": "2020-04-14T20:01:15.215Z", + "entityName": "Document", + "filingDate": "2020-04-14T03:01:15.215Z", "pending": false, - "receivedAt": "2020-04-14T20:01:15.215Z", + "receivedAt": "2020-04-14T03:01:15.215Z", "signedJudgeName": "Maurice B. Foley", - "createdAt": "2020-04-14T20:01:19.901Z", + "createdAt": "2020-04-14T03:01:15.215Z", "scenario": "Type B", "caseId": "1a92894e-83a5-48ba-9994-3ada44235deb", "documentTitle": "Order of Dismissal and Decision Entered, Judge Buch", @@ -47,26 +48,26 @@ "eventCode": "ODD", "documentType": "Order of Dismissal and Decision", "caseId": "1a92894e-83a5-48ba-9994-3ada44235deb", - "documentContents": "Déjà vu, this is a seed order\n", + "documentContents": "Déjà vu, this is a seed order in case 104-20 filed on Apr 13 at 11:01pm ET\n", "documentTitle": "Order of Dismissal and Decision", - "richText": "

Déjà vu, this is a seed order

", + "richText": "

Déjà vu, this is a seed order in case 104-20 filed on Apr 13 at 11:01pm ET

", "docketNumber": "104-20" }, "attachments": false, "documentType": "ODD - Order of Dismissal and Decision Entered,", - "filingDate": "2020-04-14T20:01:15.215Z", + "filingDate": "2020-04-14T03:01:15.215Z", "pending": false, - "documentContents": "Déjà vu, this is a seed order\n", + "documentContents": "Déjà vu, this is a seed order in case 104-20 filed on Apr 13 at 11:01pm ET\n", "isFileAttached": true, - "receivedAt": "2020-04-14T20:01:15.215Z", + "receivedAt": "2020-04-14T03:01:15.215Z", "userId": "2805d1ab-18d0-43ec-bafb-654e83405416", "eventCode": "ODD", "processingStatus": "complete", "signedJudgeName": "Maurice B. Foley", - "createdAt": "2020-04-14T20:01:19.901Z", + "createdAt": "2020-04-14T03:01:15.215Z", "scenario": "Type B", "caseId": "1a92894e-83a5-48ba-9994-3ada44235deb", - "signedAt": "2020-04-14T20:01:19.901Z", + "signedAt": "2020-04-14T03:01:15.215Z", "documentId": "1f1aa3f7-e2e3-43e6-885d-4ce341588c76", "signedByUserId": "2805d1ab-18d0-43ec-bafb-654e83405416", "documentTitle": "Order of Dismissal and Decision Entered, Judge Buch", @@ -79,14 +80,14 @@ "isQC": true, "sentBy": "Test Docketclerk1", "sentBySection": "docket", - "createdAt": "2020-04-14T20:01:49.855Z", - "caseCaptionNames": "Hanan Al Hroub", + "createdAt": "2020-04-14T03:01:49.855Z", + "caseTitle": "Hanan Al Hroub", "assigneeName": "Test Docketclerk1", "caseId": "1a92894e-83a5-48ba-9994-3ada44235deb", "hideFromPendingMessages": true, "messages": [ { - "createdAt": "2020-04-14T20:01:49.856Z", + "createdAt": "2020-04-14T03:01:49.856Z", "messageId": "fdccb125-7f41-434e-9f78-e3efa2280551", "from": "Test Docketclerk1", "message": "ODD - Order of Dismissal and Decision Entered, filed by Docketclerk is ready for review.", @@ -95,18 +96,18 @@ ], "docketNumber": "104-20", "sentByUserId": "2805d1ab-18d0-43ec-bafb-654e83405416", - "updatedAt": "2020-04-14T20:01:49.855Z" + "updatedAt": "2020-04-14T03:01:49.855Z" } ], - "documentContents": "Déjà vu, this is a seed order\n", + "documentContents": "Déjà vu, this is a seed order in case 104-20 filed on Apr 13 at 11:01pm ET\n", "isFileAttached": true, "userId": "2805d1ab-18d0-43ec-bafb-654e83405416", "eventCode": "ODD", "processingStatus": "complete", - "signedAt": "2020-04-14T20:01:19.901Z", + "signedAt": "2020-04-14T03:01:15.215Z", "documentId": "1f1aa3f7-e2e3-43e6-885d-4ce341588c76", "signedByUserId": "2805d1ab-18d0-43ec-bafb-654e83405416", - "servedAt": "2020-04-14T20:01:50.399Z", + "servedAt": "2020-04-14T03:01:50.399Z", "docketNumber": "104-20", "status": "served" }, @@ -114,13 +115,13 @@ "workItemId": "c99d49ff-f651-4f8f-b3b3-e57b8d400868", "isQC": true, "sentBy": "Test Docketclerk1", - "createdAt": "2020-04-14T20:01:49.855Z", - "caseCaptionNames": "Hanan Al Hroub", + "createdAt": "2020-04-14T03:01:49.855Z", + "caseTitle": "Hanan Al Hroub", "assigneeName": "Test Docketclerk1", "caseId": "1a92894e-83a5-48ba-9994-3ada44235deb", - "sk": "2020-04-14T20:01:49.855Z", - "updatedAt": "2020-04-14T20:01:49.855Z", - "completedAt": "2020-04-14T20:01:50.612Z", + "sk": "2020-04-14T03:01:49.855Z", + "updatedAt": "2020-04-14T03:01:49.855Z", + "completedAt": "2020-04-14T03:01:50.612Z", "docketNumberSuffix": "R", "completedMessage": "completed", "assigneeId": "2805d1ab-18d0-43ec-bafb-654e83405416", @@ -129,7 +130,7 @@ "hideFromPendingMessages": true, "messages": [ { - "createdAt": "2020-04-14T20:01:49.856Z", + "createdAt": "2020-04-14T03:01:49.856Z", "messageId": "fdccb125-7f41-434e-9f78-e3efa2280551", "from": "Test Docketclerk1", "message": "ODD - Order of Dismissal and Decision Entered, filed by Docketclerk is ready for review.", @@ -187,7 +188,7 @@ "preferredTrialCity": "San Francisco, California", "initialCaption": "Hanan Al Hroub, Petitioner", "hasPendingItems": false, - "closedDate": "2020-04-14T20:01:50.746Z", + "closedDate": "2020-04-14T03:01:50.746Z", "orderForAmendedPetitionAndFilingFee": false, "pk": "case|1a92894e-83a5-48ba-9994-3ada44235deb", "docketNumber": "104-20", @@ -196,7 +197,7 @@ { "eventCode": "ODD", "docketRecordId": "874084d8-eb34-4e7a-9c8a-60d3f531a809", - "filingDate": "2020-04-14T20:01:50.746Z", + "filingDate": "2020-04-14T03:01:50.746Z", "sk": "docket-record|874084d8-eb34-4e7a-9c8a-60d3f531a809", "description": "Order of Dismissal and Decision Entered, Judge Buch", "index": 3, @@ -241,11 +242,12 @@ ], "attachments": false, "documentType": "ODD - Order of Dismissal and Decision Entered,", - "filingDate": "2020-04-14T20:01:15.215Z", + "entityName": "Document", + "filingDate": "2020-04-14T03:01:15.215Z", "pending": false, - "receivedAt": "2020-04-14T20:01:15.215Z", + "receivedAt": "2020-04-14T03:01:15.215Z", "signedJudgeName": "Maurice B. Foley", - "createdAt": "2020-04-14T20:01:19.901Z", + "createdAt": "2020-04-14T03:01:15.215Z", "scenario": "Type B", "caseId": "1a92894e-83a5-48ba-9994-3ada44235deb", "sk": "document|1f1aa3f7-e2e3-43e6-885d-4ce341588c76", @@ -254,7 +256,7 @@ "workItems": [ { "associatedJudge": "Chief Judge", - "completedAt": "2020-04-14T20:01:50.612Z", + "completedAt": "2020-04-14T03:01:50.612Z", "docketNumberSuffix": null, "caseStatus": "General Docket - Not at Issue", "completedMessage": "completed", @@ -273,11 +275,11 @@ ], "attachments": false, "documentType": "ODD - Order of Dismissal and Decision Entered,", - "filingDate": "2020-04-14T20:01:15.215Z", + "filingDate": "2020-04-14T03:01:15.215Z", "pending": false, - "receivedAt": "2020-04-14T20:01:15.215Z", + "receivedAt": "2020-04-14T03:01:15.215Z", "signedJudgeName": "Maurice B. Foley", - "createdAt": "2020-04-14T20:01:19.901Z", + "createdAt": "2020-04-14T03:01:15.215Z", "scenario": "Type B", "caseId": "1a92894e-83a5-48ba-9994-3ada44235deb", "documentTitle": "Order of Dismissal and Decision Entered, Judge Buch", @@ -293,26 +295,26 @@ "eventCode": "ODD", "documentType": "Order of Dismissal and Decision", "caseId": "1a92894e-83a5-48ba-9994-3ada44235deb", - "documentContents": "Déjà vu, this is a seed order\n", + "documentContents": "Déjà vu, this is a seed order in case 104-20 filed on Apr 13 at 11:01pm ET\n", "documentTitle": "Order of Dismissal and Decision", - "richText": "

Déjà vu, this is a seed order

", + "richText": "

Déjà vu, this is a seed order in case 104-20 filed on Apr 13 at 11:01pm ET

", "docketNumber": "104-20" }, "attachments": false, "documentType": "ODD - Order of Dismissal and Decision Entered,", - "filingDate": "2020-04-14T20:01:15.215Z", + "filingDate": "2020-04-14T03:01:15.215Z", "pending": false, - "documentContents": "Déjà vu, this is a seed order\n", + "documentContents": "Déjà vu, this is a seed order in case 104-20 filed on Apr 13 at 11:01pm ET\n", "isFileAttached": true, - "receivedAt": "2020-04-14T20:01:15.215Z", + "receivedAt": "2020-04-14T03:01:15.215Z", "userId": "2805d1ab-18d0-43ec-bafb-654e83405416", "eventCode": "ODD", "processingStatus": "complete", "signedJudgeName": "Maurice B. Foley", - "createdAt": "2020-04-14T20:01:19.901Z", + "createdAt": "2020-04-14T03:01:15.215Z", "scenario": "Type B", "caseId": "1a92894e-83a5-48ba-9994-3ada44235deb", - "signedAt": "2020-04-14T20:01:19.901Z", + "signedAt": "2020-04-14T03:01:15.215Z", "documentId": "1f1aa3f7-e2e3-43e6-885d-4ce341588c76", "signedByUserId": "2805d1ab-18d0-43ec-bafb-654e83405416", "documentTitle": "Order of Dismissal and Decision Entered, Judge Buch", @@ -325,14 +327,14 @@ "isQC": true, "sentBy": "Test Docketclerk1", "sentBySection": "docket", - "createdAt": "2020-04-14T20:01:49.855Z", - "caseCaptionNames": "Hanan Al Hroub", + "createdAt": "2020-04-14T03:01:49.855Z", + "caseTitle": "Hanan Al Hroub", "assigneeName": "Test Docketclerk1", "caseId": "1a92894e-83a5-48ba-9994-3ada44235deb", "hideFromPendingMessages": true, "messages": [ { - "createdAt": "2020-04-14T20:01:49.856Z", + "createdAt": "2020-04-14T03:01:49.856Z", "messageId": "fdccb125-7f41-434e-9f78-e3efa2280551", "from": "Test Docketclerk1", "message": "ODD - Order of Dismissal and Decision Entered, filed by Docketclerk is ready for review.", @@ -341,18 +343,18 @@ ], "docketNumber": "104-20", "sentByUserId": "2805d1ab-18d0-43ec-bafb-654e83405416", - "updatedAt": "2020-04-14T20:01:49.855Z" + "updatedAt": "2020-04-14T03:01:49.855Z" } ], - "documentContents": "Déjà vu, this is a seed order\n", + "documentContents": "Déjà vu, this is a seed order in case 104-20 filed on Apr 13 at 11:01pm ET\n", "isFileAttached": true, "userId": "2805d1ab-18d0-43ec-bafb-654e83405416", "eventCode": "ODD", "processingStatus": "complete", - "signedAt": "2020-04-14T20:01:19.901Z", + "signedAt": "2020-04-14T03:01:15.215Z", "documentId": "1f1aa3f7-e2e3-43e6-885d-4ce341588c76", "signedByUserId": "2805d1ab-18d0-43ec-bafb-654e83405416", - "servedAt": "2020-04-14T20:01:50.399Z", + "servedAt": "2020-04-14T03:01:50.399Z", "docketNumber": "104-20", "status": "served" }, @@ -363,14 +365,14 @@ "completedByUserId": "2805d1ab-18d0-43ec-bafb-654e83405416", "sentBy": "Test Docketclerk1", "sentBySection": "docket", - "createdAt": "2020-04-14T20:01:49.855Z", - "caseCaptionNames": "Hanan Al Hroub", + "createdAt": "2020-04-14T03:01:49.855Z", + "caseTitle": "Hanan Al Hroub", "assigneeName": "Test Docketclerk1", "caseId": "1a92894e-83a5-48ba-9994-3ada44235deb", "hideFromPendingMessages": true, "messages": [ { - "createdAt": "2020-04-14T20:01:49.856Z", + "createdAt": "2020-04-14T03:01:49.856Z", "messageId": "fdccb125-7f41-434e-9f78-e3efa2280551", "from": "Test Docketclerk1", "message": "ODD - Order of Dismissal and Decision Entered, filed by Docketclerk is ready for review.", @@ -380,19 +382,19 @@ "docketNumber": "104-20", "sentByUserId": "2805d1ab-18d0-43ec-bafb-654e83405416", "completedBy": "Test Docketclerk1", - "updatedAt": "2020-04-14T20:01:49.855Z" + "updatedAt": "2020-04-14T03:01:49.855Z" } ], - "documentContents": "Déjà vu, this is a seed order\n", + "documentContents": "Déjà vu, this is a seed order in case 104-20 filed on Apr 13 at 11:01pm ET\n", "isFileAttached": true, "userId": "2805d1ab-18d0-43ec-bafb-654e83405416", "eventCode": "ODD", "processingStatus": "complete", - "signedAt": "2020-04-14T20:01:19.901Z", + "signedAt": "2020-04-14T03:01:15.215Z", "documentId": "1f1aa3f7-e2e3-43e6-885d-4ce341588c76", "pk": "case|1a92894e-83a5-48ba-9994-3ada44235deb", "signedByUserId": "2805d1ab-18d0-43ec-bafb-654e83405416", - "servedAt": "2020-04-14T20:01:50.399Z", + "servedAt": "2020-04-14T03:01:50.399Z", "docketNumber": "104-20", "status": "served" }, @@ -411,6 +413,7 @@ ], "isPaper": true, "documentType": "Statement of Taxpayer Identification", + "entityName": "Document", "filingDate": "2020-04-12T04:00:00.000Z", "workItems": [], "partyPrimary": true, @@ -478,7 +481,7 @@ "sentBy": "Test Petitionsclerk1", "sentBySection": "petitions", "createdAt": "2020-04-14T19:59:46.118Z", - "caseCaptionNames": "Hanan Al Hroub", + "caseTitle": "Hanan Al Hroub", "assigneeName": "Test Petitionsclerk1", "caseId": "1a92894e-83a5-48ba-9994-3ada44235deb", "messages": [ @@ -530,6 +533,7 @@ ], "isPaper": true, "documentType": "Request for Place of Trial", + "entityName": "Document", "filingDate": "2020-04-12T04:00:00.000Z", "workItems": [], "partyPrimary": true, @@ -578,7 +582,7 @@ "isQC": true, "sentBy": "Test Petitionsclerk1", "createdAt": "2020-04-14T19:59:46.118Z", - "caseCaptionNames": "Hanan Al Hroub", + "caseTitle": "Hanan Al Hroub", "assigneeName": "Test Petitionsclerk1", "caseId": "1a92894e-83a5-48ba-9994-3ada44235deb", "sk": "work-item|2020d554-30c7-450a-ac01-738c1996c783", @@ -631,7 +635,7 @@ "isQC": true, "sentBy": "Test Petitionsclerk1", "createdAt": "2020-04-14T19:59:46.118Z", - "caseCaptionNames": "Hanan Al Hroub", + "caseTitle": "Hanan Al Hroub", "assigneeName": "Test Petitionsclerk1", "caseId": "1a92894e-83a5-48ba-9994-3ada44235deb", "sk": "2020-04-14T19:59:46.118Z", diff --git a/web-api/storage/fixtures/seed/105-19.json b/web-api/storage/fixtures/seed/105-19.json index 46445b0c22f..212478c1968 100755 --- a/web-api/storage/fixtures/seed/105-19.json +++ b/web-api/storage/fixtures/seed/105-19.json @@ -180,6 +180,7 @@ }, { "documentType": "Petition", + "entityName": "Document", "filingDate": "2019-03-27T21:53:00.297Z", "workItems": [ { @@ -230,6 +231,7 @@ }, { "documentType": "Statement of Taxpayer Identification", + "entityName": "Document", "filingDate": "2019-03-27T21:53:00.298Z", "workItems": [], "pending": false, diff --git a/web-api/storage/fixtures/seed/105-20.json b/web-api/storage/fixtures/seed/105-20.json new file mode 100644 index 00000000000..c13af8740e6 --- /dev/null +++ b/web-api/storage/fixtures/seed/105-20.json @@ -0,0 +1,777 @@ +[ + { + "associatedJudge": "Chief Judge", + "isSealed": true, + "procedureType": "Regular", + "sealedDate": "2020-04-29T15:53:09.650Z", + "isPaper": false, + "contactSecondary": {}, + "automaticBlocked": false, + "qcCompleteForTrial": {}, + "irsNoticeDate": null, + "petitionPaymentStatus": "Not Paid", + "orderForFilingFee": false, + "partyType": "Petitioner", + "receivedAt": "2020-04-29T15:51:28.572Z", + "irsSendDate": "2020-04-29T15:51:29.250Z", + "caseType": "CDP (Lien/Levy)", + "orderDesignatingPlaceOfTrial": false, + "createdAt": "2020-04-29T15:50:41.686Z", + "contactPrimary": { + "serviceIndicator": "None", + "city": "New York", + "phone": "+1 (836) 359-2128", + "address1": "20 West Nobel Court", + "postalCode": "24778", + "name": "Astra Santiago", + "state": "NY", + "countryType": "domestic", + "email": "petitioner" + }, + "noticeOfAttachments": false, + "entityName": "Case", + "caseCaption": "Astra Santiago, Petitioner", + "caseId": "28caad58-df69-4a4d-af15-6554aee7fbd6", + "sk": "case|28caad58-df69-4a4d-af15-6554aee7fbd6", + "filingType": "Myself", + "orderForOds": false, + "orderForRatification": false, + "hasIrsNotice": false, + "initialDocketNumberSuffix": "L", + "docketNumberSuffix": "L", + "orderToChangeDesignatedPlaceOfTrial": false, + "sortableDocketNumber": 20000106, + "noticeOfTrialDate": "2020-04-29T15:50:41.687Z", + "userId": "7805d1ab-18d0-43ec-bafb-654e83405416", + "orderForAmendedPetition": false, + "orderToShowCause": false, + "preferredTrialCity": "New York City, New York", + "initialCaption": "Astra Santiago, Petitioner", + "hasPendingItems": false, + "petitionPaymentDate": null, + "orderForAmendedPetitionAndFilingFee": false, + "pk": "case|28caad58-df69-4a4d-af15-6554aee7fbd6", + "docketNumber": "105-20", + "petitionPaymentWaivedDate": null, + "status": "General Docket - Not at Issue" + }, + { + "eventCode": "P", + "docketRecordId": "96f78072-858a-4eb5-bde9-ec68ff16dd2d", + "filingDate": "2020-04-29T15:50:41.698Z", + "entityName": "DocketRecord", + "filedBy": "Petr. Astra Santiago", + "sk": "docket-record|96f78072-858a-4eb5-bde9-ec68ff16dd2d", + "description": "Petition", + "index": 1, + "documentId": "af9e2d43-1255-4e3d-80d0-63f0aedfab5a", + "pk": "case|28caad58-df69-4a4d-af15-6554aee7fbd6" + }, + { + "eventCode": "RQT", + "docketRecordId": "b9471b59-fbe3-436f-a695-2583f013b975", + "filingDate": "2020-04-29T15:50:41.686Z", + "entityName": "DocketRecord", + "sk": "docket-record|b9471b59-fbe3-436f-a695-2583f013b975", + "description": "Request for Place of Trial at New York City, New York", + "index": 2, + "pk": "case|28caad58-df69-4a4d-af15-6554aee7fbd6" + }, + { + "eventCode": "O", + "docketRecordId": "cb57802b-4571-43ad-8f35-b54ac7fb7399", + "filingDate": "2020-04-29T15:52:16.963Z", + "entityName": "DocketRecord", + "sk": "docket-record|cb57802b-4571-43ad-8f35-b54ac7fb7399", + "description": "Order that this case is sealed", + "index": 3, + "documentId": "06f60736-5f37-4590-b62a-5c7edf84ffc6", + "editState": "{\"eventCode\":\"O\",\"documentType\":\"O - Order\",\"documentTitle\":\"[Anything]\",\"scenario\":\"Type A\",\"attachments\":false,\"freeText\":\"Order that this case is sealed\",\"serviceStamp\":\"Served\",\"generatedDocumentTitle\":\"Order that this case is sealed\",\"caseId\":\"28caad58-df69-4a4d-af15-6554aee7fbd6\",\"documentId\":\"06f60736-5f37-4590-b62a-5c7edf84ffc6\"}", + "pk": "case|28caad58-df69-4a4d-af15-6554aee7fbd6" + }, + { + "draftState": null, + "servedParties": [ + { + "name": "Astra Santiago", + "email": "petitioner" + } + ], + "serviceStamp": "Served", + "attachments": false, + "documentType": "O - Order", + "filingDate": "2020-04-29T15:52:01.457Z", + "pending": false, + "receivedAt": "2020-04-29T15:52:01.457Z", + "signedJudgeName": "Maurice B. Foley", + "createdAt": "2020-04-29T15:52:05.725Z", + "scenario": "Type A", + "entityName": "Document", + "caseId": "28caad58-df69-4a4d-af15-6554aee7fbd6", + "sk": "document|06f60736-5f37-4590-b62a-5c7edf84ffc6", + "documentTitle": "Order that this case is sealed", + "relationship": "primaryDocument", + "workItems": [ + { + "associatedJudge": "Chief Judge", + "completedAt": "2020-04-29T15:52:16.578Z", + "docketNumberSuffix": "L", + "caseStatus": "General Docket - Not at Issue", + "completedMessage": "completed", + "document": { + "draftState": null, + "servedParties": [ + { + "name": "Astra Santiago", + "email": "petitioner" + } + ], + "serviceStamp": "Served", + "attachments": false, + "documentType": "O - Order", + "filingDate": "2020-04-29T15:52:01.457Z", + "pending": false, + "receivedAt": "2020-04-29T15:52:01.457Z", + "signedJudgeName": "Maurice B. Foley", + "createdAt": "2020-04-29T15:52:05.725Z", + "scenario": "Type A", + "entityName": "Document", + "caseId": "28caad58-df69-4a4d-af15-6554aee7fbd6", + "documentTitle": "Order that this case is sealed", + "relationship": "primaryDocument", + "documentContents": "We are sealing this case right meow.\n", + "isFileAttached": true, + "userId": "3805d1ab-18d0-43ec-bafb-654e83405416", + "eventCode": "O", + "processingStatus": "complete", + "freeText": "Order that this case is sealed", + "signedAt": "2020-04-29T15:52:05.726Z", + "documentId": "06f60736-5f37-4590-b62a-5c7edf84ffc6", + "signedByUserId": "3805d1ab-18d0-43ec-bafb-654e83405416", + "servedAt": "2020-04-29T15:52:16.484Z", + "docketNumber": "105-20", + "status": "served" + }, + "caseTitle": "Astra Santiago", + "section": "petitions", + "workItemId": "1bb6306f-0019-4fc5-9286-9f2aa54fadf7", + "assigneeId": "3805d1ab-18d0-43ec-bafb-654e83405416", + "isQC": true, + "completedByUserId": "3805d1ab-18d0-43ec-bafb-654e83405416", + "sentBy": "Test Petitionsclerk", + "sentBySection": "petitions", + "createdAt": "2020-04-29T15:52:15.627Z", + "assigneeName": "Test Petitionsclerk", + "entityName": "WorkItem", + "caseId": "28caad58-df69-4a4d-af15-6554aee7fbd6", + "hideFromPendingMessages": true, + "messages": [ + { + "createdAt": "2020-04-29T15:52:15.628Z", + "messageId": "fd717166-8cf6-4925-96e8-0f3c807dabca", + "from": "Test Petitionsclerk", + "message": "O - Order filed by Petitionsclerk is ready for review.", + "entityName": "Message", + "fromUserId": "3805d1ab-18d0-43ec-bafb-654e83405416" + } + ], + "docketNumber": "105-20", + "sentByUserId": "3805d1ab-18d0-43ec-bafb-654e83405416", + "completedBy": "Test Petitionsclerk", + "updatedAt": "2020-04-29T15:52:15.628Z" + } + ], + "documentContents": "We are sealing this case right meow.\n", + "isFileAttached": true, + "userId": "3805d1ab-18d0-43ec-bafb-654e83405416", + "eventCode": "O", + "processingStatus": "complete", + "freeText": "Order that this case is sealed", + "signedAt": "2020-04-29T15:52:05.726Z", + "documentId": "06f60736-5f37-4590-b62a-5c7edf84ffc6", + "pk": "case|28caad58-df69-4a4d-af15-6554aee7fbd6", + "signedByUserId": "3805d1ab-18d0-43ec-bafb-654e83405416", + "servedAt": "2020-04-29T15:52:16.484Z", + "docketNumber": "105-20", + "status": "served" + }, + { + "draftState": null, + "servedParties": [ + { + "name": "Astra Santiago", + "email": "petitioner" + } + ], + "documentType": "Statement of Taxpayer Identification", + "filingDate": "2020-04-29T15:50:41.686Z", + "workItems": [], + "partyPrimary": true, + "pending": false, + "receivedAt": "2020-04-29T15:50:41.699Z", + "userId": "7805d1ab-18d0-43ec-bafb-654e83405416", + "eventCode": "STIN", + "processingStatus": "complete", + "createdAt": "2020-04-29T15:50:41.699Z", + "entityName": "Document", + "filedBy": "Petr. Astra Santiago", + "caseId": "28caad58-df69-4a4d-af15-6554aee7fbd6", + "sk": "document|abba69d5-a96a-423c-937f-b4d1c5442bf4", + "partySecondary": false, + "documentId": "abba69d5-a96a-423c-937f-b4d1c5442bf4", + "pk": "case|28caad58-df69-4a4d-af15-6554aee7fbd6", + "servedAt": "2020-04-29T15:51:29.168Z", + "privatePractitioners": [], + "status": "served" + }, + { + "draftState": null, + "servedParties": [ + { + "name": "Astra Santiago", + "email": "petitioner" + } + ], + "documentType": "Petition", + "filingDate": "2020-04-29T15:50:41.686Z", + "workItems": [ + { + "associatedJudge": "Chief Judge", + "completedAt": "2020-04-29T15:51:29.331Z", + "docketNumberSuffix": "L", + "caseStatus": "New", + "completedMessage": "Served to IRS", + "document": { + "documentType": "Petition", + "filingDate": "2020-04-29T15:50:41.686Z", + "partyPrimary": true, + "pending": false, + "receivedAt": "2020-04-29T15:50:41.698Z", + "userId": "7805d1ab-18d0-43ec-bafb-654e83405416", + "eventCode": "P", + "processingStatus": "pending", + "createdAt": "2020-04-29T15:50:41.698Z", + "entityName": "Document", + "filedBy": "Petr. Astra Santiago", + "partySecondary": false, + "documentId": "af9e2d43-1255-4e3d-80d0-63f0aedfab5a", + "privatePractitioners": [] + }, + "caseTitle": "Astra Santiago", + "section": "petitions", + "workItemId": "332026fb-8844-49b6-bb13-66eff6882f00", + "isInitializeCase": true, + "assigneeId": null, + "isQC": true, + "completedByUserId": "3805d1ab-18d0-43ec-bafb-654e83405416", + "sentBy": "7805d1ab-18d0-43ec-bafb-654e83405416", + "createdAt": "2020-04-29T15:50:41.698Z", + "assigneeName": null, + "entityName": "WorkItem", + "caseId": "28caad58-df69-4a4d-af15-6554aee7fbd6", + "messages": [ + { + "createdAt": "2020-04-29T15:50:41.699Z", + "messageId": "48b750d1-7243-4420-8e03-2a592c07d5bc", + "from": "Test Petitioner", + "message": "Petition filed by Astra Santiago is ready for review.", + "entityName": "Message", + "fromUserId": "7805d1ab-18d0-43ec-bafb-654e83405416" + } + ], + "docketNumber": "105-20", + "completedBy": "Test Petitionsclerk", + "updatedAt": "2020-04-29T15:50:41.699Z" + } + ], + "partyPrimary": true, + "pending": false, + "receivedAt": "2020-04-29T15:50:41.698Z", + "userId": "7805d1ab-18d0-43ec-bafb-654e83405416", + "eventCode": "P", + "processingStatus": "complete", + "createdAt": "2020-04-29T15:50:41.698Z", + "entityName": "Document", + "filedBy": "Petr. Astra Santiago", + "caseId": "28caad58-df69-4a4d-af15-6554aee7fbd6", + "sk": "document|af9e2d43-1255-4e3d-80d0-63f0aedfab5a", + "partySecondary": false, + "documentId": "af9e2d43-1255-4e3d-80d0-63f0aedfab5a", + "pk": "case|28caad58-df69-4a4d-af15-6554aee7fbd6", + "servedAt": "2020-04-29T15:51:29.168Z", + "privatePractitioners": [], + "status": "served" + }, + { + "role": "privatePractitioner", + "serviceIndicator": "Electronic", + "barNumber": "PT1234", + "entityName": "PrivatePractitioner", + "contact": { + "address3": "Under the stairs", + "address2": "Apartment 4", + "city": "Chicago", + "phone": "+1 (555) 555-5555", + "address1": "234 Main St", + "postalCode": "61234", + "state": "IL", + "countryType": "domestic" + }, + "sk": "privatePractitioner|9805d1ab-18d0-43ec-bafb-654e83405416", + "name": "Test Private Practitioner", + "section": "privatePractitioner", + "pk": "case|28caad58-df69-4a4d-af15-6554aee7fbd6", + "representingPrimary": true, + "userId": "9805d1ab-18d0-43ec-bafb-654e83405416", + "email": "privatePractitioner" + }, + { + "sk": "work-item|332026fb-8844-49b6-bb13-66eff6882f00", + "pk": "case|28caad58-df69-4a4d-af15-6554aee7fbd6" + }, + { + "sk": "case|28caad58-df69-4a4d-af15-6554aee7fbd6", + "caseId": "28caad58-df69-4a4d-af15-6554aee7fbd6", + "pk": "catalog" + }, + { + "associatedJudge": "Chief Judge", + "caseStatus": "General Docket - Not at Issue", + "document": { + "documentType": "Petition", + "filingDate": "2020-04-29T15:50:41.686Z", + "partyPrimary": true, + "pending": false, + "receivedAt": "2020-04-29T15:50:41.698Z", + "userId": "7805d1ab-18d0-43ec-bafb-654e83405416", + "eventCode": "P", + "processingStatus": "pending", + "createdAt": "2020-04-29T15:50:41.698Z", + "entityName": "Document", + "filedBy": "Petr. Astra Santiago", + "partySecondary": false, + "documentId": "af9e2d43-1255-4e3d-80d0-63f0aedfab5a", + "privatePractitioners": [] + }, + "gsi1pk": "work-item|332026fb-8844-49b6-bb13-66eff6882f00", + "section": "petitions", + "workItemId": "332026fb-8844-49b6-bb13-66eff6882f00", + "isQC": true, + "sentBy": "7805d1ab-18d0-43ec-bafb-654e83405416", + "createdAt": "2020-04-29T15:50:41.698Z", + "assigneeName": null, + "entityName": "WorkItem", + "caseId": "28caad58-df69-4a4d-af15-6554aee7fbd6", + "sk": "2020-04-29T15:50:41.698Z", + "updatedAt": "2020-04-29T15:50:41.699Z", + "completedAt": "2020-04-29T15:51:29.331Z", + "docketNumberSuffix": "L", + "completedMessage": "Served to IRS", + "caseTitle": "Astra Santiago", + "isInitializeCase": true, + "assigneeId": null, + "completedByUserId": "3805d1ab-18d0-43ec-bafb-654e83405416", + "messages": [ + { + "createdAt": "2020-04-29T15:50:41.699Z", + "messageId": "48b750d1-7243-4420-8e03-2a592c07d5bc", + "from": "Test Petitioner", + "message": "Petition filed by Astra Santiago is ready for review.", + "entityName": "Message", + "fromUserId": "7805d1ab-18d0-43ec-bafb-654e83405416" + } + ], + "pk": "user-outbox|3805d1ab-18d0-43ec-bafb-654e83405416", + "docketNumber": "105-20", + "completedBy": "Test Petitionsclerk" + }, + { + "associatedJudge": "Chief Judge", + "caseStatus": "General Docket - Not at Issue", + "gsi1pk": "work-item|1bb6306f-0019-4fc5-9286-9f2aa54fadf7", + "document": { + "draftState": null, + "servedParties": [ + { + "name": "Astra Santiago", + "email": "petitioner" + } + ], + "serviceStamp": "Served", + "attachments": false, + "documentType": "O - Order", + "filingDate": "2020-04-29T15:52:01.457Z", + "pending": false, + "receivedAt": "2020-04-29T15:52:01.457Z", + "signedJudgeName": "Maurice B. Foley", + "createdAt": "2020-04-29T15:52:05.725Z", + "scenario": "Type A", + "entityName": "Document", + "caseId": "28caad58-df69-4a4d-af15-6554aee7fbd6", + "documentTitle": "Order that this case is sealed", + "relationship": "primaryDocument", + "workItems": [ + { + "associatedJudge": "Chief Judge", + "docketNumberSuffix": "L", + "inProgress": true, + "caseStatus": "General Docket - Not at Issue", + "document": { + "draftState": { + "eventCode": "O", + "documentType": "Order", + "caseId": "28caad58-df69-4a4d-af15-6554aee7fbd6", + "documentContents": "We are sealing this case right meow.\n", + "documentTitle": "Order that this case is sealed", + "richText": "

We are sealing this case right meow.

", + "docketNumber": "105-20" + }, + "serviceStamp": "Served", + "attachments": false, + "documentType": "O - Order", + "filingDate": "2020-04-29T15:52:01.457Z", + "pending": false, + "documentContents": "We are sealing this case right meow.\n", + "isFileAttached": true, + "receivedAt": "2020-04-29T15:52:01.457Z", + "userId": "3805d1ab-18d0-43ec-bafb-654e83405416", + "eventCode": "O", + "processingStatus": "complete", + "signedJudgeName": "Maurice B. Foley", + "createdAt": "2020-04-29T15:52:05.725Z", + "scenario": "Type A", + "entityName": "Document", + "caseId": "28caad58-df69-4a4d-af15-6554aee7fbd6", + "freeText": "Order that this case is sealed", + "signedAt": "2020-04-29T15:52:05.726Z", + "documentId": "06f60736-5f37-4590-b62a-5c7edf84ffc6", + "signedByUserId": "3805d1ab-18d0-43ec-bafb-654e83405416", + "documentTitle": "Order that this case is sealed", + "relationship": "primaryDocument", + "docketNumber": "105-20" + }, + "caseTitle": "Astra Santiago", + "section": "petitions", + "workItemId": "1bb6306f-0019-4fc5-9286-9f2aa54fadf7", + "assigneeId": "3805d1ab-18d0-43ec-bafb-654e83405416", + "isQC": true, + "sentBy": "Test Petitionsclerk", + "sentBySection": "petitions", + "createdAt": "2020-04-29T15:52:15.627Z", + "assigneeName": "Test Petitionsclerk", + "entityName": "WorkItem", + "caseId": "28caad58-df69-4a4d-af15-6554aee7fbd6", + "hideFromPendingMessages": true, + "messages": [ + { + "createdAt": "2020-04-29T15:52:15.628Z", + "messageId": "fd717166-8cf6-4925-96e8-0f3c807dabca", + "from": "Test Petitionsclerk", + "message": "O - Order filed by Petitionsclerk is ready for review.", + "entityName": "Message", + "fromUserId": "3805d1ab-18d0-43ec-bafb-654e83405416" + } + ], + "docketNumber": "105-20", + "sentByUserId": "3805d1ab-18d0-43ec-bafb-654e83405416", + "updatedAt": "2020-04-29T15:52:15.628Z" + } + ], + "documentContents": "We are sealing this case right meow.\n", + "isFileAttached": true, + "userId": "3805d1ab-18d0-43ec-bafb-654e83405416", + "eventCode": "O", + "processingStatus": "complete", + "freeText": "Order that this case is sealed", + "signedAt": "2020-04-29T15:52:05.726Z", + "documentId": "06f60736-5f37-4590-b62a-5c7edf84ffc6", + "signedByUserId": "3805d1ab-18d0-43ec-bafb-654e83405416", + "servedAt": "2020-04-29T15:52:16.484Z", + "docketNumber": "105-20", + "status": "served" + }, + "section": "petitions", + "workItemId": "1bb6306f-0019-4fc5-9286-9f2aa54fadf7", + "isQC": true, + "sentBy": "Test Petitionsclerk", + "createdAt": "2020-04-29T15:52:15.627Z", + "assigneeName": "Test Petitionsclerk", + "entityName": "WorkItem", + "caseId": "28caad58-df69-4a4d-af15-6554aee7fbd6", + "sk": "2020-04-29T15:52:15.627Z", + "updatedAt": "2020-04-29T15:52:15.628Z", + "completedAt": "2020-04-29T15:52:16.578Z", + "docketNumberSuffix": "L", + "completedMessage": "completed", + "caseTitle": "Astra Santiago", + "assigneeId": "3805d1ab-18d0-43ec-bafb-654e83405416", + "completedByUserId": "3805d1ab-18d0-43ec-bafb-654e83405416", + "sentBySection": "petitions", + "hideFromPendingMessages": true, + "messages": [ + { + "createdAt": "2020-04-29T15:52:15.628Z", + "messageId": "fd717166-8cf6-4925-96e8-0f3c807dabca", + "from": "Test Petitionsclerk", + "message": "O - Order filed by Petitionsclerk is ready for review.", + "entityName": "Message", + "fromUserId": "3805d1ab-18d0-43ec-bafb-654e83405416" + } + ], + "pk": "user-outbox|3805d1ab-18d0-43ec-bafb-654e83405416", + "docketNumber": "105-20", + "sentByUserId": "3805d1ab-18d0-43ec-bafb-654e83405416", + "completedBy": "Test Petitionsclerk" + }, + { + "associatedJudge": "Chief Judge", + "completedAt": "2020-04-29T15:51:29.331Z", + "docketNumberSuffix": "L", + "caseStatus": "New", + "completedMessage": "Served to IRS", + "document": { + "documentType": "Petition", + "filingDate": "2020-04-29T15:50:41.686Z", + "partyPrimary": true, + "pending": false, + "receivedAt": "2020-04-29T15:50:41.698Z", + "userId": "7805d1ab-18d0-43ec-bafb-654e83405416", + "eventCode": "P", + "processingStatus": "pending", + "createdAt": "2020-04-29T15:50:41.698Z", + "entityName": "Document", + "filedBy": "Petr. Astra Santiago", + "partySecondary": false, + "documentId": "af9e2d43-1255-4e3d-80d0-63f0aedfab5a", + "privatePractitioners": [] + }, + "caseTitle": "Astra Santiago", + "section": "petitions", + "workItemId": "332026fb-8844-49b6-bb13-66eff6882f00", + "isInitializeCase": true, + "assigneeId": null, + "isQC": true, + "completedByUserId": "3805d1ab-18d0-43ec-bafb-654e83405416", + "sentBy": "7805d1ab-18d0-43ec-bafb-654e83405416", + "createdAt": "2020-04-29T15:50:41.698Z", + "assigneeName": null, + "entityName": "WorkItem", + "caseId": "28caad58-df69-4a4d-af15-6554aee7fbd6", + "sk": "work-item|332026fb-8844-49b6-bb13-66eff6882f00", + "messages": [ + { + "createdAt": "2020-04-29T15:50:41.699Z", + "messageId": "48b750d1-7243-4420-8e03-2a592c07d5bc", + "from": "Test Petitioner", + "message": "Petition filed by Astra Santiago is ready for review.", + "entityName": "Message", + "fromUserId": "7805d1ab-18d0-43ec-bafb-654e83405416" + } + ], + "pk": "work-item|332026fb-8844-49b6-bb13-66eff6882f00", + "docketNumber": "105-20", + "completedBy": "Test Petitionsclerk", + "updatedAt": "2020-04-29T15:50:41.699Z" + }, + { + "associatedJudge": "Chief Judge", + "caseStatus": "General Docket - Not at Issue", + "document": { + "documentType": "Petition", + "filingDate": "2020-04-29T15:50:41.686Z", + "partyPrimary": true, + "pending": false, + "receivedAt": "2020-04-29T15:50:41.698Z", + "userId": "7805d1ab-18d0-43ec-bafb-654e83405416", + "eventCode": "P", + "processingStatus": "pending", + "createdAt": "2020-04-29T15:50:41.698Z", + "entityName": "Document", + "filedBy": "Petr. Astra Santiago", + "partySecondary": false, + "documentId": "af9e2d43-1255-4e3d-80d0-63f0aedfab5a", + "privatePractitioners": [] + }, + "gsi1pk": "work-item|332026fb-8844-49b6-bb13-66eff6882f00", + "section": "petitions", + "workItemId": "332026fb-8844-49b6-bb13-66eff6882f00", + "isQC": true, + "sentBy": "7805d1ab-18d0-43ec-bafb-654e83405416", + "createdAt": "2020-04-29T15:50:41.698Z", + "assigneeName": null, + "entityName": "WorkItem", + "caseId": "28caad58-df69-4a4d-af15-6554aee7fbd6", + "sk": "2020-04-29T15:50:41.698Z", + "updatedAt": "2020-04-29T15:50:41.699Z", + "completedAt": "2020-04-29T15:51:29.331Z", + "docketNumberSuffix": "L", + "completedMessage": "Served to IRS", + "caseTitle": "Astra Santiago", + "isInitializeCase": true, + "assigneeId": null, + "completedByUserId": "3805d1ab-18d0-43ec-bafb-654e83405416", + "messages": [ + { + "createdAt": "2020-04-29T15:50:41.699Z", + "messageId": "48b750d1-7243-4420-8e03-2a592c07d5bc", + "from": "Test Petitioner", + "message": "Petition filed by Astra Santiago is ready for review.", + "entityName": "Message", + "fromUserId": "7805d1ab-18d0-43ec-bafb-654e83405416" + } + ], + "pk": "section-outbox|petitions", + "docketNumber": "105-20", + "completedBy": "Test Petitionsclerk" + }, + { + "associatedJudge": "Chief Judge", + "caseStatus": "General Docket - Not at Issue", + "gsi1pk": "work-item|1bb6306f-0019-4fc5-9286-9f2aa54fadf7", + "document": { + "draftState": null, + "servedParties": [ + { + "name": "Astra Santiago", + "email": "petitioner" + } + ], + "serviceStamp": "Served", + "attachments": false, + "documentType": "O - Order", + "filingDate": "2020-04-29T15:52:01.457Z", + "pending": false, + "receivedAt": "2020-04-29T15:52:01.457Z", + "signedJudgeName": "Maurice B. Foley", + "createdAt": "2020-04-29T15:52:05.725Z", + "scenario": "Type A", + "entityName": "Document", + "caseId": "28caad58-df69-4a4d-af15-6554aee7fbd6", + "documentTitle": "Order that this case is sealed", + "relationship": "primaryDocument", + "workItems": [ + { + "associatedJudge": "Chief Judge", + "docketNumberSuffix": "L", + "inProgress": true, + "caseStatus": "General Docket - Not at Issue", + "document": { + "draftState": { + "eventCode": "O", + "documentType": "Order", + "caseId": "28caad58-df69-4a4d-af15-6554aee7fbd6", + "documentContents": "We are sealing this case right meow.\n", + "documentTitle": "Order that this case is sealed", + "richText": "

We are sealing this case right meow.

", + "docketNumber": "105-20" + }, + "serviceStamp": "Served", + "attachments": false, + "documentType": "O - Order", + "filingDate": "2020-04-29T15:52:01.457Z", + "pending": false, + "documentContents": "We are sealing this case right meow.\n", + "isFileAttached": true, + "receivedAt": "2020-04-29T15:52:01.457Z", + "userId": "3805d1ab-18d0-43ec-bafb-654e83405416", + "eventCode": "O", + "processingStatus": "complete", + "signedJudgeName": "Maurice B. Foley", + "createdAt": "2020-04-29T15:52:05.725Z", + "scenario": "Type A", + "entityName": "Document", + "caseId": "28caad58-df69-4a4d-af15-6554aee7fbd6", + "freeText": "Order that this case is sealed", + "signedAt": "2020-04-29T15:52:05.726Z", + "documentId": "06f60736-5f37-4590-b62a-5c7edf84ffc6", + "signedByUserId": "3805d1ab-18d0-43ec-bafb-654e83405416", + "documentTitle": "Order that this case is sealed", + "relationship": "primaryDocument", + "docketNumber": "105-20" + }, + "caseTitle": "Astra Santiago", + "section": "petitions", + "workItemId": "1bb6306f-0019-4fc5-9286-9f2aa54fadf7", + "assigneeId": "3805d1ab-18d0-43ec-bafb-654e83405416", + "isQC": true, + "sentBy": "Test Petitionsclerk", + "sentBySection": "petitions", + "createdAt": "2020-04-29T15:52:15.627Z", + "assigneeName": "Test Petitionsclerk", + "entityName": "WorkItem", + "caseId": "28caad58-df69-4a4d-af15-6554aee7fbd6", + "hideFromPendingMessages": true, + "messages": [ + { + "createdAt": "2020-04-29T15:52:15.628Z", + "messageId": "fd717166-8cf6-4925-96e8-0f3c807dabca", + "from": "Test Petitionsclerk", + "message": "O - Order filed by Petitionsclerk is ready for review.", + "entityName": "Message", + "fromUserId": "3805d1ab-18d0-43ec-bafb-654e83405416" + } + ], + "docketNumber": "105-20", + "sentByUserId": "3805d1ab-18d0-43ec-bafb-654e83405416", + "updatedAt": "2020-04-29T15:52:15.628Z" + } + ], + "documentContents": "We are sealing this case right meow.\n", + "isFileAttached": true, + "userId": "3805d1ab-18d0-43ec-bafb-654e83405416", + "eventCode": "O", + "processingStatus": "complete", + "freeText": "Order that this case is sealed", + "signedAt": "2020-04-29T15:52:05.726Z", + "documentId": "06f60736-5f37-4590-b62a-5c7edf84ffc6", + "signedByUserId": "3805d1ab-18d0-43ec-bafb-654e83405416", + "servedAt": "2020-04-29T15:52:16.484Z", + "docketNumber": "105-20", + "status": "served" + }, + "section": "petitions", + "workItemId": "1bb6306f-0019-4fc5-9286-9f2aa54fadf7", + "isQC": true, + "sentBy": "Test Petitionsclerk", + "createdAt": "2020-04-29T15:52:15.627Z", + "assigneeName": "Test Petitionsclerk", + "entityName": "WorkItem", + "caseId": "28caad58-df69-4a4d-af15-6554aee7fbd6", + "sk": "2020-04-29T15:52:15.627Z", + "updatedAt": "2020-04-29T15:52:15.628Z", + "completedAt": "2020-04-29T15:52:16.578Z", + "docketNumberSuffix": "L", + "completedMessage": "completed", + "caseTitle": "Astra Santiago", + "assigneeId": "3805d1ab-18d0-43ec-bafb-654e83405416", + "completedByUserId": "3805d1ab-18d0-43ec-bafb-654e83405416", + "sentBySection": "petitions", + "hideFromPendingMessages": true, + "messages": [ + { + "createdAt": "2020-04-29T15:52:15.628Z", + "messageId": "fd717166-8cf6-4925-96e8-0f3c807dabca", + "from": "Test Petitionsclerk", + "message": "O - Order filed by Petitionsclerk is ready for review.", + "entityName": "Message", + "fromUserId": "3805d1ab-18d0-43ec-bafb-654e83405416" + } + ], + "pk": "section-outbox|petitions", + "docketNumber": "105-20", + "sentByUserId": "3805d1ab-18d0-43ec-bafb-654e83405416", + "completedBy": "Test Petitionsclerk" + }, + { + "sk": "case|28caad58-df69-4a4d-af15-6554aee7fbd6", + "pk": "user|7805d1ab-18d0-43ec-bafb-654e83405416" + }, + { + "sk": "case|28caad58-df69-4a4d-af15-6554aee7fbd6", + "pk": "user|9805d1ab-18d0-43ec-bafb-654e83405416" + }, + { + "sk": "case|28caad58-df69-4a4d-af15-6554aee7fbd6", + "pk": "case-by-docket-number|105-20" + } +] diff --git a/web-api/storage/fixtures/seed/106-19.json b/web-api/storage/fixtures/seed/106-19.json index 350b3f774cf..1df1315eb7b 100755 --- a/web-api/storage/fixtures/seed/106-19.json +++ b/web-api/storage/fixtures/seed/106-19.json @@ -466,7 +466,7 @@ "sentBy": "Test Docketclerk", "sentBySection": "docket", "isQC": false, - "caseCaptionNames": "Denise Gould", + "caseTitle": "Denise Gould", "createdAt": "2019-08-08T14:23:51.565Z", "assigneeName": "Judge Armen", "caseId": "d3d92ca6-d9b3-4bd6-8328-e94a9fc36f88", @@ -589,7 +589,7 @@ "isQC": false, "createdAt": "2019-08-08T14:23:51.565Z", "assigneeName": "Judge Armen", - "caseCaptionNames": "Denise Gould", + "caseTitle": "Denise Gould", "caseId": "d3d92ca6-d9b3-4bd6-8328-e94a9fc36f88", "sk": "work-item|368e5d9a-6a9d-4e27-bd88-8521741f0639", "messages": [ @@ -626,7 +626,7 @@ "sentBy": "Test Docketclerk", "sentBySection": "docket", "isQC": false, - "caseCaptionNames": "Denise Gould", + "caseTitle": "Denise Gould", "createdAt": "2019-08-08T14:23:51.565Z", "assigneeName": "Judge Armen", "caseId": "d3d92ca6-d9b3-4bd6-8328-e94a9fc36f88", @@ -659,7 +659,7 @@ "documentId": "7a923abd-fc41-407a-b76b-7f724fa5d47f" }, "section": "armensChambers", - "caseCaptionNames": "Denise Gould", + "caseTitle": "Denise Gould", "workItemId": "368e5d9a-6a9d-4e27-bd88-8521741f0639", "isInitializeCase": false, "assigneeId": "dabbad00-18d0-43ec-bafb-654e83405416", @@ -711,7 +711,7 @@ "createdAt": "2019-08-08T14:23:51.565Z", "assigneeName": "Judge Armen", "caseId": "d3d92ca6-d9b3-4bd6-8328-e94a9fc36f88", - "caseCaptionNames": "Denise Gould", + "caseTitle": "Denise Gould", "sk": "2019-08-08T14:23:51.565Z", "messages": [ { @@ -749,6 +749,7 @@ }, { "documentType": "Statement of Taxpayer Identification", + "entityName": "Document", "filingDate": "2019-07-12T17:09:41.027Z", "workItems": [], "pending": false, @@ -764,6 +765,7 @@ }, { "documentType": "Petition", + "entityName": "Document", "filingDate": "2019-07-12T17:09:41.026Z", "workItems": [ { @@ -819,6 +821,7 @@ "isPaper": true, "serviceDate": null, "documentType": "Proposed Stipulated Decision", + "entityName": "Document", "filingDate": "1990-10-10", "practitioner": [], "partyPrimary": true, diff --git a/web-api/storage/fixtures/seed/107-19.json b/web-api/storage/fixtures/seed/107-19.json index 7508a986af3..dc3ad6eae45 100644 --- a/web-api/storage/fixtures/seed/107-19.json +++ b/web-api/storage/fixtures/seed/107-19.json @@ -316,6 +316,7 @@ }, { "documentType": "Ownership Disclosure Statement", + "entityName": "Document", "filingDate": "2019-08-16T17:29:10.133Z", "workItems": [], "pending": false, @@ -333,6 +334,7 @@ }, { "documentType": "Petition", + "entityName": "Document", "filingDate": "2019-08-16T17:29:10.132Z", "workItems": [ { @@ -395,6 +397,7 @@ }, { "documentType": "Statement of Taxpayer Identification", + "entityName": "Document", "filingDate": "2019-08-16T17:29:10.133Z", "workItems": [], "pending": false, diff --git a/web-api/storage/fixtures/seed/108-19.json b/web-api/storage/fixtures/seed/108-19.json index f588745a25e..450b557d54b 100644 --- a/web-api/storage/fixtures/seed/108-19.json +++ b/web-api/storage/fixtures/seed/108-19.json @@ -227,6 +227,7 @@ }, { "documentType": "Statement of Taxpayer Identification", + "entityName": "Document", "filingDate": "2019-08-16T19:21:46.147Z", "workItems": [], "pending": false, @@ -244,6 +245,7 @@ }, { "documentType": "Petition", + "entityName": "Document", "filingDate": "2019-08-16T19:21:46.146Z", "workItems": [ { diff --git a/web-api/storage/fixtures/seed/109-19.json b/web-api/storage/fixtures/seed/109-19.json index d24ef94973a..d55541f3f89 100644 --- a/web-api/storage/fixtures/seed/109-19.json +++ b/web-api/storage/fixtures/seed/109-19.json @@ -93,6 +93,7 @@ }, { "documentType": "Petition", + "entityName": "Document", "filingDate": "2019-03-01T21:40:46.415Z", "workItems": [ { @@ -108,7 +109,7 @@ "userId": "7805d1ab-18d0-43ec-bafb-654e83405416", "filedBy": "Test Petitioner" }, - "caseCaptionNames": "Brett Osborne", + "caseTitle": "Brett Osborne", "section": "petitions", "workItemId": "2611344f-f7bf-4f47-8ba0-60c70cb25446", "isInitializeCase": true, @@ -152,6 +153,7 @@ "caseId": "2fb2da8d-4328-4a20-a5d7-b76637e1dc02" }, "documentType": "Order of Dismissal for Lack of Jurisdiction", + "entityName": "Document", "filingDate": "2019-10-07T14:29:30.288Z", "workItems": [], "pending": false, @@ -173,6 +175,7 @@ }, { "documentType": "Statement of Taxpayer Identification", + "entityName": "Document", "filingDate": "2019-03-05T17:34:13.491Z", "workItems": [], "pending": false, diff --git a/web-api/storage/fixtures/seed/110-19.json b/web-api/storage/fixtures/seed/110-19.json index eb16a2aebba..8b4bb3971e2 100644 --- a/web-api/storage/fixtures/seed/110-19.json +++ b/web-api/storage/fixtures/seed/110-19.json @@ -72,6 +72,7 @@ }, { "documentType": "Petition", + "entityName": "Document", "filingDate": "2019-03-01T21:40:46.415Z", "workItems": [ { @@ -88,7 +89,7 @@ "documentTitle": "Petition", "userId": "7805d1ab-18d0-43ec-bafb-654e83405416" }, - "caseCaptionNames": "Brett Osborne", + "caseTitle": "Brett Osborne", "section": "petitions", "workItemId": "2611344f-f7bf-4f47-8ba0-60c70cb25446", "isInitializeCase": true, @@ -132,6 +133,7 @@ "caseId": "2fb2da8d-4328-4a20-a5d7-a76637e1dc01" }, "documentType": "Order of Dismissal for Lack of Jurisdiction", + "entityName": "Document", "filingDate": "2019-10-07T14:29:30.288Z", "workItems": [], "pending": false, @@ -153,6 +155,7 @@ }, { "documentType": "Statement of Taxpayer Identification", + "entityName": "Document", "filingDate": "2019-03-05T17:34:13.491Z", "workItems": [], "pending": false, diff --git a/web-api/storage/fixtures/seed/111-19.json b/web-api/storage/fixtures/seed/111-19.json index 587029bdb8e..9d56dae8fd8 100644 --- a/web-api/storage/fixtures/seed/111-19.json +++ b/web-api/storage/fixtures/seed/111-19.json @@ -76,6 +76,7 @@ }, { "documentType": "Statement of Taxpayer Identification", + "entityName": "Document", "filingDate": "2019-12-11T15:25:09.286Z", "partyPrimary": true, "workItems": [], @@ -94,6 +95,7 @@ }, { "documentType": "Petition", + "entityName": "Document", "filingDate": "2019-12-11T15:25:09.285Z", "partyPrimary": true, "workItems": [ @@ -116,7 +118,7 @@ "receivedAt": "2019-12-11T15:25:09.285Z", "userId": "7805d1ab-18d0-43ec-bafb-654e83405416" }, - "caseCaptionNames": "Guy Fieri", + "caseTitle": "Guy Fieri", "section": "petitions", "workItemId": "9fc70206-15c6-4c68-87bb-295dee8f002d", "isInitializeCase": true, diff --git a/web-api/storage/fixtures/seed/112-19.json b/web-api/storage/fixtures/seed/112-19.json index 4f862f133d8..451bbaa939e 100644 --- a/web-api/storage/fixtures/seed/112-19.json +++ b/web-api/storage/fixtures/seed/112-19.json @@ -77,6 +77,7 @@ }, { "documentType": "Statement of Taxpayer Identification", + "entityName": "Document", "filingDate": "2019-12-11T15:25:55.008Z", "partyPrimary": true, "workItems": [], @@ -95,6 +96,7 @@ }, { "documentType": "Petition", + "entityName": "Document", "filingDate": "2019-12-11T15:25:55.007Z", "partyPrimary": true, "workItems": [ @@ -117,7 +119,7 @@ "receivedAt": "2019-12-11T15:25:55.007Z", "userId": "7805d1ab-18d0-43ec-bafb-654e83405416" }, - "caseCaptionNames": "Brian Earl Spilner", + "caseTitle": "Brian Earl Spilner", "section": "petitions", "workItemId": "dfded65f-8aba-4af2-8e1e-b17a901e1753", "isInitializeCase": true, diff --git a/web-api/storage/fixtures/seed/113-19.json b/web-api/storage/fixtures/seed/113-19.json index 1b7cf290059..23830848d67 100644 --- a/web-api/storage/fixtures/seed/113-19.json +++ b/web-api/storage/fixtures/seed/113-19.json @@ -76,6 +76,7 @@ }, { "documentType": "Statement of Taxpayer Identification", + "entityName": "Document", "filingDate": "2019-12-11T16:02:31.176Z", "partyPrimary": true, "workItems": [], @@ -94,6 +95,7 @@ }, { "documentType": "Petition", + "entityName": "Document", "filingDate": "2019-12-11T16:02:31.174Z", "partyPrimary": true, "workItems": [ @@ -116,7 +118,7 @@ "receivedAt": "2019-12-11T16:02:31.174Z", "userId": "7805d1ab-18d0-43ec-bafb-654e83405416" }, - "caseCaptionNames": "Letti Toretto", + "caseTitle": "Letti Toretto", "section": "petitions", "workItemId": "f1f8459d-771d-4d60-b97c-9f05c7f79b94", "isInitializeCase": true, diff --git a/web-api/storage/fixtures/seed/index.js b/web-api/storage/fixtures/seed/index.js index 993dd9e58bf..ae4c648ba9c 100755 --- a/web-api/storage/fixtures/seed/index.js +++ b/web-api/storage/fixtures/seed/index.js @@ -16,6 +16,7 @@ module.exports = [ ...require('./102-20.json'), ...require('./103-20.json'), ...require('./104-20.json'), + ...require('./105-20.json'), ...require('./trial-sessions.json'), ...require('./trial-sessions-past.json'), ...require('./misc.json'), diff --git a/web-api/storage/fixtures/seed/misc.json b/web-api/storage/fixtures/seed/misc.json index 7fcb45e6da8..a8d3c8e9e8d 100755 --- a/web-api/storage/fixtures/seed/misc.json +++ b/web-api/storage/fixtures/seed/misc.json @@ -6,7 +6,7 @@ }, { "sk": "docketNumberCounter-2020", - "id": 4, + "id": 5, "pk": "docketNumberCounter-2020" } ] diff --git a/web-api/storage/fixtures/seed/users.json b/web-api/storage/fixtures/seed/users.json index ab41780dc41..33eeac393e8 100755 --- a/web-api/storage/fixtures/seed/users.json +++ b/web-api/storage/fixtures/seed/users.json @@ -4,21 +4,24 @@ "name": "Test Admin", "section": "admin", "userId": "86c3f87b-350b-477d-92c3-43bd095cb006", - "email": "admin" + "email": "admin", + "entityName": "User" }, { "role": "docketclerk", "name": "Test Docketclerk", "section": "docket", "userId": "1805d1ab-18d0-43ec-bafb-654e83405416", - "email": "docketclerk" + "email": "docketclerk", + "entityName": "User" }, { "role": "docketclerk", "name": "Test Docketclerk1", "section": "docket", "userId": "2805d1ab-18d0-43ec-bafb-654e83405416", - "email": "docketclerk1" + "email": "docketclerk1", + "entityName": "User" }, { "role": "judge", @@ -27,7 +30,8 @@ "userId": "dabbad00-18d0-43ec-bafb-654e83405416", "email": "judgeArmen", "judgeFullName": "Robert N. Armen, Jr.", - "judgeTitle": "Special Trial Judge" + "judgeTitle": "Special Trial Judge", + "entityName": "User" }, { "role": "judge", @@ -36,7 +40,17 @@ "userId": "dabbad01-18d0-43ec-bafb-654e83405416", "email": "judgeAshford", "judgeFullName": "Tamara W. Ashford", - "judgeTitle": "Judge" + "judgeTitle": "Judge", + "entityName": "User" + }, + { + "role": "judge", + "name": "Chief Judge Foley", + "section": "foleysChambers", + "userId": "659789b4-acc5-40b7-9318-3354e7eb8604", + "email": "judgeFoley", + "judgeFullName": "Maurice B. Foley", + "judgeTitle": "Chief Judge" }, { "role": "judge", @@ -45,7 +59,8 @@ "userId": "dabbad02-18d0-43ec-bafb-654e83405416", "email": "judgeBuch", "judgeFullName": "Ronald L. Buch", - "judgeTitle": "Judge" + "judgeTitle": "Judge", + "entityName": "User" }, { "role": "judge", @@ -54,7 +69,8 @@ "userId": "dabbad03-18d0-43ec-bafb-654e83405416", "email": "judgeCarluzzo", "judgeFullName": "Lewis R. Carluzzo", - "judgeTitle": "Chief Special Trial Judge" + "judgeTitle": "Chief Special Trial Judge", + "entityName": "User" }, { "role": "judge", @@ -63,7 +79,8 @@ "userId": "dabbad04-18d0-43ec-bafb-654e83405416", "email": "judgeCohen", "judgeFullName": "Mary Ann Cohen", - "judgeTitle": "Judge" + "judgeTitle": "Judge", + "entityName": "User" }, { "role": "judge", @@ -72,7 +89,8 @@ "userId": "dabbad05-18d0-43ec-bafb-654e83405416", "email": "judgeGustafson", "judgeFullName": "David Gustafson", - "judgeTitle": "Judge" + "judgeTitle": "Judge", + "entityName": "User" }, { "role": "judge", @@ -81,7 +99,8 @@ "userId": "dabbad06-18d0-43ec-bafb-654e83405416", "email": "judgePugh", "judgeFullName": "Cary Douglas Pugh", - "judgeTitle": "Judge" + "judgeTitle": "Judge", + "entityName": "User" }, { "role": "judge", @@ -90,28 +109,32 @@ "userId": "dabbad0a-18d0-43ec-bafb-654e83405416", "email": "judgeUrda", "judgeFullName": "Patrick J. Urda", - "judgeTitle": "Judge" + "judgeTitle": "Judge", + "entityName": "User" }, { "role": "adc", "name": "Test ADC", "section": "adc", "userId": "6805d1ab-18d0-43ec-bafb-654e83405416", - "email": "adc" + "email": "adc", + "entityName": "User" }, { "role": "petitionsclerk", "name": "Test Petitionsclerk", "section": "petitions", "userId": "3805d1ab-18d0-43ec-bafb-654e83405416", - "email": "petitionsclerk" + "email": "petitionsclerk", + "entityName": "User" }, { "role": "petitionsclerk", "name": "Test Petitionsclerk1", "section": "petitions", "userId": "4805d1ab-18d0-43ec-bafb-654e83405416", - "email": "petitionsclerk1" + "email": "petitionsclerk1", + "entityName": "User" }, { "role": "privatePractitioner", @@ -127,6 +150,7 @@ "suffix": "", "section": "privatePractitioner", "userId": "9805d1ab-18d0-43ec-bafb-654e83405416", + "entityName": "PrivatePractitioner", "email": "privatePractitioner", "firmName": "GW Law Offices", "alternateEmail": "privatePractitioner@example.com", @@ -158,6 +182,7 @@ "suffix": "", "section": "privatePractitioner", "userId": "ad07b846-8933-4778-9fe2-b5d8ac8ad728", + "entityName": "PrivatePractitioner", "email": "privatePractitioner1", "firmName": "Bogus Barristers", "barNumber": "PT5432", @@ -200,7 +225,8 @@ "postalCode": "61234", "state": "IL" }, - "originalBarState": "N/A" + "originalBarState": "N/A", + "entityName": "PrivatePractitioner" }, { "role": "privatePractitioner", @@ -229,7 +255,8 @@ "postalCode": "61234", "state": "IL" }, - "originalBarState": "Texas" + "originalBarState": "Texas", + "entityName": "PrivatePractitioner" }, { "role": "privatePractitioner", @@ -258,7 +285,8 @@ "postalCode": "61234", "state": "IL" }, - "originalBarState": "Florida" + "originalBarState": "Florida", + "entityName": "PrivatePractitioner" }, { "role": "irsPractitioner", @@ -286,7 +314,8 @@ "postalCode": "61234", "state": "IL" }, - "originalBarState": "Maryland" + "originalBarState": "Maryland", + "entityName": "IrsPractitioner" }, { "role": "irsPractitioner", @@ -314,7 +343,8 @@ "postalCode": "61234", "state": "IL" }, - "originalBarState": "Arkansas" + "originalBarState": "Arkansas", + "entityName": "IrsPractitioner" }, { "role": "irsPractitioner", @@ -342,7 +372,8 @@ "postalCode": "61234", "state": "IL" }, - "originalBarState": "Colorado" + "originalBarState": "Colorado", + "entityName": "IrsPractitioner" }, { "role": "irsPractitioner", @@ -370,7 +401,8 @@ "postalCode": "61234", "state": "IL" }, - "originalBarState": "Nevada" + "originalBarState": "Nevada", + "entityName": "IrsPractitioner" }, { "role": "irsPractitioner", @@ -391,7 +423,8 @@ "address2": "Hanover, MI 49241", "barNumber": "LJ9999", "phone": "517-563-1536", - "originalBarState": "Tennessee" + "originalBarState": "Tennessee", + "entityName": "IrsPractitioner" }, { "role": "petitioner", @@ -401,91 +434,104 @@ "email": "petitioner", "address1": "3202 Elk Avenue", "address2": "Hanover, MI 49241", - "phone": "517-563-1536" + "phone": "517-563-1536", + "entityName": "User" }, { "role": "admissionsclerk", "name": "Test Admissions Clerk", "section": "admissions", "userId": "9d7d63b7-d7a5-4905-ba89-ef71bf30057f", - "email": "admissionsclerk" + "email": "admissionsclerk", + "entityName": "User" }, { "role": "clerkofcourt", "name": "Test Clerk of Court", "section": "clerkofcourt", "userId": "23dd8806-c0c7-4265-81f0-5f264ef78248", - "email": "clerkofcourt" + "email": "clerkofcourt", + "entityName": "User" }, { "role": "trialclerk", "name": "Test Trial Clerk", "section": "trialClerks", "userId": "f0a1e52a-876f-4c03-853c-f66e407e5a1e", - "email": "trialclerk" + "email": "trialclerk", + "entityName": "User" }, { "role": "chambers", "name": "Test Armen's Chambers", "section": "armensChambers", "userId": "9c9292a4-2d5d-45b1-b67f-ac0e1c9b5df5", - "email": "armensChambers" + "email": "armensChambers", + "entityName": "User" }, { "role": "chambers", "name": "Test Ashford's Chambers", "section": "ashfordsChambers", "userId": "817b48c5-d4e5-4544-9e11-9ba0102918f4", - "email": "ashfordsChambers" + "email": "ashfordsChambers", + "entityName": "User" }, { "role": "chambers", "name": "Test Buch's Chambers", "section": "buchsChambers", "userId": "49421c68-0c09-4b4b-b32c-a535279be8d0", - "email": "buchsChambers" + "email": "buchsChambers", + "entityName": "User" }, { "role": "chambers", "name": "Test Carluzzo's Chambers", "section": "carluzzosChambers", "userId": "8c0902ab-d156-4cca-b80d-43f595aa5ab0", - "email": "carluzzosChambers" + "email": "carluzzosChambers", + "entityName": "User" }, { "role": "chambers", "name": "Test Cohen's Chambers", "section": "cohensChambers", "userId": "0bd3bc49-4e46-4caa-adeb-4960c56e17c8", - "email": "cohensChambers" + "email": "cohensChambers", + "entityName": "User" }, { "role": "chambers", "name": "Test Gustafson's Chambers", "section": "gustafsonsChambers", "userId": "3ce1dad5-87ee-4b00-a4fb-f7f80296a5c2", - "email": "gustafsonsChambers" + "email": "gustafsonsChambers", + "entityName": "User" }, { "role": "chambers", "name": "Test Pugh's Chambers", "section": "pughsChambers", "userId": "9fbae83a-a55b-4132-96df-e04a8ee675e3", - "email": "pughsChambers" + "email": "pughsChambers", + "entityName": "User" }, { "role": "chambers", "name": "Test Urda's Chambers", "section": "urdasChambers", "userId": "44f02385-e4c6-49f9-a554-ecf93531d8a3", - "email": "urdasChambers" + "email": "urdasChambers", + "entityName": "User" }, { "role": "floater", "name": "Test Floater", "section": "floater", "userId": "9ef02385-e4c6-49f9-a554-ecf93531d8a4", - "email": "testFloater" + "email": "testFloater", + "entityName": "User" }, { "role": "inactivePractitioner", @@ -513,13 +559,15 @@ "postalCode": "61234", "state": "IL" }, - "originalBarState": "California" + "originalBarState": "California", + "entityName": "Practitioner" }, { "role": "irsSuperuser", "name": "Test IRS Superuser", "section": "irsSuperuser", "userId": "02c9b614-e498-4dae-b0f5-751b9ab5e8b3", - "email": "irsSuperuser" + "email": "irsSuperuser", + "entityName": "User" } ] diff --git a/web-api/storage/fixtures/validate-seed.js b/web-api/storage/fixtures/validate-seed.js new file mode 100755 index 00000000000..4b312eaeeea --- /dev/null +++ b/web-api/storage/fixtures/validate-seed.js @@ -0,0 +1,46 @@ +#!/usr/bin/env node + +const fs = require('fs'); +const { stdin } = process; + +const EXISTING_UUID = '1f1aa3f7-e2e3-43e6-885d-4ce341588c76'; + +const uuidMatch = /([-\d]+\.json).*?([-0-9a-f]{36})/gims; + +stdin.setEncoding('utf8'); +stdin.on('error', console.error); + +const documentIds = {}; + +stdin.on('data', function (chunk) { + let match; + while ((match = uuidMatch.exec(chunk)) !== null) { + const uuid = match[2]; + documentIds[uuid] = match[1]; + } +}); +stdin.on('end', () => { + Object.entries(documentIds).forEach(checkFilesExist); +}); + +/** + * @param {Array} entry to the seedFile which ought to exist + * @param {string} entry.seedFile the seed file that referenced the documentId + * @param {string} entry.uuid the documentId's UUID + */ +function checkFilesExist([uuid, seedFile]) { + const createFiles = { + [`${__dirname}/s3/noop-documents-local-us-east-1/${uuid}._S3rver_metadata.json`]: `${__dirname}/s3/noop-documents-local-us-east-1/${EXISTING_UUID}._S3rver_metadata.json`, + [`${__dirname}/s3/noop-documents-local-us-east-1/${uuid}._S3rver_object`]: `${__dirname}/s3/noop-documents-local-us-east-1/${EXISTING_UUID}._S3rver_object`, + [`${__dirname}/s3/noop-documents-local-us-east-1/${uuid}._S3rver_object.md5`]: `${__dirname}/s3/noop-documents-local-us-east-1/${EXISTING_UUID}._S3rver_object.md5`, + }; + + Object.entries(createFiles).forEach(([desired, copyFrom]) => { + fs.access(desired, fs.F_OK, err => { + if (err) { + // console.warn(`WARNING: missing s3 seed data files from ${seedFile}!`); + console.warn(`cp "${copyFrom}" "${desired}"`); + } + }); + }); +} diff --git a/web-api/storage/scripts/loadTest/loadTestHelpers.js b/web-api/storage/scripts/loadTest/loadTestHelpers.js index beacdc1fa26..20699532fc3 100644 --- a/web-api/storage/scripts/loadTest/loadTestHelpers.js +++ b/web-api/storage/scripts/loadTest/loadTestHelpers.js @@ -1,8 +1,11 @@ const faker = require('faker'); +const { + TrialSession, +} = require('../../../../shared/src/business/entities/trialSessions/TrialSession'); +const { Case } = require('../../../../shared/src/business/entities/cases/Case'); +const { User } = require('../../../../shared/src/business/entities/User'); const createTrialSession = async ({ applicationContext }) => { - const { TrialSession } = applicationContext.getEntityConstructors(); - let startDate = faker.date.future(1); let startDateObj = new Date(startDate); let selectedMonth = startDate.getMonth() + 1; @@ -104,12 +107,6 @@ const createCase = async ({ } } - const { - Case, - TrialSession, - User, - } = applicationContext.getEntityConstructors(); - const petitionerName = `${faker.name.firstName()} ${faker.name.lastName()}`; const caseDetail = await applicationContext @@ -153,7 +150,6 @@ const createCase = async ({ }); }; - let idx = 0; for (const document of caseDetail.documents) { if (shouldUpload) { await addCoversheet(document); @@ -166,8 +162,6 @@ const createCase = async ({ caseId: caseDetail.caseId, documentId: document.documentId, }); - - idx++; } return { caseDetail, petitionFileId, stinFileId }; diff --git a/web-api/terraform/bin/deploy-app.sh b/web-api/terraform/bin/deploy-app.sh index 08ff980372d..17562fc2a7d 100755 --- a/web-api/terraform/bin/deploy-app.sh +++ b/web-api/terraform/bin/deploy-app.sh @@ -21,8 +21,18 @@ else echo "dynamodb lock table already exists" fi +# build the cognito authorizer using parcel +pushd ../template/cognito-authorizer +npx parcel build index.js --target node --bundle-node-modules --no-minify +popd + +pushd ../template/log-forwarder +npx parcel build index.js --target node --bundle-node-modules --no-minify +popd + + # exit on any failure set -eo pipefail terraform init -backend=true -backend-config=bucket="${BUCKET}" -backend-config=key="${KEY}" -backend-config=dynamodb_table="${LOCK_TABLE}" -backend-config=region="${REGION}" -TF_VAR_my_s3_state_bucket="${BUCKET}" TF_VAR_my_s3_state_key="${KEY}" terraform apply -auto-approve -var "dns_domain=${EFCMS_DOMAIN}" -var "environment=${ENVIRONMENT}" -var "cognito_suffix=${COGNITO_SUFFIX}" -var "ses_dmarc_rua=${SES_DMARC_EMAIL}" -var "es_instance_count=${ES_INSTANCE_COUNT}" +TF_VAR_my_s3_state_bucket="${BUCKET}" TF_VAR_my_s3_state_key="${KEY}" terraform apply -auto-approve -var "dns_domain=${EFCMS_DOMAIN}" -var "environment=${ENVIRONMENT}" -var "cognito_suffix=${COGNITO_SUFFIX}" -var "ses_dmarc_rua=${SES_DMARC_EMAIL}" -var "es_instance_count=${ES_INSTANCE_COUNT}" -var "honeybadger_key=${CIRCLE_HONEYBADGER_API_KEY}" diff --git a/web-api/terraform/main/main.tf b/web-api/terraform/main/main.tf index ec0f37e840d..36ff38ca15b 100644 --- a/web-api/terraform/main/main.tf +++ b/web-api/terraform/main/main.tf @@ -14,4 +14,5 @@ module "ef-cms_apis" { cognito_suffix = "${var.cognito_suffix}" ses_dmarc_rua = "${var.ses_dmarc_rua}" es_instance_count = "${var.es_instance_count}" + honeybadger_key = "${var.honeybadger_key}" } diff --git a/web-api/terraform/main/variables.tf b/web-api/terraform/main/variables.tf index b5a073ca661..a28cc922b86 100644 --- a/web-api/terraform/main/variables.tf +++ b/web-api/terraform/main/variables.tf @@ -21,4 +21,8 @@ variable "ses_dmarc_rua" { variable "es_instance_count" { type = "string" default = "1" +} + +variable "honeybadger_key" { + type = "string" } \ No newline at end of file diff --git a/web-api/terraform/template/cognito-authorizer.tf b/web-api/terraform/template/cognito-authorizer.tf new file mode 100644 index 00000000000..e798bed3a57 --- /dev/null +++ b/web-api/terraform/template/cognito-authorizer.tf @@ -0,0 +1,42 @@ +data "archive_file" "zip_authorizer" { + type = "zip" + output_path = "${path.module}/cognito-authorizer/index.js.zip" + source_file = "${path.module}/cognito-authorizer/dist/index.js" +} + +resource "aws_lambda_function" "cognito_authorizer_lambda" { + filename = "${data.archive_file.zip_authorizer.output_path}" + function_name = "cognito_authorizer_lambda_${var.environment}" + role = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/authorizer_lambda_role_${var.environment}" + handler = "index.handler" + source_code_hash = "${data.archive_file.zip_authorizer.output_base64sha256}" + + runtime = "nodejs12.x" + + environment { + variables = { + USER_POOL_ID_MAIN = "${aws_cognito_user_pool.pool.id}" + USER_POOL_ID_IRS = "${aws_cognito_user_pool.irs_pool.id}" + } + } +} + + +resource "aws_lambda_function" "cognito_authorizer_lambda_west" { + filename = "${data.archive_file.zip_authorizer.output_path}" + function_name = "cognito_authorizer_lambda_${var.environment}" + role = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/authorizer_lambda_role_${var.environment}" + handler = "index.handler" + source_code_hash = "${data.archive_file.zip_authorizer.output_base64sha256}" + + runtime = "nodejs12.x" + + environment { + variables = { + USER_POOL_ID_MAIN = "${aws_cognito_user_pool.pool.id}" + USER_POOL_ID_IRS = "${aws_cognito_user_pool.irs_pool.id}" + } + } + + provider = "aws.us-west-1" +} \ No newline at end of file diff --git a/web-api/terraform/template/cognito-authorizer/index.js b/web-api/terraform/template/cognito-authorizer/index.js new file mode 100644 index 00000000000..8ac27cd5257 --- /dev/null +++ b/web-api/terraform/template/cognito-authorizer/index.js @@ -0,0 +1,81 @@ +const jwk = require('jsonwebtoken'); +const jwkToPem = require('jwk-to-pem'); +const request = require('request'); + +const issMain = `https://cognito-idp.us-east-1.amazonaws.com/${process.env.USER_POOL_ID_MAIN}`; +const issIrs = `https://cognito-idp.us-east-1.amazonaws.com/${process.env.USER_POOL_ID_IRS}`; + +let keys; + +const generatePolicy = (principalId, effect, resource) => { + const authResponse = {}; + authResponse.principalId = principalId; + if (effect && resource) { + const policyDocument = {}; + policyDocument.Version = '2012-10-17'; + policyDocument.Statement = []; + const statementOne = {}; + statementOne.Action = 'execute-api:Invoke'; + statementOne.Effect = effect; + statementOne.Resource = resource; + policyDocument.Statement[0] = statementOne; + authResponse.policyDocument = policyDocument; + } + return authResponse; +}; + +const verify = (methodArn, token, keys, kid, cb) => { + const k = keys.keys.find(k => k.kid === kid); + const pem = jwkToPem(k); + + jwk.verify(token, pem, { issuer: [issMain, issIrs] }, (err, decoded) => { + if (err) { + console.log('Unauthorized user:', err.message); + cb('Unauthorized'); + } else { + cb( + null, + generatePolicy( + decoded.sub, + 'Allow', + methodArn.split('/').slice(0, 2).join('/') + '/*', + ), + ); + } + }); +}; + +module.exports.handler = (event, context, cb) => { + console.log('Auth function invoked'); + + let requestToken = null; + if (event.authorizationToken) { + requestToken = event.authorizationToken.substring(7); + } else if (event.queryStringParameters.token) { + requestToken = event.queryStringParameters.token; + } + + if (requestToken) { + const { header, payload } = jwk.decode(requestToken, { complete: true }); + const { iss } = payload; + const { kid } = header; + if (keys) { + verify(event.methodArn, requestToken, keys, kid, cb); + } else { + request( + { json: true, url: `${iss}/.well-known/jwks.json` }, + (error, response, body) => { + if (error || response.statusCode !== 200) { + console.log('Request error:', error); + cb('Unauthorized'); + } + keys = body; + verify(event.methodArn, requestToken, keys, kid, cb); + }, + ); + } + } else { + console.log('No authorizationToken found in the header.'); + cb('Unauthorized'); + } +}; diff --git a/web-api/terraform/template/cognito.tf b/web-api/terraform/template/cognito.tf index 2fa38e0f0d7..5a8c2cc333b 100644 --- a/web-api/terraform/template/cognito.tf +++ b/web-api/terraform/template/cognito.tf @@ -25,8 +25,8 @@ resource "aws_cognito_user_pool" "pool" { allow_admin_create_user_only = false invite_message_template { sms_message = "Your username is {username} and temporary password is {####}." - email_subject = "U.S. Tax Court account creation" - email_message = "An account has been created for you on the U.S. Tax Court site. Your username is {username} and temporary password is {####}. Please log in and change your password." + email_subject = "Update Your Email with the U.S. Tax Court" + email_message = "Welcome to the U.S. Tax Court case management system. You are now able to log in to view and manage your cases.

Your username: {username}

Temporary password: {####}


For added security, please log in to the U.S. Tax Court site to change your password." } } @@ -100,3 +100,117 @@ resource "aws_cognito_user_pool_domain" "main" { domain = "auth-${var.environment}-${var.cognito_suffix}" user_pool_id = "${aws_cognito_user_pool.pool.id}" } + +resource "aws_cognito_user_pool" "irs_pool" { + name = "efcms-irs-${var.environment}" + + mfa_configuration = "ON" + + software_token_mfa_configuration { + enabled = true + } + + device_configuration { + challenge_required_on_new_device = true + device_only_remembered_on_user_prompt = false + } + + auto_verified_attributes = ["email"] + + username_attributes = ["email"] + + verification_message_template { + default_email_option = "CONFIRM_WITH_LINK" + email_message_by_link = "Please click the link below to verify your email address. {##Verify Email##} " + email_subject_by_link = "U.S. Tax Court account verification" + } + + sms_authentication_message = "{####}" + + lifecycle { + prevent_destroy = true + } + + lambda_config { + post_confirmation = "${aws_lambda_function.cognito_post_confirmation_lambda.arn}" + } + + admin_create_user_config { + allow_admin_create_user_only = true + invite_message_template { + sms_message = "Your username is {username} and temporary password is {####}." + email_subject = "U.S. Tax Court account creation" + email_message = "An account has been created for you on the U.S. Tax Court site. Your username is {username} and temporary password is {####}. Please log in and change your password." + } + } + + schema { + attribute_data_type = "String" + name = "email" + required = true + mutable = true + + string_attribute_constraints { + min_length = 0 + max_length = 255 + } + } + + schema { + attribute_data_type = "String" + name = "role" + required = false + mutable = true + + string_attribute_constraints { + min_length = 0 + max_length = 255 + } + } + + schema { + attribute_data_type = "String" + name = "name" + required = true + mutable = true + + string_attribute_constraints { + min_length = 0 + max_length = 255 + } + } + + password_policy { + minimum_length = 8 + require_lowercase = true + require_uppercase = true + require_numbers = true + require_symbols = true + } +} + +resource "aws_cognito_user_pool_client" "irs_client" { + name = "irs_client" + + explicit_auth_flows = ["ADMIN_NO_SRP_AUTH","USER_PASSWORD_AUTH"] + + generate_secret = false + refresh_token_validity = 30 + allowed_oauth_flows_user_pool_client = true + + callback_urls = [ + "http://localhost:1234/log-in", + "https://ui-${var.environment}.${var.dns_domain}/log-in", + ] + + allowed_oauth_flows = ["code", "implicit"] + allowed_oauth_scopes = ["email", "openid", "profile", "phone", "aws.cognito.signin.user.admin"] + supported_identity_providers = ["COGNITO"] + + user_pool_id = "${aws_cognito_user_pool.irs_pool.id}" +} + +resource "aws_cognito_user_pool_domain" "irs" { + domain = "auth-irs-${var.environment}-${var.cognito_suffix}" + user_pool_id = "${aws_cognito_user_pool.irs_pool.id}" +} diff --git a/web-api/terraform/template/elasticsearch.tf b/web-api/terraform/template/elasticsearch.tf index f6e5b4aca71..c50ad3bd0ad 100644 --- a/web-api/terraform/template/elasticsearch.tf +++ b/web-api/terraform/template/elasticsearch.tf @@ -1,6 +1,6 @@ resource "aws_elasticsearch_domain" "efcms-search" { domain_name = "efcms-search-${var.environment}" - elasticsearch_version = "7.1" + elasticsearch_version = "7.4" cluster_config { instance_type = "t2.small.elasticsearch" diff --git a/web-api/terraform/template/log-forwarder.tf b/web-api/terraform/template/log-forwarder.tf new file mode 100644 index 00000000000..0854f9c857e --- /dev/null +++ b/web-api/terraform/template/log-forwarder.tf @@ -0,0 +1,42 @@ +data "archive_file" "zip_forwarder" { + type = "zip" + output_path = "${path.module}/log-forwarder/index.js.zip" + source_file = "${path.module}/log-forwarder/dist/index.js" +} + +resource "aws_lambda_function" "log_forwarder" { + filename = "${data.archive_file.zip_forwarder.output_path}" + function_name = "log_forwarder_${var.environment}" + role = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/log_forwarder_role_${var.environment}" + handler = "index.handler" + source_code_hash = "${data.archive_file.zip_forwarder.output_base64sha256}" + + runtime = "nodejs12.x" + + environment { + variables = { + CIRCLE_HONEYBADGER_API_KEY = "${var.honeybadger_key}" + NODE_ENV = "production" + } + } +} + + +resource "aws_lambda_function" "log_forwarder_west" { + filename = "${data.archive_file.zip_forwarder.output_path}" + function_name = "log_forwarder_${var.environment}" + role = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/log_forwarder_role_${var.environment}" + handler = "index.handler" + source_code_hash = "${data.archive_file.zip_forwarder.output_base64sha256}" + + runtime = "nodejs12.x" + + environment { + variables = { + CIRCLE_HONEYBADGER_API_KEY = "${var.honeybadger_key}" + NODE_ENV = "production" + } + } + + provider = "aws.us-west-1" +} \ No newline at end of file diff --git a/web-api/terraform/template/log-forwarder/index.js b/web-api/terraform/template/log-forwarder/index.js new file mode 100644 index 00000000000..19681c6705f --- /dev/null +++ b/web-api/terraform/template/log-forwarder/index.js @@ -0,0 +1,23 @@ +const Honeybadger = require('honeybadger'); +const zlib = require('zlib'); + +const honeybadger = Honeybadger.configure({ + apiKey: process.env.CIRCLE_HONEYBADGER_API_KEY, + environment: 'api', +}); + +exports.handler = async event => { + if (event.awslogs && event.awslogs.data) { + const payload = Buffer.from(event.awslogs.data, 'base64'); + + const logevents = JSON.parse(zlib.unzipSync(payload).toString()).logEvents; + + for (const logevent of logevents) { + await new Promise(resolve => { + honeybadger.notify(logevent, null, null, resolve); + }); + + console.log(logevent); + } + } +}; diff --git a/web-api/terraform/template/variables.tf b/web-api/terraform/template/variables.tf index 4bfd4fe6d0d..58c04f604a5 100644 --- a/web-api/terraform/template/variables.tf +++ b/web-api/terraform/template/variables.tf @@ -17,3 +17,7 @@ variable "ses_dmarc_rua" { variable "es_instance_count" { type = "string" } + +variable "honeybadger_key" { + type = "string" +} diff --git a/web-api/verify-authorizers.js b/web-api/verify-authorizers.js new file mode 100755 index 00000000000..dba9183c883 --- /dev/null +++ b/web-api/verify-authorizers.js @@ -0,0 +1,78 @@ +const axios = require('axios'); +const fs = require('fs'); +const yaml = require('js-yaml'); +const env = process.env.ENV; + +axios.interceptors.request.use(function (config) { + config.headers['Content-Type'] = 'application/json'; + return config; +}); + +const main = async () => { + const serverlessYmlFiles = process.argv + .slice(2) + .filter(path => !path.includes('public-api')); + + const serverlessConfigs = serverlessYmlFiles.map(path => + yaml.safeLoad(fs.readFileSync(path, 'utf8')), + ); + + const missingAuthorizers = []; + const no401Response = []; + + console.log('verifying the follwing urls:'); + + for (const config of serverlessConfigs) { + if (!config.custom.customDomain) continue; + + const { basePath } = config.custom.customDomain; + const { functions } = config; + + for (const [funName, funConfig] of Object.entries(functions)) { + const event = funConfig.events[0]; + const def = event.http; + if (!def) continue; + + const { authorizer, method, path } = def; + + if (!authorizer) { + missingAuthorizers.push(funName); + } + + const urlToVerify = `https://efcms-${env}.${process.env.EFCMS_DOMAIN}/${basePath}${path}`; + let responseStatus = null; + try { + console.log(` ${urlToVerify}`); + await axios[method.toLowerCase()](urlToVerify); + } catch (err) { + responseStatus = err.response.status; + } + if (responseStatus !== 401) { + no401Response.push(urlToVerify); + } + } + } + + if (missingAuthorizers.length) { + console.log( + `\n\nThe following http functions are missing authorizers: ${missingAuthorizers.join( + ', ', + )}`, + ); + process.exit(1); + } + + if (no401Response.length) { + console.log( + `\n\nThe following urls functions are missing authorizers:\n${no401Response.join( + '\n', + )}`, + ); + process.exit(1); + } +}; + +main().catch(err => { + console.error(err); + process.exit(1); +}); diff --git a/web-client/integration-tests-public/journey/unauthedUserSearchesForOrderByKeyword.js b/web-client/integration-tests-public/journey/unauthedUserSearchesForOrderByKeyword.js index 4674d4f70dd..3103494a308 100644 --- a/web-client/integration-tests-public/journey/unauthedUserSearchesForOrderByKeyword.js +++ b/web-client/integration-tests-public/journey/unauthedUserSearchesForOrderByKeyword.js @@ -1,5 +1,9 @@ +import { refreshElasticsearchIndex } from '../../integration-tests/helpers'; + export default (test, testClient) => { return it('Search for order by keyword', async () => { + await refreshElasticsearchIndex(); + test.setState('advancedSearchForm', { orderSearch: { orderKeyword: 'osteodontolignikeratic', @@ -13,7 +17,7 @@ export default (test, testClient) => { test.setState('advancedSearchForm', { orderSearch: { - orderKeyword: 'dismiss', + orderKeyword: 'dismissed', }, }); diff --git a/web-client/integration-tests-public/journey/unauthedUserSearchesForSealedCaseOrderByKeyword.js b/web-client/integration-tests-public/journey/unauthedUserSearchesForSealedCaseOrderByKeyword.js new file mode 100644 index 00000000000..d41d11e211e --- /dev/null +++ b/web-client/integration-tests-public/journey/unauthedUserSearchesForSealedCaseOrderByKeyword.js @@ -0,0 +1,23 @@ +import { refreshElasticsearchIndex } from '../../integration-tests/helpers'; + +export default (test, testClient) => { + return it('Search for sealed case order by keyword', async () => { + await refreshElasticsearchIndex(); + + test.setState('advancedSearchForm', { + orderSearch: { + orderKeyword: 'dismiss', + }, + }); + + await test.runSequence('submitPublicOrderAdvancedSearchSequence'); + + expect(test.getState('searchResults')).not.toEqual( + expect.arrayContaining([ + expect.objectContaining({ + documentId: testClient.draftOrders[1].documentId, + }), + ]), + ); + }); +}; diff --git a/web-client/integration-tests-public/unauthedUserSearchesForOrder.test.js b/web-client/integration-tests-public/unauthedUserSearchesForOrder.test.js index 0588b284323..52f33e65543 100644 --- a/web-client/integration-tests-public/unauthedUserSearchesForOrder.test.js +++ b/web-client/integration-tests-public/unauthedUserSearchesForOrder.test.js @@ -2,6 +2,7 @@ import { ContactFactory } from '../../shared/src/business/entities/contacts/Cont import { docketClerkAddsDocketEntryFromOrder } from '../integration-tests/journey/docketClerkAddsDocketEntryFromOrder'; import { docketClerkAddsDocketEntryFromOrderOfDismissal } from '../integration-tests/journey/docketClerkAddsDocketEntryFromOrderOfDismissal'; import { docketClerkCreatesAnOrder } from '../integration-tests/journey/docketClerkCreatesAnOrder'; +import { docketClerkSealsCase } from '../integration-tests/journey/docketClerkSealsCase'; import { docketClerkServesOrder } from '../integration-tests/journey/docketClerkServesOrder'; import { loginAs, @@ -12,6 +13,7 @@ import { setupTest } from './helpers'; import unauthedUserInvalidSearchForOrder from './journey/unauthedUserInvalidSearchForOrder'; import unauthedUserNavigatesToPublicSite from './journey/unauthedUserNavigatesToPublicSite'; import unauthedUserSearchesForOrderByKeyword from './journey/unauthedUserSearchesForOrderByKeyword'; +import unauthedUserSearchesForSealedCaseOrderByKeyword from './journey/unauthedUserSearchesForSealedCaseOrderByKeyword'; const test = setupTest(); const testClient = setupTestClient({ @@ -78,3 +80,13 @@ describe('Unauthed user searches for an order by keyword', () => { unauthedUserInvalidSearchForOrder(test); unauthedUserSearchesForOrderByKeyword(test, testClient); }); + +describe('Docket clerk seals case', () => { + loginAs(testClient, 'docketclerk'); + docketClerkSealsCase(testClient); +}); + +describe('Unauthed user searches for an order by keyword and does not see sealed cases', () => { + unauthedUserNavigatesToPublicSite(test); + unauthedUserSearchesForSealedCaseOrderByKeyword(test, testClient); +}); diff --git a/web-client/integration-tests/docketClerkAddsCourtIssuedOrderToDocketRecord.test.js b/web-client/integration-tests/docketClerkAddsCourtIssuedOrderToDocketRecord.test.js index 7ea567a8fbd..52869589711 100644 --- a/web-client/integration-tests/docketClerkAddsCourtIssuedOrderToDocketRecord.test.js +++ b/web-client/integration-tests/docketClerkAddsCourtIssuedOrderToDocketRecord.test.js @@ -1,10 +1,19 @@ -import { fakeFile, loginAs, setupTest } from './helpers'; +import { loginAs, setupTest, uploadPetition } from './helpers'; // docketClerk import { docketClerkAddsDocketEntryFromOrder } from './journey/docketClerkAddsDocketEntryFromOrder'; import { docketClerkAddsDocketEntryFromOrderOfDismissal } from './journey/docketClerkAddsDocketEntryFromOrderOfDismissal'; +import { docketClerkAddsDocketEntryFromOrderWithDate } from './journey/docketClerkAddsDocketEntryFromOrderWithDate'; import { docketClerkCancelsAddDocketEntryFromOrder } from './journey/docketClerkCancelsAddDocketEntryFromOrder'; import { docketClerkCreatesAnOrder } from './journey/docketClerkCreatesAnOrder'; +import { docketClerkEditsDocketEntryFromOrderTypeA } from './journey/docketClerkEditsDocketEntryFromOrderTypeA'; +import { docketClerkEditsDocketEntryFromOrderTypeB } from './journey/docketClerkEditsDocketEntryFromOrderTypeB'; +import { docketClerkEditsDocketEntryFromOrderTypeC } from './journey/docketClerkEditsDocketEntryFromOrderTypeC'; +import { docketClerkEditsDocketEntryFromOrderTypeD } from './journey/docketClerkEditsDocketEntryFromOrderTypeD'; +import { docketClerkEditsDocketEntryFromOrderTypeE } from './journey/docketClerkEditsDocketEntryFromOrderTypeE'; +import { docketClerkEditsDocketEntryFromOrderTypeF } from './journey/docketClerkEditsDocketEntryFromOrderTypeF'; +import { docketClerkEditsDocketEntryFromOrderTypeG } from './journey/docketClerkEditsDocketEntryFromOrderTypeG'; +import { docketClerkEditsDocketEntryFromOrderTypeH } from './journey/docketClerkEditsDocketEntryFromOrderTypeH'; import { docketClerkViewsCaseDetailForCourtIssuedDocketEntry } from './journey/docketClerkViewsCaseDetailForCourtIssuedDocketEntry'; import { docketClerkViewsDraftOrder } from './journey/docketClerkViewsDraftOrder'; import { docketClerkViewsSavedCourtIssuedDocketEntryInProgress } from './journey/docketClerkViewsSavedCourtIssuedDocketEntryInProgress'; @@ -12,10 +21,7 @@ import { docketClerkViewsSavedCourtIssuedDocketEntryInProgress } from './journey import { petitionsClerkViewsCaseDetail } from './journey/petitionsClerkViewsCaseDetail'; import petitionsClerkViewsDocketEntry from './journey/petitionsClerkViewsDocketEntry'; import petitionsClerkViewsDraftOrder from './journey/petitionsClerkViewsDraftOrder'; -// petitioner -import { petitionerChoosesCaseType } from './journey/petitionerChoosesCaseType'; -import { petitionerChoosesProcedureType } from './journey/petitionerChoosesProcedureType'; -import { petitionerCreatesNewCase } from './journey/petitionerCreatesNewCase'; +//petitioner import { petitionerViewsCaseDetail } from './journey/petitionerViewsCaseDetail'; const test = setupTest({ @@ -31,9 +37,11 @@ describe('Docket Clerk Adds Court-Issued Order to Docket Record', () => { }); loginAs(test, 'petitioner'); - petitionerChoosesProcedureType(test, { procedureType: 'Regular' }); - petitionerChoosesCaseType(test); - petitionerCreatesNewCase(test, fakeFile); + it('Create test case', async () => { + const caseDetail = await uploadPetition(test); + + test.docketNumber = caseDetail.docketNumber; + }); loginAs(test, 'docketclerk'); docketClerkCreatesAnOrder(test, { @@ -55,6 +63,14 @@ describe('Docket Clerk Adds Court-Issued Order to Docket Record', () => { docketClerkViewsCaseDetailForCourtIssuedDocketEntry(test); docketClerkViewsDraftOrder(test, 0); docketClerkAddsDocketEntryFromOrder(test, 0); + docketClerkEditsDocketEntryFromOrderTypeA(test, 0); + docketClerkEditsDocketEntryFromOrderTypeB(test, 0); + docketClerkEditsDocketEntryFromOrderTypeC(test, 0); + docketClerkEditsDocketEntryFromOrderTypeD(test, 0); + docketClerkEditsDocketEntryFromOrderTypeE(test, 0); + docketClerkEditsDocketEntryFromOrderTypeF(test, 0); + docketClerkEditsDocketEntryFromOrderTypeG(test, 0); + docketClerkEditsDocketEntryFromOrderTypeH(test, 0); docketClerkViewsCaseDetailForCourtIssuedDocketEntry(test); docketClerkViewsDraftOrder(test, 1); docketClerkCancelsAddDocketEntryFromOrder(test, 1); @@ -62,10 +78,19 @@ describe('Docket Clerk Adds Court-Issued Order to Docket Record', () => { docketClerkAddsDocketEntryFromOrderOfDismissal(test, 1); docketClerkViewsCaseDetailForCourtIssuedDocketEntry(test); docketClerkViewsSavedCourtIssuedDocketEntryInProgress(test, 1); + docketClerkCreatesAnOrder(test, { + documentTitle: 'Order to do something', + eventCode: 'O', + expectedDocumentType: 'Order', + }); + docketClerkAddsDocketEntryFromOrderWithDate(test, 2); loginAs(test, 'petitionsclerk'); petitionsClerkViewsDocketEntry(test, 1); loginAs(test, 'petitioner'); - petitionerViewsCaseDetail(test, { documentCount: 4 }); + petitionerViewsCaseDetail(test, { + docketNumberSuffix: 'L', + documentCount: 5, + }); }); diff --git a/web-client/integration-tests/docketClerkAddsTranscriptToDocketRecord.test.js b/web-client/integration-tests/docketClerkAddsTranscriptToDocketRecord.test.js index dface5d5ccd..5f9b13bfa43 100644 --- a/web-client/integration-tests/docketClerkAddsTranscriptToDocketRecord.test.js +++ b/web-client/integration-tests/docketClerkAddsTranscriptToDocketRecord.test.js @@ -1,17 +1,14 @@ -import { fakeFile, loginAs, setupTest } from './helpers'; -import { formattedCaseDetail as formattedCaseDetailComputed } from '../src/presenter/computeds/formattedCaseDetail'; -import { runCompute } from 'cerebral/test'; -import { withAppContextDecorator } from '../src/withAppContext'; - -// docketClerk import { docketClerkAddsTranscriptDocketEntryFromOrder } from './journey/docketClerkAddsTranscriptDocketEntryFromOrder'; import { docketClerkCreatesAnOrder } from './journey/docketClerkCreatesAnOrder'; import { docketClerkServesOrder } from './journey/docketClerkServesOrder'; import { docketClerkViewsDraftOrder } from './journey/docketClerkViewsDraftOrder'; -// petitioner +import { fakeFile, loginAs, setupTest } from './helpers'; +import { formattedCaseDetail as formattedCaseDetailComputed } from '../src/presenter/computeds/formattedCaseDetail'; import { petitionerChoosesCaseType } from './journey/petitionerChoosesCaseType'; import { petitionerChoosesProcedureType } from './journey/petitionerChoosesProcedureType'; import { petitionerCreatesNewCase } from './journey/petitionerCreatesNewCase'; +import { runCompute } from 'cerebral/test'; +import { withAppContextDecorator } from '../src/withAppContext'; const formattedCaseDetail = withAppContextDecorator( formattedCaseDetailComputed, @@ -41,7 +38,7 @@ describe('Docket Clerk Adds Transcript to Docket Record', () => { expectedDocumentType: 'Order', }); docketClerkViewsDraftOrder(test, 0); - //old transcript that should be available to the user + // old transcript that should be available to the user docketClerkAddsTranscriptDocketEntryFromOrder(test, 0, { day: '01', month: '01', @@ -54,7 +51,7 @@ describe('Docket Clerk Adds Transcript to Docket Record', () => { expectedDocumentType: 'Order', }); docketClerkViewsDraftOrder(test, 1); - //new transcript that should NOT be available to the user + // new transcript that should NOT be available to the user const today = new Date(); docketClerkAddsTranscriptDocketEntryFromOrder(test, 1, { day: today.getDate(), @@ -74,9 +71,9 @@ describe('Docket Clerk Adds Transcript to Docket Record', () => { const transcriptDocuments = formattedCase.formattedDocketEntries.filter( document => document.eventCode === 'TRAN', ); - //first transcript should be available to the user + // first transcript should be available to the user expect(transcriptDocuments[0].showLinkToDocument).toEqual(true); - //second transcript should NOT be available to the user + // second transcript should NOT be available to the user expect(transcriptDocuments[1].showLinkToDocument).toEqual(false); }); }); diff --git a/web-client/integration-tests/docketClerkEditsDocketEntryMeta.test.js b/web-client/integration-tests/docketClerkEditsDocketEntryMeta.test.js index 705da3694f6..91727838ecd 100644 --- a/web-client/integration-tests/docketClerkEditsDocketEntryMeta.test.js +++ b/web-client/integration-tests/docketClerkEditsDocketEntryMeta.test.js @@ -1,19 +1,29 @@ -import { fakeFile, loginAs, setupTest } from './helpers'; +import { fakeFile, loginAs, setupTest, uploadPetition } from './helpers'; // docketClerk import { docketClerkChecksDocketEntryEditLink } from './journey/docketClerkChecksDocketEntryEditLink'; +import { docketClerkCreatesAnOrder } from './journey/docketClerkCreatesAnOrder'; import { docketClerkEditsDocketEntryMeta } from './journey/docketClerkEditsDocketEntryMeta'; import { docketClerkNavigatesToEditDocketEntryMeta } from './journey/docketClerkNavigatesToEditDocketEntryMeta'; +import { docketClerkNavigatesToEditDocketEntryMetaCourtIssued } from './journey/docketClerkNavigatesToEditDocketEntryMetaCourtIssued'; import { docketClerkQCsDocketEntry } from './journey/docketClerkQCsDocketEntry'; +import { docketClerkServesOrder } from './journey/docketClerkServesOrder'; import { docketClerkVerifiesDocketEntryMetaUpdates } from './journey/docketClerkVerifiesDocketEntryMetaUpdates'; +import { docketClerkVerifiesEditCourtIssuedNonstandardFields } from './journey/docketClerkVerifiesEditCourtIssuedNonstandardFields'; // petitioner -import { petitionerChoosesCaseType } from './journey/petitionerChoosesCaseType'; -import { petitionerChoosesProcedureType } from './journey/petitionerChoosesProcedureType'; -import { petitionerCreatesNewCase } from './journey/petitionerCreatesNewCase'; +import { docketClerkAddsDocketEntryFromOrder } from './journey/docketClerkAddsDocketEntryFromOrder'; +import { docketClerkAddsDocketEntryFromOrderOfDismissal } from './journey/docketClerkAddsDocketEntryFromOrderOfDismissal'; +import { docketClerkEditsDocketEntryMetaCourtIssued } from './journey/docketClerkEditsDocketEntryMetaCourtIssued'; +import { docketClerkVerifiesDocketEntryMetaCourtIssuedUpdates } from './journey/docketClerkVerifiesDocketEntryMetaCourtIssuedUpdates'; +import { docketClerkVerifiesEditCourtIssuedNonstandardFieldsWithJudge } from './journey/docketClerkVerifiesEditCourtIssuedNonstandardFieldsWithJudge'; import { petitionerFilesADocumentForCase } from './journey/petitionerFilesADocumentForCase'; -const test = setupTest(); +const test = setupTest({ + useCases: { + loadPDFForSigningInteractor: () => Promise.resolve(null), + }, +}); test.draftOrders = []; describe("Docket Clerk Edits a Docket Entry's Meta", () => { @@ -22,9 +32,10 @@ describe("Docket Clerk Edits a Docket Entry's Meta", () => { }); loginAs(test, 'petitioner'); - petitionerChoosesProcedureType(test, { procedureType: 'Regular' }); - petitionerChoosesCaseType(test); - petitionerCreatesNewCase(test, fakeFile); + it('Create test case', async () => { + const caseDetail = await uploadPetition(test); + test.docketNumber = caseDetail.docketNumber; + }); petitionerFilesADocumentForCase(test, fakeFile); loginAs(test, 'docketclerk'); @@ -35,4 +46,27 @@ describe("Docket Clerk Edits a Docket Entry's Meta", () => { docketClerkNavigatesToEditDocketEntryMeta(test, 3); docketClerkEditsDocketEntryMeta(test); docketClerkVerifiesDocketEntryMetaUpdates(test, 3); + + docketClerkCreatesAnOrder(test, { + documentTitle: 'Order to do something', + eventCode: 'O', + expectedDocumentType: 'Order', + }); + docketClerkAddsDocketEntryFromOrder(test, 0); + docketClerkServesOrder(test, 0); + docketClerkNavigatesToEditDocketEntryMetaCourtIssued(test, 4); + docketClerkEditsDocketEntryMetaCourtIssued(test); + docketClerkVerifiesDocketEntryMetaCourtIssuedUpdates(test, 4); + docketClerkNavigatesToEditDocketEntryMetaCourtIssued(test, 4); + docketClerkVerifiesEditCourtIssuedNonstandardFields(test); + + docketClerkCreatesAnOrder(test, { + documentTitle: 'Order of Dismissal', + eventCode: 'OD', + expectedDocumentType: 'Order of Dismissal', + }); + docketClerkAddsDocketEntryFromOrderOfDismissal(test, 1); + docketClerkServesOrder(test, 1); + docketClerkNavigatesToEditDocketEntryMetaCourtIssued(test, 5); + docketClerkVerifiesEditCourtIssuedNonstandardFieldsWithJudge(test); }); diff --git a/web-client/integration-tests/docketClerkEditsServiceIndicators.test.js b/web-client/integration-tests/docketClerkEditsServiceIndicators.test.js index e7dc8520007..e2bd6383ba4 100644 --- a/web-client/integration-tests/docketClerkEditsServiceIndicators.test.js +++ b/web-client/integration-tests/docketClerkEditsServiceIndicators.test.js @@ -8,7 +8,7 @@ import { docketClerkEditsServiceIndicatorForPractitioner } from './journey/docke import { docketClerkEditsServiceIndicatorForRespondent } from './journey/docketClerkEditsServiceIndicatorForRespondent'; import { docketClerkServesOrderOnPaperParties } from './journey/docketClerkServesOrderOnPaperParties'; import { petitionsClerkAddsPractitionersToCase } from './journey/petitionsClerkAddsPractitionersToCase'; -import petitionsClerkAddsRespondentsToCase from './journey/petitionsClerkAddsRespondentsToCase'; +import { petitionsClerkAddsRespondentsToCase } from './journey/petitionsClerkAddsRespondentsToCase'; import { petitionsClerkViewsCaseDetail } from './journey/petitionsClerkViewsCaseDetail'; const test = setupTest({ diff --git a/web-client/integration-tests/docketClerkOrderAdvancedSearch.test.js b/web-client/integration-tests/docketClerkOrderAdvancedSearch.test.js index 17f9b135417..f7521e5c9ac 100644 --- a/web-client/integration-tests/docketClerkOrderAdvancedSearch.test.js +++ b/web-client/integration-tests/docketClerkOrderAdvancedSearch.test.js @@ -2,6 +2,7 @@ import { OrderSearch } from '../../shared/src/business/entities/orders/OrderSear import { docketClerkAddsDocketEntryFromOrder } from './journey/docketClerkAddsDocketEntryFromOrder'; import { docketClerkAddsDocketEntryFromOrderOfDismissal } from './journey/docketClerkAddsDocketEntryFromOrderOfDismissal'; import { docketClerkCreatesAnOrder } from './journey/docketClerkCreatesAnOrder'; +import { docketClerkSealsCase } from './journey/docketClerkSealsCase'; import { docketClerkServesOrder } from './journey/docketClerkServesOrder'; import { loginAs, setupTest, uploadPetition } from './helpers'; import { refreshElasticsearchIndex } from './helpers'; @@ -18,6 +19,30 @@ describe('docket clerk order advanced search', () => { test.draftOrders = []; }); + const seedData = { + caseCaption: 'Hanan Al Hroub, Petitioner', + caseId: '1a92894e-83a5-48ba-9994-3ada44235deb', + contactPrimary: { + address1: '123 Teachers Way', + city: 'Haifa', + country: 'Palestine', + countryType: 'international', + name: 'Hanan Al Hroub', + postalCode: '123456', + serviceIndicator: 'Paper', + }, + contactSecondary: {}, + docketNumber: '104-20', + docketNumberSuffix: 'R', + documentContents: + 'Déjà vu, this is a seed order filed on Apr 13 at 11:01pm ET', + documentId: '1f1aa3f7-e2e3-43e6-885d-4ce341588c76', + documentTitle: 'Order of Dismissal and Decision Entered, Judge Buch', + filingDate: '2020-04-14T03:01:15.215Z', + signedJudgeName: 'Maurice B. Foley', + }; + + const signedByJudge = 'Maurice B. Foley'; let caseDetail; loginAs(test, 'petitioner'); @@ -58,6 +83,7 @@ describe('docket clerk order advanced search', () => { }); docketClerkAddsDocketEntryFromOrder(test, 3); docketClerkServesOrder(test, 3); + docketClerkSealsCase(test); it('go to advanced order search tab', async () => { await refreshElasticsearchIndex(); @@ -84,10 +110,155 @@ describe('docket clerk order advanced search', () => { expect(test.getState('searchResults')).toEqual([]); }); - it('search for a keyword which is present in served orders', async () => { + it('search for a keyword that is present in served orders', async () => { + test.setState('advancedSearchForm', { + orderSearch: { + orderKeyword: 'dismissal', + }, + }); + + await test.runSequence('submitOrderAdvancedSearchSequence'); + + expect(test.getState('searchResults')).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + documentId: test.draftOrders[2].documentId, + isSealed: true, + }), + ]), + ); + expect(test.getState('searchResults')).not.toEqual( + expect.arrayContaining([ + expect.objectContaining({ documentId: test.draftOrders[1].documentId }), + ]), + ); + }); + + it('search for a docket number that is not present in any served orders', async () => { + const docketNumberNoOrders = '999-99'; + + test.setState('advancedSearchForm', { + orderSearch: { + docketNumber: docketNumberNoOrders, + orderKeyword: 'dismissal', + }, + }); + + await test.runSequence('submitOrderAdvancedSearchSequence'); + + expect(test.getState('searchResults')).toEqual([]); + }); + + it('search for a docket number that is present in served orders', async () => { + test.setState('advancedSearchForm', { + orderSearch: { + docketNumber: caseDetail.docketNumber, + orderKeyword: 'dismissal', + }, + }); + + await test.runSequence('submitOrderAdvancedSearchSequence'); + + expect(test.getState('searchResults')).toEqual( + expect.arrayContaining([ + expect.objectContaining({ documentId: test.draftOrders[2].documentId }), + ]), + ); + expect(test.getState('searchResults')).not.toEqual( + expect.arrayContaining([ + expect.objectContaining({ documentId: test.draftOrders[1].documentId }), + ]), + ); + }); + + it('clears search fields', async () => { + test.setState('advancedSearchForm', { + orderSearch: { + caseTitleOrPetitioner: caseDetail.caseCaption, + docketNumber: caseDetail.docketNumber, + orderKeyword: 'dismissal', + }, + }); + + await test.runSequence('clearAdvancedSearchFormSequence', { + formType: 'orderSearch', + }); + + expect(test.getState('advancedSearchForm.orderSearch')).toEqual({ + orderKeyword: '', + }); + }); + + it('search for a case title that is not present in any served orders', async () => { + const caseCaptionNoOrders = 'abcdefghijk'; + + test.setState('advancedSearchForm', { + orderSearch: { + caseTitleOrPetitioner: caseCaptionNoOrders, + orderKeyword: 'dismissal', + }, + }); + + await test.runSequence('submitOrderAdvancedSearchSequence'); + + expect(test.getState('searchResults')).toEqual([]); + }); + + it('search for a case title that is present in served orders', async () => { + test.setState('advancedSearchForm', { + orderSearch: { + caseTitleOrPetitioner: caseDetail.caseCaption, + orderKeyword: 'dismissal', + }, + }); + + await test.runSequence('submitOrderAdvancedSearchSequence'); + + expect(test.getState('searchResults')).toEqual( + expect.arrayContaining([ + expect.objectContaining({ documentId: test.draftOrders[2].documentId }), + ]), + ); + expect(test.getState('searchResults')).not.toEqual( + expect.arrayContaining([ + expect.objectContaining({ documentId: test.draftOrders[1].documentId }), + ]), + ); + }); + + it('search for a date range that does not contain served orders', async () => { + test.setState('advancedSearchForm', { + orderSearch: { + endDateDay: '03', + endDateMonth: '01', + endDateYear: '2005', + orderKeyword: 'dismissal', + startDateDay: '01', + startDateMonth: '01', + startDateYear: '2005', + }, + }); + + await test.runSequence('submitOrderAdvancedSearchSequence'); + + expect(test.getState('searchResults')).toEqual([]); + }); + + it('search for a date range that contains served orders', async () => { + const currentDate = new Date(); + const orderCreationYear = currentDate.getUTCFullYear(); + const orderCreationMonth = currentDate.getUTCMonth(); + const orderCreationDate = currentDate.getDate(); + test.setState('advancedSearchForm', { orderSearch: { + endDateDay: orderCreationDate, + endDateMonth: orderCreationMonth + 1, + endDateYear: orderCreationYear, orderKeyword: 'dismissal', + startDateDay: orderCreationDate, + startDateMonth: orderCreationMonth - 1, + startDateYear: orderCreationYear, }, }); @@ -104,4 +275,94 @@ describe('docket clerk order advanced search', () => { ]), ); }); + + it('search for a judge that has not signed any served orders', async () => { + const invalidJudge = 'Judge Exotic'; + + test.setState('advancedSearchForm', { + orderSearch: { + judge: invalidJudge, + orderKeyword: 'dismissal', + }, + }); + + await test.runSequence('submitOrderAdvancedSearchSequence'); + + expect(test.getState('searchResults')).toEqual([]); + }); + + it('search for a judge that has signed served orders', async () => { + test.setState('advancedSearchForm', { + orderSearch: { + judge: signedByJudge, + orderKeyword: 'dismissal', + }, + }); + + await test.runSequence('submitOrderAdvancedSearchSequence'); + + expect(test.getState('searchResults')).toEqual( + expect.arrayContaining([ + expect.objectContaining({ documentId: seedData.documentId }), + ]), + ); + expect(test.getState('searchResults')).not.toEqual( + expect.arrayContaining([ + expect.objectContaining({ documentId: test.draftOrders[2].documentId }), + ]), + ); + }); + + it('includes the number of pages present in each document in the search results', async () => { + test.setState('advancedSearchForm', { + orderSearch: { + orderKeyword: 'Order of Dismissal Entered', + }, + }); + + await test.runSequence('submitOrderAdvancedSearchSequence'); + + expect(test.getState('searchResults')).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + numberOfPages: 1, + }), + ]), + ); + }); + + it('clears validation errors when switching tabs', async () => { + test.setState('advancedSearchForm', { + orderSearch: {}, + }); + + await test.runSequence('submitOrderAdvancedSearchSequence'); + + expect(test.getState('alertError')).toEqual({ + messages: ['Enter a keyword or phrase'], + title: 'Please correct the following errors:', + }); + + await test.runSequence('advancedSearchTabChangeSequence'); + + expect(test.getState('alertError')).not.toBeDefined(); + }); + + it('includes the number of pages present in each document in the search results', async () => { + test.setState('advancedSearchForm', { + orderSearch: { + orderKeyword: 'Order of Dismissal Entered', + }, + }); + + await test.runSequence('submitOrderAdvancedSearchSequence'); + + expect(test.getState('searchResults')).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + numberOfPages: 1, + }), + ]), + ); + }); }); diff --git a/web-client/integration-tests/docketClerkSealsCase.test.js b/web-client/integration-tests/docketClerkSealsCase.test.js index b8df83a9223..9e5d7a2df3d 100644 --- a/web-client/integration-tests/docketClerkSealsCase.test.js +++ b/web-client/integration-tests/docketClerkSealsCase.test.js @@ -5,8 +5,8 @@ import { associatedUserAdvancedSearchForSealedCase } from './journey/associatedU import { associatedUserViewsCaseDetailForSealedCase } from './journey/associatedUserViewsCaseDetailForSealedCase'; import { docketClerkSealsCase } from './journey/docketClerkSealsCase'; import { petitionsClerkAddsPractitionersToCase } from './journey/petitionsClerkAddsPractitionersToCase'; +import { petitionsClerkAddsRespondentsToCase } from './journey/petitionsClerkAddsRespondentsToCase'; import { petitionsClerkViewsCaseDetail } from './journey/petitionsClerkViewsCaseDetail'; -import petitionsClerkAddsRespondentsToCase from './journey/petitionsClerkAddsRespondentsToCase'; import unassociatedUserAdvancedSearchForSealedCase from './journey/unassociatedUserAdvancedSearchForSealedCase'; import unassociatedUserViewsCaseDetailForSealedCase from './journey/unassociatedUserViewsCaseDetailForSealedCase'; diff --git a/web-client/integration-tests/externalUserOrderAdvancedSearch.test.js b/web-client/integration-tests/externalUserOrderAdvancedSearch.test.js new file mode 100644 index 00000000000..3ec2471f3f6 --- /dev/null +++ b/web-client/integration-tests/externalUserOrderAdvancedSearch.test.js @@ -0,0 +1,103 @@ +import { associatedUserSearchesForServedOrder } from './journey/associatedUserSearchesForServedOrder'; +import { docketClerkAddsDocketEntryFromOrder } from './journey/docketClerkAddsDocketEntryFromOrder'; +import { docketClerkCreatesAnOrder } from './journey/docketClerkCreatesAnOrder'; +import { docketClerkSealsCase } from './journey/docketClerkSealsCase'; +import { docketClerkServesOrder } from './journey/docketClerkServesOrder'; +import { loginAs, refreshElasticsearchIndex, setupTest } from './helpers'; +import { petitionsClerkAddsPractitionersToCase } from './journey/petitionsClerkAddsPractitionersToCase'; +import { petitionsClerkAddsRespondentsToCase } from './journey/petitionsClerkAddsRespondentsToCase'; +import { petitionsClerkViewsCaseDetail } from './journey/petitionsClerkViewsCaseDetail'; +import { unassociatedUserSearchesForServedOrderInSealedCase } from './journey/unassociatedUserSearchesForServedOrderInSealedCase'; +import { unassociatedUserSearchesForServedOrderInUnsealedCase } from './journey/unassociatedUserSearchesForServedOrderInUnsealedCase'; +import { uploadPetition } from './helpers'; + +const test = setupTest({ + useCases: { + loadPDFForSigningInteractor: () => Promise.resolve(null), + }, +}); +test.draftOrders = []; + +describe('external users perform an advanced search for orders', () => { + beforeAll(() => { + jest.setTimeout(30000); + }); + + loginAs(test, 'petitioner'); + it('Create test case #1', async () => { + const caseDetail = await uploadPetition(test); + test.docketNumber = caseDetail.docketNumber; + }); + + loginAs(test, 'petitionsclerk'); + petitionsClerkViewsCaseDetail(test); + petitionsClerkAddsPractitionersToCase(test, true); + petitionsClerkAddsRespondentsToCase(test); + + loginAs(test, 'docketclerk'); + docketClerkCreatesAnOrder(test, { + documentContents: 'this is a thing that I can search for, Jiminy Cricket', + documentTitle: 'Order', + eventCode: 'O', + expectedDocumentType: 'Order', + }); + docketClerkAddsDocketEntryFromOrder(test, 0); + docketClerkServesOrder(test, 0); + it('refresh elasticsearch index', async () => { + await refreshElasticsearchIndex(); + }); + + loginAs(test, 'privatePractitioner'); + associatedUserSearchesForServedOrder(test, { + draftOrderIndex: 0, + orderKeyword: 'Jiminy Cricket', + }); + + loginAs(test, 'privatePractitioner1'); + unassociatedUserSearchesForServedOrderInUnsealedCase(test, { + draftOrderIndex: 0, + orderKeyword: 'Jiminy Cricket', + }); + + loginAs(test, 'irsPractitioner'); + associatedUserSearchesForServedOrder(test, { + draftOrderIndex: 0, + orderKeyword: 'Jiminy Cricket', + }); + + loginAs(test, 'irsPractitioner2'); + unassociatedUserSearchesForServedOrderInUnsealedCase(test, { + draftOrderIndex: 0, + orderKeyword: 'Jiminy Cricket', + }); + + loginAs(test, 'docketclerk'); + docketClerkSealsCase(test); + it('refresh elasticsearch index', async () => { + await refreshElasticsearchIndex(); + }); + + loginAs(test, 'privatePractitioner'); + associatedUserSearchesForServedOrder(test, { + draftOrderIndex: 0, + orderKeyword: 'Jiminy Cricket', + }); + + loginAs(test, 'privatePractitioner1'); + unassociatedUserSearchesForServedOrderInSealedCase(test, { + draftOrderIndex: 0, + orderKeyword: 'Jiminy Cricket', + }); + + loginAs(test, 'irsPractitioner'); + associatedUserSearchesForServedOrder(test, { + draftOrderIndex: 0, + orderKeyword: 'Jiminy Cricket', + }); + + loginAs(test, 'irsPractitioner2'); + unassociatedUserSearchesForServedOrderInSealedCase(test, { + draftOrderIndex: 0, + orderKeyword: 'Jiminy Cricket', + }); +}); diff --git a/web-client/integration-tests/helpers.js b/web-client/integration-tests/helpers.js index 4405c9d9663..a76f6620891 100644 --- a/web-client/integration-tests/helpers.js +++ b/web-client/integration-tests/helpers.js @@ -9,6 +9,7 @@ import { revokeObjectURL, router, } from '../src/router'; +import { elasticsearchIndexes } from '../../web-api/elasticsearch/elasticsearch-indexes'; import { formattedWorkQueue as formattedWorkQueueComputed } from '../src/presenter/computeds/formattedWorkQueue'; import { getScannerInterface } from '../../shared/src/persistence/dynamsoft/getScannerMockInterface'; import { @@ -383,7 +384,9 @@ export const loginAs = (test, user) => { export const setupTest = ({ useCases = {} } = {}) => { let test; global.FormData = FormData; - global.Blob = () => {}; + global.Blob = () => { + return fakeFile; + }; global.File = () => { return fakeFile; }; @@ -411,6 +414,12 @@ export const setupTest = ({ useCases = {} } = {}) => { getScanner: getScannerInterface, }); + presenter.providers.applicationContext = applicationContext; + const { initialize: initializeSocketProvider, start, stop } = socketProvider({ + socketRouter, + }); + presenter.providers.socket = { start, stop }; + test = CerebralTest(presenter); test.getSequence = name => async obj => await test.runSequence(name, obj); test.closeSocket = stop; @@ -449,12 +458,6 @@ export const setupTest = ({ useCases = {} } = {}) => { location: {}, }; - presenter.providers.applicationContext = applicationContext; - const { initialize: initializeSocketProvider, start, stop } = socketProvider({ - socketRouter, - }); - presenter.providers.socket = { start, stop }; - const originalUseCases = applicationContext.getUseCases(); presenter.providers.applicationContext.getUseCases = () => { return { @@ -558,7 +561,11 @@ export const wait = time => { }; export const refreshElasticsearchIndex = async () => { - await axios.post('http://localhost:9200/efcms/_refresh'); + await Promise.all( + elasticsearchIndexes.map(async index => { + await axios.post(`http://localhost:9200/${index}/_refresh`); + }), + ); return await wait(1500); }; diff --git a/web-client/integration-tests/journey/associatedUserSearchesForServedOrder.js b/web-client/integration-tests/journey/associatedUserSearchesForServedOrder.js new file mode 100644 index 00000000000..776a564e45d --- /dev/null +++ b/web-client/integration-tests/journey/associatedUserSearchesForServedOrder.js @@ -0,0 +1,19 @@ +export const associatedUserSearchesForServedOrder = (test, options) => { + return it('associated user searches for served order', async () => { + test.setState('advancedSearchForm', { + orderSearch: { + orderKeyword: options.orderKeyword, + }, + }); + + await test.runSequence('submitOrderAdvancedSearchSequence'); + + expect(test.getState('searchResults')).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + documentId: test.draftOrders[options.draftOrderIndex].documentId, + }), + ]), + ); + }); +}; diff --git a/web-client/integration-tests/journey/docketClerkAddsDocketEntryFromOrderWithDate.js b/web-client/integration-tests/journey/docketClerkAddsDocketEntryFromOrderWithDate.js new file mode 100644 index 00000000000..d8606952fb7 --- /dev/null +++ b/web-client/integration-tests/journey/docketClerkAddsDocketEntryFromOrderWithDate.js @@ -0,0 +1,66 @@ +import { formattedCaseDetail } from '../../src/presenter/computeds/formattedCaseDetail'; +import { runCompute } from 'cerebral/test'; +import { withAppContextDecorator } from '../../src/withAppContext'; + +export const docketClerkAddsDocketEntryFromOrderWithDate = ( + test, + draftOrderIndex, +) => { + return it(`Docket Clerk adds a docket entry from the given order ${draftOrderIndex} including a nonstandard type with date`, async () => { + const caseDetailFormatted = runCompute( + withAppContextDecorator(formattedCaseDetail), + { + state: test.getState(), + }, + ); + + const { documentId } = test.draftOrders[draftOrderIndex]; + + const draftOrderDocument = caseDetailFormatted.draftDocuments.find( + doc => doc.documentId === documentId, + ); + + expect(draftOrderDocument).toBeTruthy(); + + await test.runSequence('gotoAddCourtIssuedDocketEntrySequence', { + docketNumber: test.docketNumber, + documentId: draftOrderDocument.documentId, + }); + + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'eventCode', + value: 'OF', + }); + + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'freeText', + value: 'something', + }); + + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'month', + value: '2', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'day', + value: '2', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'year', + value: '2050', + }); + + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'serviceStamp', + value: 'Served', + }); + + await test.runSequence('submitCourtIssuedDocketEntrySequence'); + + expect(test.getState('validationErrors')).toEqual({}); + + expect(test.getState('alertSuccess').message).toEqual( + 'Entry added to Docket Record.', + ); + }); +}; diff --git a/web-client/integration-tests/journey/docketClerkCreatesAnOrder.js b/web-client/integration-tests/journey/docketClerkCreatesAnOrder.js index c8ecea8d05d..67bbe92058d 100644 --- a/web-client/integration-tests/journey/docketClerkCreatesAnOrder.js +++ b/web-client/integration-tests/journey/docketClerkCreatesAnOrder.js @@ -37,6 +37,10 @@ export const docketClerkCreatesAnOrder = (test, data) => { key: 'richText', value: 'Some order content', }); + await test.runSequence('updateFormValueSequence', { + key: 'documentContents', + value: data.documentContents || 'Some order content', + }); await test.runSequence('submitCourtIssuedOrderSequence'); diff --git a/web-client/integration-tests/journey/docketClerkEditsDocketEntryFromOrderTypeA.js b/web-client/integration-tests/journey/docketClerkEditsDocketEntryFromOrderTypeA.js new file mode 100644 index 00000000000..40b407dc177 --- /dev/null +++ b/web-client/integration-tests/journey/docketClerkEditsDocketEntryFromOrderTypeA.js @@ -0,0 +1,91 @@ +import { formattedCaseDetail } from '../../src/presenter/computeds/formattedCaseDetail'; +import { runCompute } from 'cerebral/test'; +import { withAppContextDecorator } from '../../src/withAppContext'; + +export const docketClerkEditsDocketEntryFromOrderTypeA = ( + test, + draftOrderIndex, +) => { + return it(`Docket Clerk edits a docket entry from the given order ${draftOrderIndex} with nonstandard type A`, async () => { + let caseDetailFormatted; + + caseDetailFormatted = runCompute( + withAppContextDecorator(formattedCaseDetail), + { + state: test.getState(), + }, + ); + + const { documentId } = test.draftOrders[draftOrderIndex]; + + const orderDocument = caseDetailFormatted.documents.find( + doc => doc.documentId === documentId, + ); + + expect(orderDocument).toBeTruthy(); + + await test.runSequence('gotoEditCourtIssuedDocketEntrySequence', { + docketNumber: test.docketNumber, + documentId: orderDocument.documentId, + }); + + // Type A + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'eventCode', + value: 'WRIT', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'documentType', + value: 'Writ of Habeas Corpus Ad Testificandum', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'documentTitle', + value: 'Writ of Habeas Corpus Ad Testificandum [anything]', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'scenario', + value: 'Type A', + }); + + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'freeText', + value: 'Some free text', + }); + + await test.runSequence('submitCourtIssuedDocketEntrySequence'); + + expect(test.getState('validationErrors')).toEqual({}); + + caseDetailFormatted = runCompute( + withAppContextDecorator(formattedCaseDetail), + { + state: test.getState(), + }, + ); + + const updatedOrderDocument = caseDetailFormatted.documents.find( + doc => doc.documentId === documentId, + ); + + expect(updatedOrderDocument).toMatchObject({ + documentTitle: 'Writ of Habeas Corpus Ad Testificandum Some free text', + documentType: 'Writ of Habeas Corpus Ad Testificandum', + eventCode: 'WRIT', + freeText: 'Some free text', + }); + + await test.runSequence('gotoEditCourtIssuedDocketEntrySequence', { + docketNumber: test.docketNumber, + documentId: orderDocument.documentId, + }); + + expect(test.getState('form')).toMatchObject({ + documentTitle: 'Writ of Habeas Corpus Ad Testificandum Some free text', + documentType: 'Writ of Habeas Corpus Ad Testificandum', + eventCode: 'WRIT', + freeText: 'Some free text', + generatedDocumentTitle: + 'Writ of Habeas Corpus Ad Testificandum Some free text', + }); + }); +}; diff --git a/web-client/integration-tests/journey/docketClerkEditsDocketEntryFromOrderTypeB.js b/web-client/integration-tests/journey/docketClerkEditsDocketEntryFromOrderTypeB.js new file mode 100644 index 00000000000..20a5a4ea3b7 --- /dev/null +++ b/web-client/integration-tests/journey/docketClerkEditsDocketEntryFromOrderTypeB.js @@ -0,0 +1,104 @@ +import { VALIDATION_ERROR_MESSAGES } from '../../../shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentConstants'; +import { formattedCaseDetail } from '../../src/presenter/computeds/formattedCaseDetail'; +import { runCompute } from 'cerebral/test'; +import { withAppContextDecorator } from '../../src/withAppContext'; + +export const docketClerkEditsDocketEntryFromOrderTypeB = ( + test, + draftOrderIndex, +) => { + return it(`Docket Clerk edits a docket entry from the given order ${draftOrderIndex} with nonstandard type B`, async () => { + let caseDetailFormatted; + + caseDetailFormatted = runCompute( + withAppContextDecorator(formattedCaseDetail), + { + state: test.getState(), + }, + ); + + const { documentId } = test.draftOrders[draftOrderIndex]; + + const orderDocument = caseDetailFormatted.documents.find( + doc => doc.documentId === documentId, + ); + + expect(orderDocument).toBeTruthy(); + + await test.runSequence('gotoEditCourtIssuedDocketEntrySequence', { + docketNumber: test.docketNumber, + documentId: orderDocument.documentId, + }); + + // Type B + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'eventCode', + value: 'TCOP', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'documentType', + value: 'TCOP - T.C. Opinion', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'documentTitle', + value: 'T.C. Opinion [judge] [anything]', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'scenario', + value: 'Type B', + }); + + await test.runSequence('submitCourtIssuedDocketEntrySequence'); + + expect(test.getState('validationErrors')).toEqual({ + judge: VALIDATION_ERROR_MESSAGES.judge, + }); + + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'judge', + value: 'Judge Pugh', + }); + + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'freeText', + value: 'freeeeee text', + }); + + await test.runSequence('submitCourtIssuedDocketEntrySequence'); + + expect(test.getState('validationErrors')).toEqual({}); + + caseDetailFormatted = runCompute( + withAppContextDecorator(formattedCaseDetail), + { + state: test.getState(), + }, + ); + + const updatedOrderDocument = caseDetailFormatted.documents.find( + doc => doc.documentId === documentId, + ); + + expect(updatedOrderDocument).toMatchObject({ + documentTitle: 'T.C. Opinion Judge Pugh freeeeee text', + documentType: 'TCOP - T.C. Opinion', + eventCode: 'TCOP', + freeText: 'freeeeee text', + judge: 'Judge Pugh', + }); + + await test.runSequence('gotoEditCourtIssuedDocketEntrySequence', { + docketNumber: test.docketNumber, + documentId: orderDocument.documentId, + }); + + expect(test.getState('form')).toMatchObject({ + documentTitle: 'T.C. Opinion Judge Pugh freeeeee text', + documentType: 'TCOP - T.C. Opinion', + eventCode: 'TCOP', + freeText: 'freeeeee text', + generatedDocumentTitle: 'T.C. Opinion Judge Pugh freeeeee text', + judge: 'Judge Pugh', + }); + }); +}; diff --git a/web-client/integration-tests/journey/docketClerkEditsDocketEntryFromOrderTypeC.js b/web-client/integration-tests/journey/docketClerkEditsDocketEntryFromOrderTypeC.js new file mode 100644 index 00000000000..449ab8b594d --- /dev/null +++ b/web-client/integration-tests/journey/docketClerkEditsDocketEntryFromOrderTypeC.js @@ -0,0 +1,103 @@ +import { VALIDATION_ERROR_MESSAGES } from '../../../shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentConstants'; +import { formattedCaseDetail } from '../../src/presenter/computeds/formattedCaseDetail'; +import { runCompute } from 'cerebral/test'; +import { withAppContextDecorator } from '../../src/withAppContext'; + +export const docketClerkEditsDocketEntryFromOrderTypeC = ( + test, + draftOrderIndex, +) => { + return it(`Docket Clerk edits a docket entry from the given order ${draftOrderIndex} with nonstandard type C`, async () => { + let caseDetailFormatted; + + caseDetailFormatted = runCompute( + withAppContextDecorator(formattedCaseDetail), + { + state: test.getState(), + }, + ); + + const { documentId } = test.draftOrders[draftOrderIndex]; + + const orderDocument = caseDetailFormatted.documents.find( + doc => doc.documentId === documentId, + ); + + expect(orderDocument).toBeTruthy(); + + await test.runSequence('gotoEditCourtIssuedDocketEntrySequence', { + docketNumber: test.docketNumber, + documentId: orderDocument.documentId, + }); + + // Type C + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'eventCode', + value: 'OAR', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'documentType', + value: 'OAR - Order that the letter "R" is added to the Docket number', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'documentTitle', + value: + 'Order that the letter "R" is added to the Docket number [Docket number]', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'scenario', + value: 'Type C', + }); + + await test.runSequence('submitCourtIssuedDocketEntrySequence'); + + expect(test.getState('validationErrors')).toEqual({ + docketNumbers: VALIDATION_ERROR_MESSAGES.docketNumbers, + }); + + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'docketNumbers', + value: '123-45', + }); + + await test.runSequence('submitCourtIssuedDocketEntrySequence'); + + expect(test.getState('validationErrors')).toEqual({}); + + caseDetailFormatted = runCompute( + withAppContextDecorator(formattedCaseDetail), + { + state: test.getState(), + }, + ); + + const updatedOrderDocument = caseDetailFormatted.documents.find( + doc => doc.documentId === documentId, + ); + + expect(updatedOrderDocument).toMatchObject({ + docketNumbers: '123-45', + documentTitle: + 'Order that the letter "R" is added to the Docket number 123-45', + documentType: + 'OAR - Order that the letter "R" is added to the Docket number', + eventCode: 'OAR', + }); + + await test.runSequence('gotoEditCourtIssuedDocketEntrySequence', { + docketNumber: test.docketNumber, + documentId: orderDocument.documentId, + }); + + expect(test.getState('form')).toMatchObject({ + docketNumbers: '123-45', + documentTitle: + 'Order that the letter "R" is added to the Docket number 123-45', + documentType: + 'OAR - Order that the letter "R" is added to the Docket number', + eventCode: 'OAR', + generatedDocumentTitle: + 'Order that the letter "R" is added to the Docket number 123-45', + }); + }); +}; diff --git a/web-client/integration-tests/journey/docketClerkEditsDocketEntryFromOrderTypeD.js b/web-client/integration-tests/journey/docketClerkEditsDocketEntryFromOrderTypeD.js new file mode 100644 index 00000000000..4a6c445df39 --- /dev/null +++ b/web-client/integration-tests/journey/docketClerkEditsDocketEntryFromOrderTypeD.js @@ -0,0 +1,119 @@ +import { VALIDATION_ERROR_MESSAGES } from '../../../shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentConstants'; +import { formattedCaseDetail } from '../../src/presenter/computeds/formattedCaseDetail'; +import { runCompute } from 'cerebral/test'; +import { withAppContextDecorator } from '../../src/withAppContext'; + +export const docketClerkEditsDocketEntryFromOrderTypeD = ( + test, + draftOrderIndex, +) => { + return it(`Docket Clerk edits a docket entry from the given order ${draftOrderIndex} with nonstandard type D`, async () => { + let caseDetailFormatted; + + caseDetailFormatted = runCompute( + withAppContextDecorator(formattedCaseDetail), + { + state: test.getState(), + }, + ); + + const { documentId } = test.draftOrders[draftOrderIndex]; + + const orderDocument = caseDetailFormatted.documents.find( + doc => doc.documentId === documentId, + ); + + expect(orderDocument).toBeTruthy(); + + await test.runSequence('gotoEditCourtIssuedDocketEntrySequence', { + docketNumber: test.docketNumber, + documentId: orderDocument.documentId, + }); + + // Type D + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'eventCode', + value: 'OF', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'documentType', + value: 'OF - Order for Filing Fee', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'documentTitle', + value: 'Order for Filing Fee on [Date] [Anything]', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'scenario', + value: 'Type D', + }); + + await test.runSequence('submitCourtIssuedDocketEntrySequence'); + + expect(test.getState('validationErrors')).toEqual({ + date: VALIDATION_ERROR_MESSAGES.date[2], + }); + + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'month', + value: '1', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'day', + value: '1', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'year', + value: '2002', + }); + + await test.runSequence('submitCourtIssuedDocketEntrySequence'); + + expect(test.getState('validationErrors')).toEqual({ + date: VALIDATION_ERROR_MESSAGES.date[0].message, + }); + + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'year', + value: '2050', + }); + + await test.runSequence('submitCourtIssuedDocketEntrySequence'); + + expect(test.getState('validationErrors')).toEqual({}); + + caseDetailFormatted = runCompute( + withAppContextDecorator(formattedCaseDetail), + { + state: test.getState(), + }, + ); + + const updatedOrderDocument = caseDetailFormatted.documents.find( + doc => doc.documentId === documentId, + ); + + expect(updatedOrderDocument).toMatchObject({ + date: '2050-01-01', + documentTitle: 'Order for Filing Fee on 01-01-2050', + documentType: 'OF - Order for Filing Fee', + eventCode: 'OF', + }); + + await test.runSequence('gotoEditCourtIssuedDocketEntrySequence', { + docketNumber: test.docketNumber, + documentId: orderDocument.documentId, + }); + + expect(test.getState('form')).toMatchObject({ + date: '2050-01-01', + day: '1', + documentTitle: 'Order for Filing Fee on 01-01-2050', + documentType: 'OF - Order for Filing Fee', + eventCode: 'OF', + generatedDocumentTitle: 'Order for Filing Fee on 01-01-2050', + month: '1', + year: '2050', + }); + }); +}; diff --git a/web-client/integration-tests/journey/docketClerkEditsDocketEntryFromOrderTypeE.js b/web-client/integration-tests/journey/docketClerkEditsDocketEntryFromOrderTypeE.js new file mode 100644 index 00000000000..99af57cee2b --- /dev/null +++ b/web-client/integration-tests/journey/docketClerkEditsDocketEntryFromOrderTypeE.js @@ -0,0 +1,125 @@ +import { VALIDATION_ERROR_MESSAGES } from '../../../shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentConstants'; +import { formattedCaseDetail } from '../../src/presenter/computeds/formattedCaseDetail'; +import { runCompute } from 'cerebral/test'; +import { withAppContextDecorator } from '../../src/withAppContext'; + +export const docketClerkEditsDocketEntryFromOrderTypeE = ( + test, + draftOrderIndex, +) => { + return it(`Docket Clerk edits a docket entry from the given order ${draftOrderIndex} with nonstandard type E`, async () => { + let caseDetailFormatted; + + caseDetailFormatted = runCompute( + withAppContextDecorator(formattedCaseDetail), + { + state: test.getState(), + }, + ); + + const { documentId } = test.draftOrders[draftOrderIndex]; + + const orderDocument = caseDetailFormatted.documents.find( + doc => doc.documentId === documentId, + ); + + expect(orderDocument).toBeTruthy(); + + await test.runSequence('gotoEditCourtIssuedDocketEntrySequence', { + docketNumber: test.docketNumber, + documentId: orderDocument.documentId, + }); + + // Type E + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'eventCode', + value: 'OFFX', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'documentType', + value: 'OFFX - Order time is extended for petr(s) to pay the filing fee', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'documentTitle', + value: + 'Order time is extended to [Date] for petr(s) to pay the filing fee', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'scenario', + value: 'Type E', + }); + + await test.runSequence('submitCourtIssuedDocketEntrySequence'); + + expect(test.getState('validationErrors')).toEqual({ + date: VALIDATION_ERROR_MESSAGES.date[2], + }); + + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'month', + value: '1', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'day', + value: '1', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'year', + value: '2002', + }); + + await test.runSequence('submitCourtIssuedDocketEntrySequence'); + + expect(test.getState('validationErrors')).toEqual({ + date: VALIDATION_ERROR_MESSAGES.date[0].message, + }); + + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'year', + value: '2050', + }); + + await test.runSequence('submitCourtIssuedDocketEntrySequence'); + + expect(test.getState('validationErrors')).toEqual({}); + + caseDetailFormatted = runCompute( + withAppContextDecorator(formattedCaseDetail), + { + state: test.getState(), + }, + ); + + const updatedOrderDocument = caseDetailFormatted.documents.find( + doc => doc.documentId === documentId, + ); + + expect(updatedOrderDocument).toMatchObject({ + date: '2050-01-01', + documentTitle: + 'Order time is extended to 01-01-2050 for petr(s) to pay the filing fee', + documentType: + 'OFFX - Order time is extended for petr(s) to pay the filing fee', + eventCode: 'OFFX', + }); + + await test.runSequence('gotoEditCourtIssuedDocketEntrySequence', { + docketNumber: test.docketNumber, + documentId: orderDocument.documentId, + }); + + expect(test.getState('form')).toMatchObject({ + date: '2050-01-01', + day: '1', + documentTitle: + 'Order time is extended to 01-01-2050 for petr(s) to pay the filing fee', + documentType: + 'OFFX - Order time is extended for petr(s) to pay the filing fee', + eventCode: 'OFFX', + generatedDocumentTitle: + 'Order time is extended to 01-01-2050 for petr(s) to pay the filing fee', + month: '1', + year: '2050', + }); + }); +}; diff --git a/web-client/integration-tests/journey/docketClerkEditsDocketEntryFromOrderTypeF.js b/web-client/integration-tests/journey/docketClerkEditsDocketEntryFromOrderTypeF.js new file mode 100644 index 00000000000..c8da7d46e11 --- /dev/null +++ b/web-client/integration-tests/journey/docketClerkEditsDocketEntryFromOrderTypeF.js @@ -0,0 +1,106 @@ +import { VALIDATION_ERROR_MESSAGES } from '../../../shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentConstants'; +import { formattedCaseDetail } from '../../src/presenter/computeds/formattedCaseDetail'; +import { runCompute } from 'cerebral/test'; +import { withAppContextDecorator } from '../../src/withAppContext'; + +export const docketClerkEditsDocketEntryFromOrderTypeF = ( + test, + draftOrderIndex, +) => { + return it(`Docket Clerk edits a docket entry from the given order ${draftOrderIndex} with nonstandard type F`, async () => { + let caseDetailFormatted; + + caseDetailFormatted = runCompute( + withAppContextDecorator(formattedCaseDetail), + { + state: test.getState(), + }, + ); + + const { documentId } = test.draftOrders[draftOrderIndex]; + + const orderDocument = caseDetailFormatted.documents.find( + doc => doc.documentId === documentId, + ); + + expect(orderDocument).toBeTruthy(); + + await test.runSequence('gotoEditCourtIssuedDocketEntrySequence', { + docketNumber: test.docketNumber, + documentId: orderDocument.documentId, + }); + + // Type F + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'eventCode', + value: 'FTRL', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'documentType', + value: 'FTRL - Further Trial before ...', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'documentTitle', + value: 'Further Trial before [Judge] at [Place]', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'scenario', + value: 'Type F', + }); + + await test.runSequence('submitCourtIssuedDocketEntrySequence'); + + expect(test.getState('validationErrors')).toEqual({ + judge: VALIDATION_ERROR_MESSAGES.judge, + trialLocation: VALIDATION_ERROR_MESSAGES.trialLocation, + }); + + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'judge', + value: 'Judge Ashford', + }); + + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'trialLocation', + value: 'Boise, Idaho', + }); + + await test.runSequence('submitCourtIssuedDocketEntrySequence'); + + expect(test.getState('validationErrors')).toEqual({}); + + caseDetailFormatted = runCompute( + withAppContextDecorator(formattedCaseDetail), + { + state: test.getState(), + }, + ); + + const updatedOrderDocument = caseDetailFormatted.documents.find( + doc => doc.documentId === documentId, + ); + + expect(updatedOrderDocument).toMatchObject({ + documentTitle: 'Further Trial before Judge Ashford at Boise, Idaho', + documentType: 'FTRL - Further Trial before ...', + eventCode: 'FTRL', + judge: 'Judge Ashford', + trialLocation: 'Boise, Idaho', + }); + + await test.runSequence('gotoEditCourtIssuedDocketEntrySequence', { + docketNumber: test.docketNumber, + documentId: orderDocument.documentId, + }); + + expect(test.getState('form')).toMatchObject({ + documentTitle: 'Further Trial before Judge Ashford at Boise, Idaho', + documentType: 'FTRL - Further Trial before ...', + eventCode: 'FTRL', + generatedDocumentTitle: + 'Further Trial before Judge Ashford at Boise, Idaho', + judge: 'Judge Ashford', + trialLocation: 'Boise, Idaho', + }); + }); +}; diff --git a/web-client/integration-tests/journey/docketClerkEditsDocketEntryFromOrderTypeG.js b/web-client/integration-tests/journey/docketClerkEditsDocketEntryFromOrderTypeG.js new file mode 100644 index 00000000000..2fa04deacd3 --- /dev/null +++ b/web-client/integration-tests/journey/docketClerkEditsDocketEntryFromOrderTypeG.js @@ -0,0 +1,118 @@ +import { VALIDATION_ERROR_MESSAGES } from '../../../shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentConstants'; +import { formattedCaseDetail } from '../../src/presenter/computeds/formattedCaseDetail'; +import { runCompute } from 'cerebral/test'; +import { withAppContextDecorator } from '../../src/withAppContext'; + +export const docketClerkEditsDocketEntryFromOrderTypeG = ( + test, + draftOrderIndex, +) => { + return it(`Docket Clerk edits a docket entry from the given order ${draftOrderIndex} with nonstandard type G`, async () => { + let caseDetailFormatted; + + caseDetailFormatted = runCompute( + withAppContextDecorator(formattedCaseDetail), + { + state: test.getState(), + }, + ); + + const { documentId } = test.draftOrders[draftOrderIndex]; + + const orderDocument = caseDetailFormatted.documents.find( + doc => doc.documentId === documentId, + ); + + expect(orderDocument).toBeTruthy(); + + await test.runSequence('gotoEditCourtIssuedDocketEntrySequence', { + docketNumber: test.docketNumber, + documentId: orderDocument.documentId, + }); + + // Type G + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'eventCode', + value: 'NTD', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'documentType', + value: 'NTD - Notice of Trial', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'documentTitle', + value: 'Notice of Trial on [Date] at [Place]', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'scenario', + value: 'Type G', + }); + + expect(test.getState('form.trialLocation')).toBeUndefined(); + + await test.runSequence('submitCourtIssuedDocketEntrySequence'); + + expect(test.getState('validationErrors')).toEqual({ + date: VALIDATION_ERROR_MESSAGES.date[2], + trialLocation: VALIDATION_ERROR_MESSAGES.trialLocation, + }); + + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'month', + value: '1', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'day', + value: '1', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'year', + value: '2002', + }); + + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'trialLocation', + value: 'Boise, Idaho', + }); + + await test.runSequence('submitCourtIssuedDocketEntrySequence'); + + expect(test.getState('validationErrors')).toEqual({}); + + caseDetailFormatted = runCompute( + withAppContextDecorator(formattedCaseDetail), + { + state: test.getState(), + }, + ); + + const updatedOrderDocument = caseDetailFormatted.documents.find( + doc => doc.documentId === documentId, + ); + + expect(updatedOrderDocument).toMatchObject({ + date: '2002-01-01', + documentTitle: 'Notice of Trial on 01-01-2002 at Boise, Idaho', + documentType: 'NTD - Notice of Trial', + eventCode: 'NTD', + trialLocation: 'Boise, Idaho', + }); + + await test.runSequence('gotoEditCourtIssuedDocketEntrySequence', { + docketNumber: test.docketNumber, + documentId: orderDocument.documentId, + }); + + expect(test.getState('form')).toMatchObject({ + date: '2002-01-01', + day: '1', + documentTitle: 'Notice of Trial on 01-01-2002 at Boise, Idaho', + documentType: 'NTD - Notice of Trial', + eventCode: 'NTD', + generatedDocumentTitle: 'Notice of Trial on 01-01-2002 at Boise, Idaho', + month: '1', + trialLocation: 'Boise, Idaho', + year: '2002', + }); + }); +}; diff --git a/web-client/integration-tests/journey/docketClerkEditsDocketEntryFromOrderTypeH.js b/web-client/integration-tests/journey/docketClerkEditsDocketEntryFromOrderTypeH.js new file mode 100644 index 00000000000..55c47eb3e47 --- /dev/null +++ b/web-client/integration-tests/journey/docketClerkEditsDocketEntryFromOrderTypeH.js @@ -0,0 +1,129 @@ +import { VALIDATION_ERROR_MESSAGES } from '../../../shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentConstants'; +import { formattedCaseDetail } from '../../src/presenter/computeds/formattedCaseDetail'; +import { runCompute } from 'cerebral/test'; +import { withAppContextDecorator } from '../../src/withAppContext'; + +export const docketClerkEditsDocketEntryFromOrderTypeH = ( + test, + draftOrderIndex, +) => { + return it(`Docket Clerk edits a docket entry from the given order ${draftOrderIndex} with nonstandard type H`, async () => { + let caseDetailFormatted; + + caseDetailFormatted = runCompute( + withAppContextDecorator(formattedCaseDetail), + { + state: test.getState(), + }, + ); + + const { documentId } = test.draftOrders[draftOrderIndex]; + + const orderDocument = caseDetailFormatted.documents.find( + doc => doc.documentId === documentId, + ); + + expect(orderDocument).toBeTruthy(); + + await test.runSequence('gotoEditCourtIssuedDocketEntrySequence', { + docketNumber: test.docketNumber, + documentId: orderDocument.documentId, + }); + + // Type H + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'eventCode', + value: 'TRAN', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'documentType', + value: 'TRAN - Transcript', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'documentTitle', + value: 'Transcript of [anything] on [date]', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'scenario', + value: 'Type H', + }); + + expect(test.getState('form.trialLocation')).toBeUndefined(); + + await test.runSequence('submitCourtIssuedDocketEntrySequence'); + + expect(test.getState('validationErrors')).toEqual({ + date: VALIDATION_ERROR_MESSAGES.date[2], + freeText: VALIDATION_ERROR_MESSAGES.freeText, + }); + + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'month', + value: '1', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'day', + value: '1', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'year', + value: '2050', + }); + + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'freeText', + value: 'this is free text', + }); + + await test.runSequence('submitCourtIssuedDocketEntrySequence'); + + expect(test.getState('validationErrors')).toEqual({ + date: VALIDATION_ERROR_MESSAGES.date[1].message, + }); + + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'year', + value: '2018', + }); + + await test.runSequence('submitCourtIssuedDocketEntrySequence'); + + expect(test.getState('validationErrors')).toEqual({}); + + caseDetailFormatted = runCompute( + withAppContextDecorator(formattedCaseDetail), + { + state: test.getState(), + }, + ); + + const updatedOrderDocument = caseDetailFormatted.documents.find( + doc => doc.documentId === documentId, + ); + + expect(updatedOrderDocument).toMatchObject({ + date: '2018-01-01', + documentTitle: 'Transcript of this is free text on 01-01-2018', + documentType: 'TRAN - Transcript', + eventCode: 'TRAN', + freeText: 'this is free text', + }); + + await test.runSequence('gotoEditCourtIssuedDocketEntrySequence', { + docketNumber: test.docketNumber, + documentId: orderDocument.documentId, + }); + + expect(test.getState('form')).toMatchObject({ + date: '2018-01-01', + day: '1', + documentTitle: 'Transcript of this is free text on 01-01-2018', + documentType: 'TRAN - Transcript', + eventCode: 'TRAN', + freeText: 'this is free text', + generatedDocumentTitle: 'Transcript of this is free text on 01-01-2018', + month: '1', + year: '2018', + }); + }); +}; diff --git a/web-client/integration-tests/journey/docketClerkEditsDocketEntryMetaCourtIssued.js b/web-client/integration-tests/journey/docketClerkEditsDocketEntryMetaCourtIssued.js new file mode 100644 index 00000000000..0a0d3b3728c --- /dev/null +++ b/web-client/integration-tests/journey/docketClerkEditsDocketEntryMetaCourtIssued.js @@ -0,0 +1,73 @@ +import { VALIDATION_ERROR_MESSAGES } from '../../../shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentConstants'; + +export const docketClerkEditsDocketEntryMetaCourtIssued = test => { + return it('docket clerk edits docket entry meta for a court-issued document', async () => { + expect(test.getState('currentPage')).toEqual('EditDocketEntryMeta'); + + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'eventCode', + value: 'OAP', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'documentType', + value: 'OAP - Order for Amended Petition', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'documentTitle', + value: 'Order for Amended Petition on [Date] [Anything]', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'scenario', + value: 'Type D', + }); + + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'freeText', + value: 'be free', + }); + + await test.runSequence('submitEditDocketEntryMetaSequence', { + caseId: test.docketNumber, + }); + + expect(test.getState('validationErrors')).toEqual({ + date: VALIDATION_ERROR_MESSAGES.date[2], + }); + + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'month', + value: '4', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'day', + value: '4', + }); + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'year', + value: '2020', + }); + + await test.runSequence('submitEditDocketEntryMetaSequence', { + caseId: test.docketNumber, + }); + + expect(test.getState('validationErrors')).toEqual({ + date: VALIDATION_ERROR_MESSAGES.date[0].message, + }); + + await test.runSequence('updateCourtIssuedDocketEntryFormValueSequence', { + key: 'year', + value: '2050', + }); + + await test.runSequence('submitEditDocketEntryMetaSequence', { + caseId: test.docketNumber, + }); + + expect(test.getState('validationErrors')).toEqual({}); + + expect(test.getState('alertSuccess')).toMatchObject({ + message: 'Docket entry changes saved.', + }); + }); +}; diff --git a/web-client/integration-tests/journey/docketClerkNavigatesToEditDocketEntryMetaCourtIssued.js b/web-client/integration-tests/journey/docketClerkNavigatesToEditDocketEntryMetaCourtIssued.js new file mode 100644 index 00000000000..083b5e298ed --- /dev/null +++ b/web-client/integration-tests/journey/docketClerkNavigatesToEditDocketEntryMetaCourtIssued.js @@ -0,0 +1,14 @@ +export const docketClerkNavigatesToEditDocketEntryMetaCourtIssued = ( + test, + docketRecordIndex = 1, +) => { + it('docket clerk navigates to page to edit docket entry meta for a court-issued document', async () => { + await test.runSequence('gotoEditDocketEntryMetaSequence', { + docketNumber: test.docketNumber, + docketRecordIndex, + }); + + expect(test.getState('currentPage')).toEqual('EditDocketEntryMeta'); + expect(test.getState('screenMetadata.editType')).toEqual('CourtIssued'); + }); +}; diff --git a/web-client/integration-tests/journey/docketClerkServesOrderWithPaperService.js b/web-client/integration-tests/journey/docketClerkServesOrderWithPaperService.js index 5c5795cb1a4..feca6655208 100644 --- a/web-client/integration-tests/journey/docketClerkServesOrderWithPaperService.js +++ b/web-client/integration-tests/journey/docketClerkServesOrderWithPaperService.js @@ -50,7 +50,7 @@ export const docketClerkServesOrderWithPaperService = ( ]); await test.runSequence('serveCourtIssuedDocumentSequence'); - expect(test.getState('currentPage')).toEqual('PrintPreview'); + expect(test.getState('currentPage')).toEqual('PrintPaperService'); expect(test.getState('pdfPreviewUrl')).toBeDefined(); }); }; diff --git a/web-client/integration-tests/journey/docketClerkVerifiesDocketEntryMetaCourtIssuedUpdates.js b/web-client/integration-tests/journey/docketClerkVerifiesDocketEntryMetaCourtIssuedUpdates.js new file mode 100644 index 00000000000..0770d1e05d6 --- /dev/null +++ b/web-client/integration-tests/journey/docketClerkVerifiesDocketEntryMetaCourtIssuedUpdates.js @@ -0,0 +1,21 @@ +export const docketClerkVerifiesDocketEntryMetaCourtIssuedUpdates = ( + test, + docketRecordIndex = 1, +) => { + return it('docket clerk verifies docket entry meta update for court-issued doc', async () => { + await test.runSequence('gotoCaseDetailSequence', { + docketNumber: test.docketNumber, + }); + + expect(test.getState('currentPage')).toEqual('CaseDetailInternal'); + + const caseDetail = test.getState('caseDetail'); + const docketRecordEntry = caseDetail.docketRecord.find( + entry => entry.index === docketRecordIndex, + ); + + expect(docketRecordEntry.description).toEqual( + 'Order for Amended Petition on 04-04-2050 be free', + ); + }); +}; diff --git a/web-client/integration-tests/journey/docketClerkVerifiesDocketEntryMetaUpdates.js b/web-client/integration-tests/journey/docketClerkVerifiesDocketEntryMetaUpdates.js index da3db9e6afc..90a8e2a4cdf 100644 --- a/web-client/integration-tests/journey/docketClerkVerifiesDocketEntryMetaUpdates.js +++ b/web-client/integration-tests/journey/docketClerkVerifiesDocketEntryMetaUpdates.js @@ -15,9 +15,7 @@ export const docketClerkVerifiesDocketEntryMetaUpdates = ( ); expect(docketRecordEntry.filingDate).toEqual('2020-01-04T05:00:00.000Z'); - expect(docketRecordEntry.filedBy).toEqual( - 'Resp. & Petr. Daenerys Stormborn of the House Targaryen, First of Her Name, the Unburnt, Queen of the Andals and the First Men, Khaleesi of the Great Grass Sea, Breaker of Chains, and Mother of Dragons', - ); + expect(docketRecordEntry.filedBy).toEqual('Resp. & Petr. Mona Schultz'); expect(docketRecordEntry.description).toEqual( 'First Request for Admissions', ); diff --git a/web-client/integration-tests/journey/docketClerkVerifiesEditCourtIssuedNonstandardFields.js b/web-client/integration-tests/journey/docketClerkVerifiesEditCourtIssuedNonstandardFields.js new file mode 100644 index 00000000000..7956bad519a --- /dev/null +++ b/web-client/integration-tests/journey/docketClerkVerifiesEditCourtIssuedNonstandardFields.js @@ -0,0 +1,10 @@ +export const docketClerkVerifiesEditCourtIssuedNonstandardFields = test => { + return it('docket clerk verifies that nonstandard fields are displayed on court-issued docket entry edit form', async () => { + expect(test.getState('currentPage')).toEqual('EditDocketEntryMeta'); + + expect(test.getState('form.freeText')).toEqual('be free'); + expect(test.getState('form.month')).toEqual('4'); + expect(test.getState('form.day')).toEqual('4'); + expect(test.getState('form.year')).toEqual('2050'); + }); +}; diff --git a/web-client/integration-tests/journey/docketClerkVerifiesEditCourtIssuedNonstandardFieldsWithJudge.js b/web-client/integration-tests/journey/docketClerkVerifiesEditCourtIssuedNonstandardFieldsWithJudge.js new file mode 100644 index 00000000000..af8d71986fe --- /dev/null +++ b/web-client/integration-tests/journey/docketClerkVerifiesEditCourtIssuedNonstandardFieldsWithJudge.js @@ -0,0 +1,8 @@ +export const docketClerkVerifiesEditCourtIssuedNonstandardFieldsWithJudge = test => { + return it('docket clerk verifies that nonstandard judge field is populated on court-issued docket entry edit form', async () => { + expect(test.getState('currentPage')).toEqual('EditDocketEntryMeta'); + + expect(test.getState('form.freeText')).toEqual('for Something'); + expect(test.getState('form.judge')).toEqual('Judge Buch'); + }); +}; diff --git a/web-client/integration-tests/journey/externalUserSearchesForOrder.js b/web-client/integration-tests/journey/externalUserSearchesForOrder.js new file mode 100644 index 00000000000..4154b18faaf --- /dev/null +++ b/web-client/integration-tests/journey/externalUserSearchesForOrder.js @@ -0,0 +1,24 @@ +import { formattedCaseDetail } from '../../src/presenter/computeds/formattedCaseDetail'; +import { runCompute } from 'cerebral/test'; +import { wait } from '../helpers'; +import { withAppContextDecorator } from '../../src/withAppContext'; + +export const externalUserSearchesForOrder = (test, options) => { + return it('external user searches for an order', async () => { + test.setState('advancedSearchForm', { + orderSearch: { + orderKeyword: 'onomatopoeia', + }, + }); + + await test.runSequence('submitOrderAdvancedSearchSequence'); + + expect(test.getState('searchResults')).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + documentId: test.draftOrders[0].documentId, + }), + ]), + ); + }); +}; diff --git a/web-client/integration-tests/journey/judgeAddsNotesFromWorkingCopyCaseList.js b/web-client/integration-tests/journey/judgeAddsNotesFromWorkingCopyCaseList.js index f9b7f3b5d17..1b864d7c834 100644 --- a/web-client/integration-tests/journey/judgeAddsNotesFromWorkingCopyCaseList.js +++ b/web-client/integration-tests/journey/judgeAddsNotesFromWorkingCopyCaseList.js @@ -24,8 +24,8 @@ export const judgeAddsNotesFromWorkingCopyCaseList = test => { }); expect(test.getState('modal')).toEqual({ - caseCaptionNames: 'Mona Schultz', caseId, + caseTitle: 'Mona Schultz', notes: undefined, showModal: 'AddEditUserCaseNoteModal', }); @@ -36,8 +36,8 @@ export const judgeAddsNotesFromWorkingCopyCaseList = test => { }); expect(test.getState('modal')).toEqual({ - caseCaptionNames: 'Mona Schultz', caseId, + caseTitle: 'Mona Schultz', notes: 'this is a note added from the modal', showModal: 'AddEditUserCaseNoteModal', }); diff --git a/web-client/integration-tests/journey/petitionerViewsCaseDetailAfterFilingDocument.js b/web-client/integration-tests/journey/petitionerViewsCaseDetailAfterFilingDocument.js index e753a2fa12c..5e7e36de6d1 100644 --- a/web-client/integration-tests/journey/petitionerViewsCaseDetailAfterFilingDocument.js +++ b/web-client/integration-tests/journey/petitionerViewsCaseDetailAfterFilingDocument.js @@ -41,22 +41,18 @@ export const petitionerViewsCaseDetailAfterFilingDocument = ( expect.objectContaining({ eventCode: 'M014', servedAt: expect.anything(), - status: 'served', }), expect.objectContaining({ eventCode: 'AFF', servedAt: expect.anything(), - status: 'served', }), expect.objectContaining({ eventCode: 'MISL', servedAt: expect.anything(), - status: 'served', }), expect.objectContaining({ eventCode: 'MISL', servedAt: expect.anything(), - status: 'served', }), ]), ); diff --git a/web-client/integration-tests/journey/petitionsClerkAddsRespondentsToCase.js b/web-client/integration-tests/journey/petitionsClerkAddsRespondentsToCase.js index 40086bd4811..88d22759a96 100644 --- a/web-client/integration-tests/journey/petitionsClerkAddsRespondentsToCase.js +++ b/web-client/integration-tests/journey/petitionsClerkAddsRespondentsToCase.js @@ -6,7 +6,7 @@ const formattedCaseDetail = withAppContextDecorator( formattedCaseDetailComputed, ); -export default test => { +export const petitionsClerkAddsRespondentsToCase = test => { return it('Petitions clerk manually adds multiple irsPractitioners to case', async () => { expect(test.getState('caseDetail.irsPractitioners')).toEqual([]); diff --git a/web-client/integration-tests/journey/petitionsClerkCompletesAndSetsTrialSession.js b/web-client/integration-tests/journey/petitionsClerkCompletesAndSetsTrialSession.js index f399d83ca79..1beb28e216e 100644 --- a/web-client/integration-tests/journey/petitionsClerkCompletesAndSetsTrialSession.js +++ b/web-client/integration-tests/journey/petitionsClerkCompletesAndSetsTrialSession.js @@ -11,8 +11,7 @@ export default (test, overrides = {}) => { await test.runSequence('openSetCalendarModalSequence'); expect(test.getState('alertWarning')).toEqual({ - message: - 'Provide an address and a judge to set this trial session.', + message: 'Provide an address and a judge to set this trial session.', }); await test.runSequence('updateTrialSessionFormDataSequence', { @@ -53,10 +52,9 @@ export default (test, overrides = {}) => { await wait(1000); // we need to wait for some reason if (overrides.hasPaper) { - expect(test.getState('currentPage')).toEqual('SimplePdfPreviewPage'); + expect(test.getState('currentPage')).toEqual('PrintPaperService'); expect(test.getState('alertWarning')).toEqual({ - message: - 'Print and mail all paper service documents now.', + message: 'Print and mail all paper service documents now.', }); } else { expect(test.getState('currentPage')).toEqual('TrialSessionDetail'); diff --git a/web-client/integration-tests/journey/petitionsClerkCreatesNewCase.js b/web-client/integration-tests/journey/petitionsClerkCreatesNewCase.js index 49db9239976..fd15dda616a 100644 --- a/web-client/integration-tests/journey/petitionsClerkCreatesNewCase.js +++ b/web-client/integration-tests/journey/petitionsClerkCreatesNewCase.js @@ -8,7 +8,7 @@ export default (test, fakeFile, trialLocation = 'Birmingham, Alabama') => { await test.runSequence('gotoStartCaseWizardSequence'); expect(test.getState('form.hasVerifiedIrsNotice')).toEqual(false); - await test.runSequence('reviewPetitionFromPaperSequence'); + await test.runSequence('submitPetitionFromPaperSequence'); expect(test.getState('alertError.title')).toEqual( 'Please correct the following errors on the page:', @@ -59,7 +59,7 @@ export default (test, fakeFile, trialLocation = 'Birmingham, Alabama') => { value: trialLocation, }); - await test.runSequence('reviewPetitionFromPaperSequence'); + await test.runSequence('submitPetitionFromPaperSequence'); expect( test.getState('validationErrors.requestForPlaceOfTrialFile'), @@ -105,7 +105,7 @@ export default (test, fakeFile, trialLocation = 'Birmingham, Alabama') => { value: 1, }); - await test.runSequence('reviewPetitionFromPaperSequence'); + await test.runSequence('submitPetitionFromPaperSequence'); expect( test.getState('validationErrors.requestForPlaceOfTrialFile'), @@ -186,11 +186,11 @@ export default (test, fakeFile, trialLocation = 'Birmingham, Alabama') => { expect(test.getState('alertError')).toBeUndefined(); expect(test.getState('validationErrors')).toEqual({}); - await test.runSequence('reviewPetitionFromPaperSequence'); + await test.runSequence('submitPetitionFromPaperSequence'); - expect(test.getState('currentPage')).toEqual('ReviewPetitionFromPaper'); + expect(test.getState('currentPage')).toEqual('ReviewSavedPetition'); - await test.runSequence('createCaseFromPaperAndServeToIrsSequence'); + await test.runSequence('serveCaseToIrsSequence'); await test.runSequence('gotoCaseDetailSequence'); diff --git a/web-client/integration-tests/journey/petitionsClerkCreatesNewCaseAndSavesForLater.js b/web-client/integration-tests/journey/petitionsClerkCreatesNewCaseAndSavesForLater.js deleted file mode 100644 index 081eba8219f..00000000000 --- a/web-client/integration-tests/journey/petitionsClerkCreatesNewCaseAndSavesForLater.js +++ /dev/null @@ -1,596 +0,0 @@ -import { Case } from '../../../shared/src/business/entities/cases/Case'; -import { CaseInternal } from '../../../shared/src/business/entities/cases/CaseInternal'; -import { ContactFactory } from '../../../shared/src/business/entities/contacts/ContactFactory'; - -export const petitionsClerkCreatesNewCaseAndSavesForLater = ( - test, - fakeFile, - trialLocation = 'Birmingham, Alabama', -) => { - const primaryContactName = { - key: 'contactPrimary.name', - value: 'Shawn Johnson', - }; - - const formValues = [ - { - key: 'dateReceivedMonth', - value: '01', - }, - { - key: 'dateReceivedDay', - value: '01', - }, - { - key: 'dateReceivedYear', - value: '2001', - }, - { - key: 'mailingDate', - value: 'Some Day', - }, - { - key: 'petitionFile', - value: fakeFile, - }, - { - key: 'petitionFileSize', - value: 1, - }, - { - key: 'stinFile', - value: fakeFile, - }, - { - key: 'stinFileSize', - value: 1, - }, - { - key: 'odsFile', - value: fakeFile, - }, - { - key: 'odsFileSize', - value: 1, - }, - { - key: 'ownershipDisclosureFile', - value: fakeFile, - }, - { - key: 'ownershipDisclosureFileSize', - value: 1, - }, - { - key: 'requestForPlaceOfTrialFile', - value: fakeFile, - }, - { - key: 'requestForPlaceOfTrialFileSize', - value: 1, - }, - { - key: 'applicationForWaiverOfFilingFeeFile', - value: fakeFile, - }, - { - key: 'applicationForWaiverOfFilingFeeFileSize', - value: 1, - }, - { - key: 'preferredTrialCity', - value: trialLocation, - }, - { - key: 'procedureType', - value: 'Small', - }, - { - key: 'caseType', - value: 'Deficiency', - }, - { - key: 'partyType', - value: ContactFactory.PARTY_TYPES.petitionerDeceasedSpouse, - }, - { - key: 'contactPrimary.countryType', - value: 'international', - }, - { - key: 'contactPrimary.country', - value: 'Switzerland', - }, - primaryContactName, - { - key: 'contactPrimary.address1', - value: '123 Abc Ln', - }, - { - key: 'contactPrimary.city', - value: 'Cityville', - }, - { - key: 'contactPrimary.postalCode', - value: '23-skidoo', - }, - { - key: 'contactPrimary.email', - value: 'test@example.com', - }, - { - key: 'contactPrimary.phone', - value: '1234567890', - }, - { - key: 'contactSecondary.name', - value: 'Julius Lenhart', - }, - { - key: 'contactSecondary.inCareOf', - value: 'Nora Stanton Barney', - }, - { - key: 'petitionPaymentStatus', - value: Case.PAYMENT_STATUS.WAIVED, - }, - { - key: 'paymentDateWaivedDay', - value: '05', - }, - { - key: 'paymentDateWaivedMonth', - value: '05', - }, - { - key: 'paymentDateWaivedYear', - value: '2005', - }, - ]; - - it('should default to parties tab when creating a new case', async () => { - await test.runSequence('gotoStartCaseWizardSequence'); - await test.runSequence('reviewPetitionFromPaperSequence'); - - expect(test.getState('currentPage')).toEqual('StartCaseInternal'); - expect(test.getState('currentViewMetadata.startCaseInternal.tab')).toBe( - 'partyInfo', - ); - }); - - it('should default to Regular procedureType when creating a new case', async () => { - expect(test.getState('form.procedureType')).toEqual( - CaseInternal.DEFAULT_PROCEDURE_TYPE, - ); - }); - - it('should generate case caption from primary and secondary contact information', async () => { - for (const item of formValues) { - if (item.key === 'partyType') { - await test.runSequence( - 'updateStartCaseInternalPartyTypeSequence', - item, - ); - } else if (item.key === 'petitionPaymentStatus') { - await test.runSequence('updatePetitionPaymentFormValueSequence', item); - } else { - await test.runSequence('updateFormValueSequence', item); - } - } - - await test.runSequence('updateFormValueAndSecondaryContactInfoSequence', { - key: 'useSameAsPrimary', - value: true, - }); - await test.runSequence( - 'updateFormValueAndInternalCaseCaptionSequence', - primaryContactName, - ); - await test.runSequence('validatePetitionFromPaperSequence'); - - expect(test.getState('form.caseCaption')).toBe( - 'Shawn Johnson & Julius Lenhart, Deceased, Shawn Johnson, Surviving Spouse, Petitioners', - ); - expect(test.getState('form.contactSecondary.address1')).toBe( - test.getState('form.contactPrimary.address1'), - ); - expect(test.getState('form.contactSecondary.city')).toBe( - test.getState('form.contactPrimary.city'), - ); - expect(test.getState('form.contactSecondary.country')).toBe( - test.getState('form.contactPrimary.country'), - ); - expect(test.getState('form.contactSecondary.postalCode')).toBe( - test.getState('form.contactPrimary.postalCode'), - ); - expect(test.getState('form.contactSecondary.email')).toBe( - test.getState('form.contactPrimary.email'), - ); - expect(test.getState('form.contactSecondary.phone')).toBe( - test.getState('form.contactPrimary.phone'), - ); - expect(test.getState('form.contactSecondary.inCareOf')).toBe( - 'Nora Stanton Barney', - ); - }); - - it('should regenerate case caption when primary contact name is changed', async () => { - await test.runSequence('updateFormValueAndInternalCaseCaptionSequence', { - key: 'contactPrimary.name', - value: 'Ada Lovelace', - }); - - expect(test.getState('form.caseCaption')).toBe( - 'Ada Lovelace & Julius Lenhart, Deceased, Ada Lovelace, Surviving Spouse, Petitioners', - ); - - const updatedCaseCaption = 'Ada Lovelace is awesome'; - await test.runSequence('updateFormValueSequence', { - key: 'caseCaption', - value: updatedCaseCaption, - }); - - expect(test.getState('form.caseCaption')).toBe(updatedCaseCaption); - }); - - it('should validate when all required information has been provided', async () => { - await test.runSequence('updateFormValueSequence', { - key: 'petitionFile', - value: fakeFile, - }); - await test.runSequence('updateFormValueSequence', { - key: 'stinFile', - value: fakeFile, - }); - - expect(test.getState('alertError')).toBeUndefined(); - expect(test.getState('validationErrors')).toEqual({}); - }); - - it('should navigate to review screen when case information has been validated', async () => { - await test.runSequence('reviewPetitionFromPaperSequence'); - - expect(test.getState('currentPage')).toEqual('ReviewPetitionFromPaper'); - }); - - it('should route to the party info tab when user selects to edit party info', async () => { - await navigateToStartCaseInternalPartiesTab(test); - }); - - it('should route to the case info tab when user selects to edit case info', async () => { - await test.runSequence('goBackToStartCaseInternalSequence', { - tab: 'caseInfo', - }); - - expect(test.getState('currentPage')).toEqual('StartCaseInternal'); - expect(test.getState('currentViewMetadata.startCaseInternal.tab')).toBe( - 'caseInfo', - ); - }); - - it('should update case caption on the review screen when it has been edited', async () => { - await test.runSequence('updateFormValueSequence', { - key: 'caseCaption', - value: 'One fish, two fish', - }); - - await test.runSequence('reviewPetitionFromPaperSequence'); - - expect(test.getState('currentPage')).toEqual('ReviewPetitionFromPaper'); - expect(test.getState('form.caseCaption')).toBe('One fish, two fish'); - }); - - it('should route to the irs notice tab when user selects to edit irs notice info', async () => { - await test.runSequence('goBackToStartCaseInternalSequence', { - tab: 'irsNotice', - }); - - expect(test.getState('currentPage')).toEqual('StartCaseInternal'); - expect(test.getState('currentViewMetadata.startCaseInternal.tab')).toBe( - 'irsNotice', - ); - }); - - it('should update case type on the review screen when when it has been edited', async () => { - await test.runSequence('updateFormValueSequence', { - key: 'caseType', - value: Case.CASE_TYPES_MAP.interestAbatement, - }); - - await test.runSequence('reviewPetitionFromPaperSequence'); - - expect(test.getState('currentPage')).toEqual('ReviewPetitionFromPaper'); - expect(test.getState('form.caseType')).toBe( - Case.CASE_TYPES_MAP.interestAbatement, - ); - }); - - it('should default to the party info tab when editing an in progress case', async () => { - await navigateToStartCaseInternalPartiesTab(test); - }); - - it('should update stin file on the review screen when it has been changed', async () => { - fakeFile.name = 'differentFakeFile.pdf'; - await test.runSequence('updateFormValueSequence', { - key: 'stinFile', - value: fakeFile, - }); - - await test.runSequence('reviewPetitionFromPaperSequence'); - - expect(test.getState('currentPage')).toEqual('ReviewPetitionFromPaper'); - expect(test.getState('form.stinFile').name).toBe('differentFakeFile.pdf'); - }); - - it('should display a preview of the uploaded petition file', async () => { - await test.runSequence('openPdfPreviewModalSequence', { - file: test.getState('form.petitionFile'), - modalId: 'PDFPreviewModal-petitionFile', - }); - expect(test.getState('modal.showModal')).toBe( - 'PDFPreviewModal-petitionFile', - ); - await test.runSequence('dismissModalSequence'); - expect(test.getState('modal.showModal')).toBeUndefined(); - }); - - it('should display a preview of the uploaded stin file', async () => { - await test.runSequence('openPdfPreviewModalSequence', { - file: test.getState('form.stinFile'), - modalId: 'PDFPreviewModal-stinFile', - }); - expect(test.getState('modal.showModal')).toBe('PDFPreviewModal-stinFile'); - await test.runSequence('dismissModalSequence'); - expect(test.getState('modal.showModal')).toBeUndefined(); - }); - - it('should display a preview of the uploaded ods file', async () => { - await test.runSequence('openPdfPreviewModalSequence', { - file: test.getState('form.odsFile'), - modalId: 'PDFPreviewModal-odsFile', - }); - expect(test.getState('modal.showModal')).toBe('PDFPreviewModal-odsFile'); - await test.runSequence('dismissModalSequence'); - expect(test.getState('modal.showModal')).toBeUndefined(); - }); - - it('should allow deletion of an uploaded petition pdf', async () => { - await test.runSequence('goBackToStartCaseInternalSequence', { - tab: 'partyInfo', - }); - expect(test.getState('currentPage')).toEqual('StartCaseInternal'); - - await test.runSequence('openConfirmDeletePDFModalSequence'); - await test.runSequence('removeScannedPdfSequence'); - expect(test.getState('form.petitionFile')).toBeUndefined(); - }); - - it('should upload a new petition file', async () => { - await test.runSequence('updateFormValueSequence', { - key: 'petitionFile', - value: fakeFile, - }); - - await test.runSequence('updateFormValueSequence', { - key: 'petitionFileSize', - value: 1, - }); - - await test.runSequence('reviewPetitionFromPaperSequence'); - expect(test.getState('currentPage')).toEqual('ReviewPetitionFromPaper'); - expect(test.getState('form.petitionFile')).toBe(fakeFile); - }); - - it('should allow deletion of an uploaded statement of identification pdf', async () => { - await test.runSequence('goBackToStartCaseInternalSequence', { - tab: 'partyInfo', - }); - expect(test.getState('currentPage')).toEqual('StartCaseInternal'); - - await test.setState( - 'currentViewMetadata.documentSelectedForScan', - 'stinFile', - ); - await test.runSequence('openConfirmDeletePDFModalSequence'); - await test.runSequence('removeScannedPdfSequence'); - expect(test.getState('form.stinFile')).toBeUndefined(); - }); - - it('should upload a new statement of identification file', async () => { - await test.runSequence('updateFormValueSequence', { - key: 'stinFile', - value: fakeFile, - }); - - await test.runSequence('updateFormValueSequence', { - key: 'stinFileSize', - value: 1, - }); - - await test.runSequence('reviewPetitionFromPaperSequence'); - expect(test.getState('currentPage')).toEqual('ReviewPetitionFromPaper'); - expect(test.getState('form.stinFile')).toBe(fakeFile); - }); - - it('should allow deletion of an uploaded request for place of trial pdf', async () => { - await test.runSequence('goBackToStartCaseInternalSequence', { - tab: 'partyInfo', - }); - expect(test.getState('currentPage')).toEqual('StartCaseInternal'); - - await test.setState( - 'currentViewMetadata.documentSelectedForScan', - 'requestForPlaceOfTrialFile', - ); - await test.runSequence('openConfirmDeletePDFModalSequence'); - await test.runSequence('removeScannedPdfSequence'); - expect(test.getState('form.requestForPlaceOfTrialFile')).toBeUndefined(); - }); - - it('should upload a new request for place of trial file', async () => { - await test.runSequence('updateFormValueSequence', { - key: 'requestForPlaceOfTrialFile', - value: fakeFile, - }); - - await test.runSequence('updateFormValueSequence', { - key: 'requestForPlaceOfTrialFileSize', - value: 1, - }); - - await test.runSequence('reviewPetitionFromPaperSequence'); - expect(test.getState('currentPage')).toEqual('ReviewPetitionFromPaper'); - - expect(test.getState('form.requestForPlaceOfTrialFile')).toBe(fakeFile); - }); - - it('should allow the deletion an uploaded ownership disclosure statement file', async () => { - await test.setState( - 'currentViewMetadata.documentSelectedForScan', - 'odsFile', - ); - await test.runSequence('openConfirmDeletePDFModalSequence'); - await test.runSequence('removeScannedPdfSequence'); - expect(test.getState('form.odsFile')).toBeUndefined(); - }); - - it('should upload a new ownership disclosure statement file', async () => { - await test.runSequence('updateFormValueSequence', { - key: 'odsFile', - value: fakeFile, - }); - - await test.runSequence('updateFormValueSequence', { - key: 'odsFileSize', - value: 1, - }); - - await test.runSequence('reviewPetitionFromPaperSequence'); - expect(test.getState('currentPage')).toEqual('ReviewPetitionFromPaper'); - - expect(test.getState('form.odsFile')).toBe(fakeFile); - }); - - it('should allow deletion of an uploaded application for waiver of filing fee file', async () => { - await test.setState( - 'currentViewMetadata.documentSelectedForScan', - 'apwFile', - ); - await test.runSequence('openConfirmDeletePDFModalSequence'); - await test.runSequence('removeScannedPdfSequence'); - expect(test.getState('form.apwFile')).toBeUndefined(); - }); - - it('should upload a new application for waiver of filing fee file', async () => { - await test.runSequence('updateFormValueSequence', { - key: 'apwFile', - value: fakeFile, - }); - - await test.runSequence('updateFormValueSequence', { - key: 'apwFileSize', - value: 1, - }); - - await test.runSequence('reviewPetitionFromPaperSequence'); - expect(test.getState('currentPage')).toEqual('ReviewPetitionFromPaper'); - - expect(test.getState('form.apwFile')).toBe(fakeFile); - }); - - it('should contain an order for notice of attachments', async () => { - await test.runSequence('goBackToStartCaseInternalSequence', { - tab: 'caseInfo', - }); - expect(test.getState('currentPage')).toEqual('StartCaseInternal'); - - await test.runSequence('updateFormValueSequence', { - key: 'noticeOfAttachments', - value: true, - }); - expect(test.getState('form.noticeOfAttachments')).toBe(true); - }); - - it('should contain an order for amended petition', async () => { - await test.runSequence('updateFormValueSequence', { - key: 'orderForAmendedPetition', - value: true, - }); - expect(test.getState('form.orderForAmendedPetition')).toBe(true); - }); - - it('should contain an order for amended petition and filing fee', async () => { - await test.runSequence('updateFormValueSequence', { - key: 'orderForAmendedPetitionAndFilingFee', - value: true, - }); - expect(test.getState('form.orderForAmendedPetitionAndFilingFee')).toBe( - true, - ); - }); - - it('should contain an order for filing fee', async () => { - await test.runSequence('updateFormValueSequence', { - key: 'orderForFilingFee', - value: true, - }); - expect(test.getState('form.orderForFilingFee')).toBe(true); - }); - - it('should contain an order for ownership disclosure statement', async () => { - await test.runSequence('updateFormValueSequence', { - key: 'orderForOds', - value: true, - }); - expect(test.getState('form.orderForOds')).toBe(true); - }); - - it('should contain an order for ratification', async () => { - await test.runSequence('updateFormValueSequence', { - key: 'orderForRatification', - value: true, - }); - expect(test.getState('form.orderForRatification')).toBe(true); - }); - - it('should contain an order designating place of trial', async () => { - await test.runSequence('updateFormValueSequence', { - key: 'orderDesignatingPlaceOfTrial', - value: true, - }); - expect(test.getState('form.orderDesignatingPlaceOfTrial')).toBe(true); - }); - - it('should contain an order to show cause', async () => { - await test.runSequence('updateFormValueSequence', { - key: 'orderToShowCause', - value: true, - }); - expect(test.getState('form.orderToShowCause')).toBe(true); - }); - - it('should navigate to Document QC inbox page when saving an in progress case for later', async () => { - await test.runSequence('reviewPetitionFromPaperSequence'); - - expect(test.getState('validationErrors')).toEqual({}); - - expect(test.getState('currentPage')).toEqual('ReviewPetitionFromPaper'); - - await test.runSequence('saveInternalCaseForLaterSequence'); - - expect(test.getState('currentPage')).toEqual('Messages'); - }); -}; - -/** - * @param test - */ -async function navigateToStartCaseInternalPartiesTab(test) { - await test.runSequence('goBackToStartCaseInternalSequence', { - tab: 'partyInfo', - }); - expect(test.getState('currentPage')).toEqual('StartCaseInternal'); - expect(test.getState('currentViewMetadata.startCaseInternal.tab')).toBe( - 'partyInfo', - ); -} diff --git a/web-client/integration-tests/journey/petitionsClerkCreatesNewCaseFromPaper.js b/web-client/integration-tests/journey/petitionsClerkCreatesNewCaseFromPaper.js new file mode 100644 index 00000000000..8573b3c0301 --- /dev/null +++ b/web-client/integration-tests/journey/petitionsClerkCreatesNewCaseFromPaper.js @@ -0,0 +1,264 @@ +import { Case } from '../../../shared/src/business/entities/cases/Case'; +import { CaseInternal } from '../../../shared/src/business/entities/cases/CaseInternal'; +import { ContactFactory } from '../../../shared/src/business/entities/contacts/ContactFactory'; +import { reviewSavedPetitionHelper as reviewSavedPetitionHelperComputed } from '../../src/presenter/computeds/reviewSavedPetitionHelper'; +import { runCompute } from 'cerebral/test'; +import { withAppContextDecorator } from '../../src/withAppContext'; + +const reviewSavedPetitionHelper = withAppContextDecorator( + reviewSavedPetitionHelperComputed, +); + +export const petitionsClerkCreatesNewCaseFromPaper = ( + test, + fakeFile, + trialLocation = 'Birmingham, Alabama', +) => { + const primaryContactName = { + key: 'contactPrimary.name', + value: 'Shawn Johnson', + }; + + const formValues = [ + { + key: 'dateReceivedMonth', + value: '01', + }, + { + key: 'dateReceivedDay', + value: '01', + }, + { + key: 'dateReceivedYear', + value: '2001', + }, + { + key: 'mailingDate', + value: 'Some Day', + }, + { + key: 'petitionFile', + value: fakeFile, + }, + { + key: 'petitionFileSize', + value: 1, + }, + { + key: 'odsFile', + value: fakeFile, + }, + { + key: 'odsFileSize', + value: 1, + }, + { + key: 'ownershipDisclosureFile', + value: fakeFile, + }, + { + key: 'ownershipDisclosureFileSize', + value: 1, + }, + { + key: 'requestForPlaceOfTrialFile', + value: fakeFile, + }, + { + key: 'requestForPlaceOfTrialFileSize', + value: 1, + }, + { + key: 'applicationForWaiverOfFilingFeeFile', + value: fakeFile, + }, + { + key: 'applicationForWaiverOfFilingFeeFileSize', + value: 1, + }, + { + key: 'preferredTrialCity', + value: trialLocation, + }, + { + key: 'procedureType', + value: 'Small', + }, + { + key: 'caseType', + value: 'Deficiency', + }, + { + key: 'partyType', + value: ContactFactory.PARTY_TYPES.petitionerDeceasedSpouse, + }, + { + key: 'contactPrimary.countryType', + value: 'international', + }, + { + key: 'contactPrimary.country', + value: 'Switzerland', + }, + primaryContactName, + { + key: 'contactPrimary.address1', + value: '123 Abc Ln', + }, + { + key: 'contactPrimary.city', + value: 'Cityville', + }, + { + key: 'contactPrimary.postalCode', + value: '23-skidoo', + }, + { + key: 'contactPrimary.email', + value: 'test@example.com', + }, + { + key: 'contactPrimary.phone', + value: '1234567890', + }, + { + key: 'contactSecondary.name', + value: 'Julius Lenhart', + }, + { + key: 'contactSecondary.inCareOf', + value: 'Nora Stanton Barney', + }, + { + key: 'petitionPaymentStatus', + value: Case.PAYMENT_STATUS.WAIVED, + }, + { + key: 'paymentDateWaivedDay', + value: '05', + }, + { + key: 'paymentDateWaivedMonth', + value: '05', + }, + { + key: 'paymentDateWaivedYear', + value: '2005', + }, + { + key: 'orderForRatification', + value: true, + }, + ]; + + it('should default to parties tab when creating a new case', async () => { + await test.runSequence('gotoStartCaseWizardSequence'); + await test.runSequence('submitPetitionFromPaperSequence'); + + expect(test.getState('currentPage')).toEqual('StartCaseInternal'); + expect(test.getState('currentViewMetadata.startCaseInternal.tab')).toBe( + 'partyInfo', + ); + }); + + it('should default to Regular procedureType when creating a new case', async () => { + expect(test.getState('form.procedureType')).toEqual( + CaseInternal.DEFAULT_PROCEDURE_TYPE, + ); + }); + + it('should generate case caption from primary and secondary contact information', async () => { + for (const item of formValues) { + if (item.key === 'partyType') { + await test.runSequence( + 'updateStartCaseInternalPartyTypeSequence', + item, + ); + } else if (item.key === 'petitionPaymentStatus') { + await test.runSequence('updatePetitionPaymentFormValueSequence', item); + } else { + await test.runSequence('updateFormValueSequence', item); + } + } + + await test.runSequence('updateFormValueAndSecondaryContactInfoSequence', { + key: 'useSameAsPrimary', + value: true, + }); + await test.runSequence( + 'updateFormValueAndCaseCaptionSequence', + primaryContactName, + ); + await test.runSequence('validatePetitionFromPaperSequence'); + + expect(test.getState('form.caseCaption')).toBe( + 'Shawn Johnson & Julius Lenhart, Deceased, Shawn Johnson, Surviving Spouse, Petitioners', + ); + expect(test.getState('form.contactSecondary.address1')).toBe( + test.getState('form.contactPrimary.address1'), + ); + expect(test.getState('form.contactSecondary.city')).toBe( + test.getState('form.contactPrimary.city'), + ); + expect(test.getState('form.contactSecondary.country')).toBe( + test.getState('form.contactPrimary.country'), + ); + expect(test.getState('form.contactSecondary.postalCode')).toBe( + test.getState('form.contactPrimary.postalCode'), + ); + expect(test.getState('form.contactSecondary.email')).toBe( + test.getState('form.contactPrimary.email'), + ); + expect(test.getState('form.contactSecondary.phone')).toBe( + test.getState('form.contactPrimary.phone'), + ); + expect(test.getState('form.contactSecondary.inCareOf')).toBe( + 'Nora Stanton Barney', + ); + }); + + const updatedCaseCaption = 'Ada Lovelace is awesome'; + + it('should regenerate case caption when primary contact name is changed', async () => { + await test.runSequence('updateFormValueAndCaseCaptionSequence', { + key: 'contactPrimary.name', + value: 'Ada Lovelace', + }); + + expect(test.getState('form.caseCaption')).toBe( + 'Ada Lovelace & Julius Lenhart, Deceased, Ada Lovelace, Surviving Spouse, Petitioners', + ); + + await test.runSequence('updateFormValueSequence', { + key: 'caseCaption', + value: updatedCaseCaption, + }); + + expect(test.getState('form.caseCaption')).toBe(updatedCaseCaption); + }); + + it('should create case and navigate to review screen when case information has been validated', async () => { + await test.runSequence('submitPetitionFromPaperSequence'); + expect(test.getState('alertError')).toBeUndefined(); + expect(test.getState('validationErrors')).toEqual({}); + + expect(test.getState('currentPage')).toEqual('ReviewSavedPetition'); + + const helper = runCompute(reviewSavedPetitionHelper, { + state: test.getState(), + }); + + expect(helper).toMatchObject({ + hasIrsNoticeFormatted: 'No', + hasOrders: true, + petitionPaymentStatusFormatted: 'Waived 05/05/05', + receivedAtFormatted: '01/01/01', + shouldShowIrsNoticeDate: false, + }); + + expect(test.getState('caseDetail')).toMatchObject({ + caseCaption: updatedCaseCaption, + isPaper: true, + }); + }); +}; diff --git a/web-client/integration-tests/journey/petitionsClerkEditsAnExistingCaseAndServesCase.js b/web-client/integration-tests/journey/petitionsClerkEditsAnExistingCaseAndServesCase.js index c13a8bf2d56..11b914ab12b 100644 --- a/web-client/integration-tests/journey/petitionsClerkEditsAnExistingCaseAndServesCase.js +++ b/web-client/integration-tests/journey/petitionsClerkEditsAnExistingCaseAndServesCase.js @@ -9,8 +9,8 @@ export const petitionsClerkEditsAnExistingCaseAndServesCase = test => { }); await test.runSequence('updateFormValueSequence', { - key: 'partyType', - value: 'Guardian', + key: 'contactPrimary.name', + value: 'New Name', }); await test.runSequence('validatePetitionFromPaperSequence'); @@ -20,9 +20,9 @@ export const petitionsClerkEditsAnExistingCaseAndServesCase = test => { }); it('should save edits to an in progress case', async () => { - await test.runSequence('gotoReviewPetitionFromPaperSequence'); + await test.runSequence('submitPetitionFromPaperSequence'); - expect(test.getState('currentPage')).toEqual('ReviewPetitionFromPaper'); + expect(test.getState('currentPage')).toEqual('ReviewSavedPetition'); await test.runSequence('saveSavedCaseForLaterSequence'); await wait(500); @@ -69,7 +69,7 @@ export const petitionsClerkEditsAnExistingCaseAndServesCase = test => { .find(x => x.docketNumber === test.docketNumber); expect(servedCase).toMatchObject({ - caseCaptionNames: 'Mona Schultz', + caseTitle: 'Mona Schultz', }); expect(servedCase.caseStatus).toEqual(Case.STATUS_TYPES.generalDocket); }); @@ -95,7 +95,7 @@ export const petitionsClerkEditsAnExistingCaseAndServesCase = test => { .find(x => x.docketNumber === test.docketNumber); expect(sectionServedCase).toMatchObject({ - caseCaptionNames: 'Mona Schultz', + caseTitle: 'Mona Schultz', }); expect(sectionServedCase.caseStatus).toEqual( Case.STATUS_TYPES.generalDocket, diff --git a/web-client/integration-tests/journey/petitionsClerkVerifiesOrderDesignatingPlaceOfTrialCheckbox.js b/web-client/integration-tests/journey/petitionsClerkVerifiesOrderDesignatingPlaceOfTrialCheckbox.js index 78b24376585..baa0e7553af 100644 --- a/web-client/integration-tests/journey/petitionsClerkVerifiesOrderDesignatingPlaceOfTrialCheckbox.js +++ b/web-client/integration-tests/journey/petitionsClerkVerifiesOrderDesignatingPlaceOfTrialCheckbox.js @@ -16,7 +16,7 @@ export const petitionsClerkVerifiesOrderDesignatingPlaceOfTrialCheckbox = ( value: false, }); - await test.runSequence('reviewPetitionFromPaperSequence'); + await test.runSequence('submitPetitionFromPaperSequence'); expect(test.getState('validationErrors')).toMatchObject({ chooseAtLeastOneValue: diff --git a/web-client/integration-tests/journey/petitionsClerkVerifiesOrderForOdsCheckbox.js b/web-client/integration-tests/journey/petitionsClerkVerifiesOrderForOdsCheckbox.js index 59e7a4cb3f5..b54cbea1276 100644 --- a/web-client/integration-tests/journey/petitionsClerkVerifiesOrderForOdsCheckbox.js +++ b/web-client/integration-tests/journey/petitionsClerkVerifiesOrderForOdsCheckbox.js @@ -21,7 +21,7 @@ export const petitionsClerkVerifiesOrderForOdsCheckbox = (test, fakeFile) => { expect(test.getState('form.orderForOds')).toBeTruthy(); - await test.runSequence('reviewPetitionFromPaperSequence'); + await test.runSequence('submitPetitionFromPaperSequence'); expect( test.getState('validationErrors.ownershipDisclosureFile'), @@ -32,7 +32,7 @@ export const petitionsClerkVerifiesOrderForOdsCheckbox = (test, fakeFile) => { value: false, }); - await test.runSequence('reviewPetitionFromPaperSequence'); + await test.runSequence('submitPetitionFromPaperSequence'); expect(test.getState('validationErrors.ownershipDisclosureFile')).toEqual( CaseInternal.VALIDATION_ERROR_MESSAGES.ownershipDisclosureFile, diff --git a/web-client/integration-tests/journey/petitionsClerkVerifiesPetitionPaymentFeeOptions.js b/web-client/integration-tests/journey/petitionsClerkVerifiesPetitionPaymentFeeOptions.js index df5760afe05..d033003fb2d 100644 --- a/web-client/integration-tests/journey/petitionsClerkVerifiesPetitionPaymentFeeOptions.js +++ b/web-client/integration-tests/journey/petitionsClerkVerifiesPetitionPaymentFeeOptions.js @@ -19,7 +19,7 @@ export const petitionsClerkVerifiesPetitionPaymentFeeOptions = ( expect(test.getState('form.orderForFilingFee')).toEqual(false); - await test.runSequence('reviewPetitionFromPaperSequence'); + await test.runSequence('submitPetitionFromPaperSequence'); expect(test.getState('validationErrors')).toMatchObject({ petitionPaymentDate: Case.VALIDATION_ERROR_MESSAGES.petitionPaymentDate, @@ -44,7 +44,7 @@ export const petitionsClerkVerifiesPetitionPaymentFeeOptions = ( value: 'check', }); - await test.runSequence('reviewPetitionFromPaperSequence'); + await test.runSequence('submitPetitionFromPaperSequence'); expect( test.getState('validationErrors.petitionPaymentDate'), @@ -60,7 +60,7 @@ export const petitionsClerkVerifiesPetitionPaymentFeeOptions = ( expect(test.getState('form.orderForFilingFee')).toEqual(true); - await test.runSequence('reviewPetitionFromPaperSequence'); + await test.runSequence('submitPetitionFromPaperSequence'); expect( test.getState('validationErrors.petitionPaymentDate'), @@ -76,7 +76,7 @@ export const petitionsClerkVerifiesPetitionPaymentFeeOptions = ( expect(test.getState('form.orderForFilingFee')).toEqual(false); - await test.runSequence('reviewPetitionFromPaperSequence'); + await test.runSequence('submitPetitionFromPaperSequence'); expect(test.getState('validationErrors')).toMatchObject({ applicationForWaiverOfFilingFeeFile: @@ -107,7 +107,7 @@ export const petitionsClerkVerifiesPetitionPaymentFeeOptions = ( value: 1, }); - await test.runSequence('reviewPetitionFromPaperSequence'); + await test.runSequence('submitPetitionFromPaperSequence'); expect( test.getState('validationErrors.petitionPaymentWaivedDate'), diff --git a/web-client/integration-tests/journey/petitionsClerkViewsDocketRecordEditLinks.js b/web-client/integration-tests/journey/petitionsClerkViewsDocketRecordEditLinks.js index 8224250a7e0..dd3942305bb 100644 --- a/web-client/integration-tests/journey/petitionsClerkViewsDocketRecordEditLinks.js +++ b/web-client/integration-tests/journey/petitionsClerkViewsDocketRecordEditLinks.js @@ -16,7 +16,7 @@ export default test => { ); expect(caseDetailFormatted.formattedDocketEntries).toMatchObject([ - { description: 'Petition', editLink: '/edit-saved' }, + { description: 'Petition', editLink: '' }, { description: 'Request for Place of Trial at Seattle, Washington', editLink: '', diff --git a/web-client/integration-tests/journey/trialClerkAddsNotesFromWorkingCopyCaseList.js b/web-client/integration-tests/journey/trialClerkAddsNotesFromWorkingCopyCaseList.js index f25cb85aab3..70ff66298f0 100644 --- a/web-client/integration-tests/journey/trialClerkAddsNotesFromWorkingCopyCaseList.js +++ b/web-client/integration-tests/journey/trialClerkAddsNotesFromWorkingCopyCaseList.js @@ -24,8 +24,8 @@ export default test => { }); expect(test.getState('modal')).toEqual({ - caseCaptionNames: 'Mona Schultz', caseId, + caseTitle: 'Mona Schultz', notes: undefined, showModal: 'AddEditUserCaseNoteModal', }); @@ -36,8 +36,8 @@ export default test => { }); expect(test.getState('modal')).toEqual({ - caseCaptionNames: 'Mona Schultz', caseId, + caseTitle: 'Mona Schultz', notes: 'this is a note added from the modal', showModal: 'AddEditUserCaseNoteModal', }); diff --git a/web-client/integration-tests/journey/unassociatedUserSearchesForServedOrderInSealedCase.js b/web-client/integration-tests/journey/unassociatedUserSearchesForServedOrderInSealedCase.js new file mode 100644 index 00000000000..2f040bce308 --- /dev/null +++ b/web-client/integration-tests/journey/unassociatedUserSearchesForServedOrderInSealedCase.js @@ -0,0 +1,22 @@ +export const unassociatedUserSearchesForServedOrderInSealedCase = ( + test, + options, +) => { + return it('unassociated user searches for served order in a sealed case', async () => { + test.setState('advancedSearchForm', { + orderSearch: { + orderKeyword: options.orderKeyword, + }, + }); + + await test.runSequence('submitOrderAdvancedSearchSequence'); + + expect(test.getState('searchResults')).not.toEqual( + expect.arrayContaining([ + expect.objectContaining({ + documentId: test.draftOrders[options.draftOrderIndex].documentId, + }), + ]), + ); + }); +}; diff --git a/web-client/integration-tests/journey/unassociatedUserSearchesForServedOrderInUnsealedCase.js b/web-client/integration-tests/journey/unassociatedUserSearchesForServedOrderInUnsealedCase.js new file mode 100644 index 00000000000..37e3e380dda --- /dev/null +++ b/web-client/integration-tests/journey/unassociatedUserSearchesForServedOrderInUnsealedCase.js @@ -0,0 +1,22 @@ +export const unassociatedUserSearchesForServedOrderInUnsealedCase = ( + test, + options, +) => { + return it('unassociated user searches for served order in an unsealed case', async () => { + test.setState('advancedSearchForm', { + orderSearch: { + orderKeyword: options.orderKeyword, + }, + }); + + await test.runSequence('submitOrderAdvancedSearchSequence'); + + expect(test.getState('searchResults')).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + documentId: test.draftOrders[options.draftOrderIndex].documentId, + }), + ]), + ); + }); +}; diff --git a/web-client/integration-tests/modifyRespondentContactInfo.test.js b/web-client/integration-tests/modifyRespondentContactInfo.test.js index 62a3181604f..89abf5448e5 100644 --- a/web-client/integration-tests/modifyRespondentContactInfo.test.js +++ b/web-client/integration-tests/modifyRespondentContactInfo.test.js @@ -1,5 +1,5 @@ import { loginAs, setupTest, uploadPetition } from './helpers'; -import petitionsClerkAddsRespondentsToCase from './journey/petitionsClerkAddsRespondentsToCase'; +import { petitionsClerkAddsRespondentsToCase } from './journey/petitionsClerkAddsRespondentsToCase'; import respondentUpdatesAddress from './journey/respondentUpdatesAddress'; import respondentViewsCaseDetailNoticeOfChangeOfAddress from './journey/respondentViewsCaseDetailNoticeOfChangeOfAddress'; diff --git a/web-client/integration-tests/petitionsClerkCounselAssociationJourney.test.js b/web-client/integration-tests/petitionsClerkCounselAssociationJourney.test.js index 3a2612cfd0a..234cb012f51 100644 --- a/web-client/integration-tests/petitionsClerkCounselAssociationJourney.test.js +++ b/web-client/integration-tests/petitionsClerkCounselAssociationJourney.test.js @@ -1,9 +1,9 @@ import { ContactFactory } from '../../shared/src/business/entities/contacts/ContactFactory'; import { loginAs, setupTest } from './helpers'; import { petitionsClerkAddsPractitionersToCase } from './journey/petitionsClerkAddsPractitionersToCase'; +import { petitionsClerkAddsRespondentsToCase } from './journey/petitionsClerkAddsRespondentsToCase'; import { petitionsClerkViewsCaseDetail } from './journey/petitionsClerkViewsCaseDetail'; import { uploadPetition } from './helpers'; -import petitionsClerkAddsRespondentsToCase from './journey/petitionsClerkAddsRespondentsToCase'; import petitionsClerkEditsPractitionerOnCase from './journey/petitionsClerkEditsPractitionerOnCase'; import petitionsClerkRemovesPractitionerFromCase from './journey/petitionsClerkRemovesPractitionerFromCase'; import petitionsClerkRemovesRespondentFromCase from './journey/petitionsClerkRemovesRespondentFromCase'; diff --git a/web-client/integration-tests/petitionsClerkPaperCaseJourney.test.js b/web-client/integration-tests/petitionsClerkPaperCaseJourney.test.js index fb9a55b7d56..827b24bcbb5 100644 --- a/web-client/integration-tests/petitionsClerkPaperCaseJourney.test.js +++ b/web-client/integration-tests/petitionsClerkPaperCaseJourney.test.js @@ -1,6 +1,6 @@ import { fakeFile, loginAs, setupTest, uploadPetition } from './helpers'; -import { petitionsClerkCreatesNewCaseAndSavesForLater } from './journey/petitionsClerkCreatesNewCaseAndSavesForLater'; -import { petitionsClerkEditsAnExistingCaseAndServesCase } from './journey/petitionsClerkEditsAnExistingCaseAndServesCase'; +import { petitionsClerkCreatesNewCaseFromPaper } from './journey/petitionsClerkCreatesNewCaseFromPaper'; +// import { petitionsClerkEditsAnExistingCaseAndServesCase } from './journey/petitionsClerkEditsAnExistingCaseAndServesCase'; import { petitionsClerkVerifiesOrderDesignatingPlaceOfTrialCheckbox } from './journey/petitionsClerkVerifiesOrderDesignatingPlaceOfTrialCheckbox'; import { petitionsClerkVerifiesOrderForOdsCheckbox } from './journey/petitionsClerkVerifiesOrderForOdsCheckbox'; import { petitionsClerkVerifiesPetitionPaymentFeeOptions } from './journey/petitionsClerkVerifiesPetitionPaymentFeeOptions'; @@ -9,11 +9,11 @@ const test = setupTest(); describe('Petitions clerk paper case flow', () => { beforeAll(() => { - jest.setTimeout(30000); + jest.setTimeout(40000); }); loginAs(test, 'petitionsclerk'); - petitionsClerkCreatesNewCaseAndSavesForLater(test, fakeFile); + petitionsClerkCreatesNewCaseFromPaper(test, fakeFile); loginAs(test, 'petitioner'); it('Create case', async () => { @@ -25,7 +25,7 @@ describe('Petitions clerk paper case flow', () => { }); loginAs(test, 'petitionsclerk'); - petitionsClerkEditsAnExistingCaseAndServesCase(test); + // petitionsClerkEditsAnExistingCaseAndServesCase(test); petitionsClerkVerifiesOrderForOdsCheckbox(test, fakeFile); petitionsClerkVerifiesOrderDesignatingPlaceOfTrialCheckbox(test, fakeFile); diff --git a/web-client/integration-tests/signAndServeStipulatedDecision.test.js b/web-client/integration-tests/signAndServeStipulatedDecision.test.js index 5af9cf4a396..f52e591e6f9 100644 --- a/web-client/integration-tests/signAndServeStipulatedDecision.test.js +++ b/web-client/integration-tests/signAndServeStipulatedDecision.test.js @@ -132,7 +132,7 @@ describe('a user signs and serves a stipulated decision', () => { const signedDocument = caseDetail.documents.find( d => d.documentId === signedDocumentId, ); - expect(signedDocument.status).toEqual('served'); + expect(signedDocument.servedAt).toBeDefined(); expect(caseDetail.status).toEqual(Case.STATUS_TYPES.closed); }); }); diff --git a/web-client/pa11y/pa11y-docketclerk.js b/web-client/pa11y/pa11y-docketclerk.js index cbe447cda12..67c32268163 100644 --- a/web-client/pa11y/pa11y-docketclerk.js +++ b/web-client/pa11y/pa11y-docketclerk.js @@ -128,7 +128,21 @@ module.exports = [ 'wait for table.search-results to be visible', ], notes: 'checks a11y of advanced order search', - url: 'http://localhost:1234/mock-login?token=docketclerk&path=/search', + url: + 'http://localhost:1234/mock-login?token=docketclerk&path=/search&info=order-search-result', + }, + { + actions: [ + 'wait for #tab-order to be visible', + 'click element #tab-order', + 'wait for #order-search to be visible', + 'set field #order-search to meow', + 'click element button#advanced-search-button', + 'wait for svg.iconSealed to be visible', + ], + notes: 'checks a11y of advanced order search of a sealed case', + url: + 'http://localhost:1234/mock-login?token=docketclerk&path=/search&info=sealed-case-order-search-result', }, 'http://localhost:1234/mock-login?token=docketclerk&path=/print-preview/110-19/', 'http://localhost:1234/mock-login?token=docketclerk&path=/case-detail/105-19/edit-petitioner-information', diff --git a/web-client/pa11y/pa11y-petitioner.js b/web-client/pa11y/pa11y-petitioner.js index d619fe46067..64db2e87946 100644 --- a/web-client/pa11y/pa11y-petitioner.js +++ b/web-client/pa11y/pa11y-petitioner.js @@ -342,7 +342,6 @@ module.exports = [ url: 'http://localhost:1234/mock-login?token=petitioner&path=/case-detail/101-19/file-a-document&info=doctype-selection-2', }, - 'http://localhost:1234/mock-login?token=petitioner&path=/case-detail/101-19/contacts/primary/edit', 'http://localhost:1234/mock-login?token=petitioner&path=/case-detail/101-19/contacts/secondary/edit', ]; diff --git a/web-client/pa11y/pa11y-petitionsclerk.js b/web-client/pa11y/pa11y-petitionsclerk.js index 13b3a0f3c54..ccd0bfa170e 100644 --- a/web-client/pa11y/pa11y-petitionsclerk.js +++ b/web-client/pa11y/pa11y-petitionsclerk.js @@ -386,4 +386,14 @@ module.exports = [ 'http://localhost:1234/mock-login?token=petitionsclerk&path=/search&info=practitioner-search-results', }, 'http://localhost:1234/mock-login?token=petitionsclerk&path=/practitioner-detail/PT1234', + { + actions: [ + 'wait for #submit-case to be visible', + 'click element #submit-case', + 'wait for .usa-alert--warning to be visible', + ], + notes: 'checks the review paper case screen', + url: + 'http://localhost:1234/mock-login?token=petitionsclerk&path=/case-detail/104-19/documents/c63be3f2-2240-451e-b6bd-8206d52a070b', + }, ]; diff --git a/web-client/pa11y/pa11y-public-user.js b/web-client/pa11y/pa11y-public-user.js index e38a834b177..dd11596945d 100644 --- a/web-client/pa11y/pa11y-public-user.js +++ b/web-client/pa11y/pa11y-public-user.js @@ -11,4 +11,16 @@ module.exports = [ notes: 'checks a11y of advanced order search', url: 'http://localhost:5678', }, + { + actions: [ + 'wait for #tab-order to be visible', + 'click element #tab-order', + 'wait for #order-search to be visible', + 'set field #order-search to meow', + 'click element button#advanced-search-button', + 'wait for #no-search-results to be visible', + ], + notes: 'checks a11y of advanced order search with no results', + url: 'http://localhost:5678?info=no-results', + }, ]; diff --git a/web-client/src/app.jsx b/web-client/src/app.jsx index 95eb0f61388..a2b42d5ca66 100644 --- a/web-client/src/app.jsx +++ b/web-client/src/app.jsx @@ -42,11 +42,13 @@ import { faDollarSign, faEdit as faEditSolid, faEnvelope as faEnvelopeSolid, + faExclamation, faExclamationCircle, faExclamationTriangle, faFile, faFileAlt as faFileAltSolid, faFilePdf, + faFingerprint, faFlag, faGavel, faHandPaper, @@ -147,7 +149,9 @@ const app = { faCalendarCheck, faCalendarPlus, faCaretDown, + faFingerprint, faExclamationCircle, + faExclamation, faCaretLeft, faCaretRight, faCaretUp, diff --git a/web-client/src/appPublic.jsx b/web-client/src/appPublic.jsx index 5405cd34674..04018546ce0 100644 --- a/web-client/src/appPublic.jsx +++ b/web-client/src/appPublic.jsx @@ -61,6 +61,7 @@ const appPublic = { ); presenter.providers.applicationContext = applicationContext; + presenter.state.baseUrl = applicationContext.getBaseUrl(); presenter.state.cognitoLoginUrl = applicationContext.getCognitoLoginUrl(); presenter.state.constants = applicationContext.getConstants(); diff --git a/web-client/src/applicationContext.js b/web-client/src/applicationContext.js index 11c5bcc72b0..df056d1796f 100644 --- a/web-client/src/applicationContext.js +++ b/web-client/src/applicationContext.js @@ -5,25 +5,9 @@ import { getUniqueId, } from '../../shared/src/sharedAppContext.js'; -import { AddIrsPractitioner } from '../../shared/src/business/entities/caseAssociation/AddIrsPractitioner'; -import { AddPrivatePractitionerFactory } from '../../shared/src/business/entities/caseAssociation/AddPrivatePractitionerFactory'; import { Case } from '../../shared/src/business/entities/cases/Case'; -import { CaseAssociationRequestFactory } from '../../shared/src/business/entities/CaseAssociationRequestFactory'; -import { CaseDeadline } from '../../shared/src/business/entities/CaseDeadline'; -import { CaseExternal } from '../../shared/src/business/entities/cases/CaseExternal'; -import { CaseExternalInformationFactory } from '../../shared/src/business/entities/cases/CaseExternalInformationFactory'; -import { CaseInternal } from '../../shared/src/business/entities/cases/CaseInternal'; -import { ContactFactory } from '../../shared/src/business/entities/contacts/ContactFactory'; -import { CourtIssuedDocumentFactory } from '../../shared/src/business/entities/courtIssuedDocument/CourtIssuedDocumentFactory'; -import { DocketEntryFactory } from '../../shared/src/business/entities/docketEntry/DocketEntryFactory'; -import { DocketRecord } from '../../shared/src/business/entities/DocketRecord'; import { Document } from '../../shared/src/business/entities/Document'; -import { EditPrivatePractitionerFactory } from '../../shared/src/business/entities/caseAssociation/EditPrivatePractitionerFactory'; import { ErrorFactory } from './presenter/errors/ErrorFactory'; -import { ExternalDocumentFactory } from '../../shared/src/business/entities/externalDocument/ExternalDocumentFactory'; -import { ExternalDocumentInformationFactory } from '../../shared/src/business/entities/externalDocument/ExternalDocumentInformationFactory'; -import { ForwardMessage } from '../../shared/src/business/entities/ForwardMessage'; -import { OrderSearch } from '../../shared/src/business/entities/orders/OrderSearch'; import { compareISODateStrings, compareStrings, @@ -37,12 +21,6 @@ import { validateDocketRecordInteractor } from '../../shared/src/business/useCas const { getJudgeForUserChambersInteractor, } = require('../../shared/src/business/useCases/users/getJudgeForUserChambersInteractor'); -import { InitialWorkItemMessage } from '../../shared/src/business/entities/InitialWorkItemMessage'; -import { NewPractitioner } from '../../shared/src/business/entities/NewPractitioner'; -import { NewTrialSession } from '../../shared/src/business/entities/trialSessions/NewTrialSession'; -import { Note } from '../../shared/src/business/entities/notes/Note'; -import { OrderWithoutBody } from '../../shared/src/business/entities/orders/OrderWithoutBody'; -import { TrialSession } from '../../shared/src/business/entities/trialSessions/TrialSession'; import { User } from '../../shared/src/business/entities/User'; import { addCaseToTrialSessionInteractor } from '../../shared/src/proxies/trialSessions/addCaseToTrialSessionProxy'; import { addConsolidatedCaseInteractor } from '../../shared/src/proxies/addConsolidatedCaseProxy'; @@ -54,6 +32,7 @@ import { associatePrivatePractitionerWithCaseInteractor } from '../../shared/src import { authorizeCodeInteractor } from '../../shared/src/business/useCases/authorizeCodeInteractor'; import { batchDownloadTrialSessionInteractor } from '../../shared/src/proxies/trialSessions/batchDownloadTrialSessionProxy'; import { blockCaseFromTrialInteractor } from '../../shared/src/proxies/blockCaseFromTrialProxy'; +import { canConsolidateInteractor } from '../../shared/src/business/useCases/caseConsolidation/canConsolidateInteractor'; import { canSetTrialSessionAsCalendaredInteractor } from '../../shared/src/business/useCases/trialSessions/canSetTrialSessionAsCalendaredInteractor'; import { caseAdvancedSearchInteractor } from '../../shared/src/proxies/caseAdvancedSearchProxy'; import { @@ -135,6 +114,8 @@ import { getIrsPractitionersBySearchKeyInteractor } from '../../shared/src/proxi import { getItem } from '../../shared/src/persistence/localStorage/getItem'; import { getItemInteractor } from '../../shared/src/business/useCases/getItemInteractor'; import { getNotificationsInteractor } from '../../shared/src/proxies/users/getNotificationsProxy'; +import { getPdfFromUrl } from '../../shared/src/persistence/s3/getPdfFromUrl'; +import { getPdfFromUrlInteractor } from '../../shared/src/business/useCases/document/getPdfFromUrlInteractor'; import { getPractitionerByBarNumberInteractor } from '../../shared/src/proxies/users/getPractitionerByBarNumberProxy'; import { getPractitionersByNameInteractor } from '../../shared/src/proxies/practitioners/getPractitionersByNameProxy'; import { getPrivatePractitionersBySearchKeyInteractor } from '../../shared/src/proxies/users/getPrivatePractitionersBySearchKeyProxy'; @@ -263,6 +244,7 @@ const allUseCases = { authorizeCodeInteractor, batchDownloadTrialSessionInteractor, blockCaseFromTrialInteractor, + canConsolidateInteractor, canSetTrialSessionAsCalendaredInteractor, caseAdvancedSearchInteractor, completeDocketEntryQCInteractor, @@ -319,6 +301,7 @@ const allUseCases = { getItemInteractor, getJudgeForUserChambersInteractor, getNotificationsInteractor, + getPdfFromUrlInteractor, getPractitionerByBarNumberInteractor, getPractitionersByNameInteractor, getPrivatePractitionersBySearchKeyInteractor, @@ -420,7 +403,7 @@ const applicationContext = { getBaseUrl: () => { return process.env.API_URL || 'http://localhost:3000'; }, - getCaseCaptionNames: Case.getCaseCaptionNames, + getCaseTitle: Case.getCaseTitle, getChiefJudgeNameForSigning: () => chiefJudgeNameForSigning, getClerkOfCourtNameForSigning: () => clerkOfCourtNameForSigning, getCognitoClientId: () => { @@ -444,33 +427,6 @@ const applicationContext = { return getUserPermissions(user); }, getCurrentUserToken, - getEntityConstructors: () => ({ - AddIrsPractitioner, - AddPrivatePractitionerFactory, - Case, - CaseAssociationRequestFactory, - CaseDeadline, - CaseExternal, - CaseExternalInformationFactory, - CaseInternal, - ContactFactory, - CourtIssuedDocumentFactory, - DocketEntryFactory, - DocketRecord, - Document, - EditPrivatePractitionerFactory, - ExternalDocumentFactory, - ExternalDocumentInformationFactory, - ForwardMessage, - InitialWorkItemMessage, - NewPractitioner, - NewTrialSession, - Note, - OrderSearch, - OrderWithoutBody, - TrialSession, - User, - }), getError: e => { return ErrorFactory.getError(e); }, @@ -489,6 +445,7 @@ const applicationContext = { return { getDocument, getItem, + getPdfFromUrl, removeItem, setItem, uploadDocumentFromClient, @@ -534,12 +491,14 @@ const applicationContext = { formatJudgeName, formatNow, formattedTrialSessionDetails, + getCaseCaption: Case.getCaseCaption, getFilingsAndProceedings, getFormattedCaseDetail, getJudgeLastName, getTrialSessionStatus, isExternalUser: User.isExternalUser, isInternalUser: User.isInternalUser, + isPendingOnCreation: Document.isPendingOnCreation, isStringISOFormatted, isValidDateString, prepareDateFromString, diff --git a/web-client/src/applicationContextPublic.js b/web-client/src/applicationContextPublic.js index 101e91bc05a..463635842ef 100644 --- a/web-client/src/applicationContextPublic.js +++ b/web-client/src/applicationContextPublic.js @@ -27,7 +27,7 @@ const applicationContextPublic = { getBaseUrl: () => { return process.env.API_URL || 'http://localhost:3000'; }, - getCaseCaptionNames: Case.getCaseCaptionNames, + getCaseTitle: Case.getCaseTitle, getCognitoLoginUrl, getConstants: () => deepFreeze({ diff --git a/web-client/src/getConstants.js b/web-client/src/getConstants.js index e0d872f4c4d..923bbc27631 100644 --- a/web-client/src/getConstants.js +++ b/web-client/src/getConstants.js @@ -72,6 +72,7 @@ export const getConstants = () => ({ STATUS_TYPES: Case.STATUS_TYPES, STATUS_TYPES_MANUAL_UPDATE: Case.STATUS_TYPES_MANUAL_UPDATE, STATUS_TYPES_WITH_ASSOCIATED_JUDGE: Case.STATUS_TYPES_WITH_ASSOCIATED_JUDGE, + SYSTEM_GENERATED_DOCUMENT_TYPES: Document.SYSTEM_GENERATED_DOCUMENT_TYPES, TRANSCRIPT_EVENT_CODE: Document.TRANSCRIPT_EVENT_CODE, TRIAL_CITIES: TrialSession.TRIAL_CITIES, TRIAL_SESSION_TYPES: TrialSession.SESSION_TYPES, diff --git a/web-client/src/presenter/actions/CaseDeadline/setDefaultDateOnCalendarAction.test.js b/web-client/src/presenter/actions/CaseDeadline/setDefaultDateOnCalendarAction.test.js index fc48369915c..8cc1bd17a97 100644 --- a/web-client/src/presenter/actions/CaseDeadline/setDefaultDateOnCalendarAction.test.js +++ b/web-client/src/presenter/actions/CaseDeadline/setDefaultDateOnCalendarAction.test.js @@ -6,6 +6,7 @@ describe('setDefaultDateOnCalendarAction', () => { const currentDate = new Date('2019-05-14T04:00:00.000Z'); global.Date = class extends Date { constructor() { + super(); return currentDate; } }; diff --git a/web-client/src/presenter/actions/CaseDetail/setAddEditCaseNoteModalStateFromDetailAction.js b/web-client/src/presenter/actions/CaseDetail/setAddEditCaseNoteModalStateFromDetailAction.js index 11c6c18772f..e2f5493a267 100644 --- a/web-client/src/presenter/actions/CaseDetail/setAddEditCaseNoteModalStateFromDetailAction.js +++ b/web-client/src/presenter/actions/CaseDetail/setAddEditCaseNoteModalStateFromDetailAction.js @@ -21,15 +21,13 @@ export const setAddEditCaseNoteModalStateFromDetailAction = ({ docketNumberSuffix, } = get(state.caseDetail); - const caseCaptionNames = applicationContext.getCaseCaptionNames( - caseCaption || '', - ); + const caseTitle = applicationContext.getCaseTitle(caseCaption || ''); store.set( state.modal.docketNumber, `${docketNumber}${docketNumberSuffix ? docketNumberSuffix : ''}`, ); - store.set(state.modal.caseCaptionNames, caseCaptionNames); + store.set(state.modal.caseTitle, caseTitle); store.set(state.modal.caseId, caseId); store.set(state.modal.notes, caseNote); }; diff --git a/web-client/src/presenter/actions/CaseDetail/setAddEditCaseNoteModalStateFromDetailAction.test.js b/web-client/src/presenter/actions/CaseDetail/setAddEditCaseNoteModalStateFromDetailAction.test.js index 08fecb6d4c5..029c50aaa2d 100644 --- a/web-client/src/presenter/actions/CaseDetail/setAddEditCaseNoteModalStateFromDetailAction.test.js +++ b/web-client/src/presenter/actions/CaseDetail/setAddEditCaseNoteModalStateFromDetailAction.test.js @@ -24,7 +24,7 @@ describe('setAddEditCaseNoteModalStateFromDetailAction', () => { }, }, ); - expect(result.state.modal.caseCaptionNames).toEqual('Sisqo'); + expect(result.state.modal.caseTitle).toEqual('Sisqo'); expect(result.state.modal.caseId).toEqual( 'c54ba5a9-b37b-479d-9201-067ec6e335bb', ); @@ -48,7 +48,7 @@ describe('setAddEditCaseNoteModalStateFromDetailAction', () => { }, }, ); - expect(result.state.modal.caseCaptionNames).toEqual(''); + expect(result.state.modal.caseTitle).toEqual(''); expect(result.state.modal.caseId).toEqual( 'c54ba5a9-b37b-479d-9201-067ec6e335bb', ); diff --git a/web-client/src/presenter/actions/CourtIssuedDocketEntry/clearCourtIssuedDocketEntryFormValuesAction.js b/web-client/src/presenter/actions/CourtIssuedDocketEntry/clearCourtIssuedDocketEntryFormValuesAction.js index 28f126474f7..61cfc9182b6 100644 --- a/web-client/src/presenter/actions/CourtIssuedDocketEntry/clearCourtIssuedDocketEntryFormValuesAction.js +++ b/web-client/src/presenter/actions/CourtIssuedDocketEntry/clearCourtIssuedDocketEntryFormValuesAction.js @@ -15,6 +15,7 @@ export const clearCourtIssuedDocketEntryFormValuesAction = ({ store.unset(state.form.freeText); store.unset(state.form.judge); store.unset(state.form.docketNumbers); + store.unset(state.form.trialLocation); store.unset(state.form.month); store.unset(state.form.day); store.unset(state.form.year); diff --git a/web-client/src/presenter/actions/CourtIssuedDocketEntry/clearCourtIssuedDocketEntryFormValuesAction.test.js b/web-client/src/presenter/actions/CourtIssuedDocketEntry/clearCourtIssuedDocketEntryFormValuesAction.test.js index 3b766cba771..c6e4c4b6ad2 100644 --- a/web-client/src/presenter/actions/CourtIssuedDocketEntry/clearCourtIssuedDocketEntryFormValuesAction.test.js +++ b/web-client/src/presenter/actions/CourtIssuedDocketEntry/clearCourtIssuedDocketEntryFormValuesAction.test.js @@ -21,6 +21,7 @@ describe('clearCourtIssuedDocketEntryFormValuesAction', () => { freeText: 'something', judge: 'Judge Armen', month: '12', + trialLocation: 'Boise, Idaho', year: '2012', }, }, @@ -37,6 +38,7 @@ describe('clearCourtIssuedDocketEntryFormValuesAction', () => { freeText: 'something', judge: 'Judge Armen', month: '12', + trialLocation: 'Boise, Idaho', year: '2012', }; diff --git a/web-client/src/presenter/actions/CourtIssuedOrder/createOrderAction.js b/web-client/src/presenter/actions/CourtIssuedOrder/createOrderAction.js index 7e0db2b936a..2bcea6b2f79 100644 --- a/web-client/src/presenter/actions/CourtIssuedOrder/createOrderAction.js +++ b/web-client/src/presenter/actions/CourtIssuedOrder/createOrderAction.js @@ -24,11 +24,11 @@ export const createOrderAction = async ({ applicationContext, get }) => { const caseDetail = get(state.caseDetail); const caseCaption = caseDetail.caseCaption || ''; const isOrderEvent = get(state.form.eventCode) == 'NOT'; // 'NOT' === 'notice' - let caseCaptionNames = applicationContext.getCaseCaptionNames(caseCaption); + let caseTitle = applicationContext.getCaseTitle(caseCaption); let caseCaptionExtension = ''; - if (caseCaptionNames !== caseCaption) { - caseCaptionNames += ', '; - caseCaptionExtension = caseCaption.replace(caseCaptionNames, ''); + if (caseTitle !== caseCaption) { + caseTitle += ', '; + caseCaptionExtension = caseCaption.replace(caseTitle, ''); } let signatureForNotice = ''; if (isOrderEvent) { @@ -42,7 +42,7 @@ export const createOrderAction = async ({ applicationContext, get }) => { const doc = replaceWithID( { '#caseCaptionExtension': caseCaptionExtension, - '#caseCaptionNames': caseCaptionNames, + '#caseTitle': caseTitle, '#docketNumber': docketNumberWithSuffix, '#orderBody': richText, '#orderTitleHeader': documentTitle, diff --git a/web-client/src/presenter/actions/CourtIssuedOrder/createOrderAction.test.js b/web-client/src/presenter/actions/CourtIssuedOrder/createOrderAction.test.js index 3ec215ebcc0..38515c5c9cd 100644 --- a/web-client/src/presenter/actions/CourtIssuedOrder/createOrderAction.test.js +++ b/web-client/src/presenter/actions/CourtIssuedOrder/createOrderAction.test.js @@ -35,7 +35,7 @@ describe('createOrderAction', () => { }, }); - expect(applicationContextForClient.getCaseCaptionNames).toBeCalled(); + expect(applicationContextForClient.getCaseTitle).toBeCalled(); expect(applicationContextForClient.getPdfStyles).toBeCalled(); expect(result.output.htmlString.indexOf('Guy Fieri')).toBeTruthy(); expect( @@ -62,7 +62,7 @@ describe('createOrderAction', () => { }, }); - expect(applicationContextForClient.getCaseCaptionNames).toBeCalled(); + expect(applicationContextForClient.getCaseTitle).toBeCalled(); expect(applicationContextForClient.getPdfStyles).toBeCalled(); expect( applicationContextForClient.getClerkOfCourtNameForSigning, diff --git a/web-client/src/presenter/actions/CourtIssuedOrder/getPdfFromUrlAction.js b/web-client/src/presenter/actions/CourtIssuedOrder/getPdfFromUrlAction.js new file mode 100644 index 00000000000..fa3a35473f4 --- /dev/null +++ b/web-client/src/presenter/actions/CourtIssuedOrder/getPdfFromUrlAction.js @@ -0,0 +1,12 @@ +/** + * Retrieves a pdf from persistence from the signed url provided + * + * @param {object} providers the providers object + * @param {object} providers.props the passed in props + * @returns {object} the pdf file + */ +export const getPdfFromUrlAction = async ({ applicationContext, props }) => { + return await applicationContext + .getUseCases() + .getPdfFromUrlInteractor({ applicationContext, pdfUrl: props.pdfUrl }); +}; diff --git a/web-client/src/presenter/actions/CourtIssuedOrder/getPdfFromUrlAction.test.js b/web-client/src/presenter/actions/CourtIssuedOrder/getPdfFromUrlAction.test.js new file mode 100644 index 00000000000..ee1e47b9e1e --- /dev/null +++ b/web-client/src/presenter/actions/CourtIssuedOrder/getPdfFromUrlAction.test.js @@ -0,0 +1,34 @@ +import { applicationContextForClient as applicationContext } from '../../../../../shared/src/business/test/createTestApplicationContext'; +import { getPdfFromUrlAction } from './getPdfFromUrlAction'; +import { presenter } from '../../presenter-mock'; +import { runAction } from 'cerebral/test'; + +describe('getPdfFromUrlAction', () => { + beforeAll(() => { + presenter.providers.applicationContext = applicationContext; + }); + + it('should get the pdf from the provided url', async () => { + const mockPdfUrl = 'www.example.com'; + const mockFile = { + name: 'mockfile.pdf', + }; + applicationContext + .getUseCases() + .getPdfFromUrlInteractor.mockReturnValue(mockFile); + + const result = await runAction(getPdfFromUrlAction, { + modules: { + presenter, + }, + props: { + pdfUrl: mockPdfUrl, + }, + }); + + expect(result.output).toMatchObject(mockFile); + expect( + applicationContext.getUseCases().getPdfFromUrlInteractor, + ).toBeCalled(); + }); +}); diff --git a/web-client/src/presenter/actions/CourtIssuedOrder/getPdfFileAction.js b/web-client/src/presenter/actions/CourtIssuedOrder/getPdfUrlAction.js similarity index 57% rename from web-client/src/presenter/actions/CourtIssuedOrder/getPdfFileAction.js rename to web-client/src/presenter/actions/CourtIssuedOrder/getPdfUrlAction.js index c655a8d0379..4679ef4e3c4 100644 --- a/web-client/src/presenter/actions/CourtIssuedOrder/getPdfFileAction.js +++ b/web-client/src/presenter/actions/CourtIssuedOrder/getPdfUrlAction.js @@ -1,21 +1,15 @@ import { state } from 'cerebral'; /** - * get the pdf file and pdf blob url from the passed in htmlString + * get the url of the pdf created from the passed in html string * * @param {object} providers the providers object * @param {Function} providers.get the cerebral get function * @param {object} providers.props the passed in props - * @returns {object} pdfFile, pdfUrl + * @returns {object} pdfUrl */ -export const getPdfFileAction = async ({ - applicationContext, - get, - props, - router, -}) => { +export const getPdfUrlAction = async ({ applicationContext, get, props }) => { const { htmlString } = props; - const documentTitle = get(state.form.documentTitle); const caseDetail = get(state.caseDetail); if (!htmlString) { @@ -26,7 +20,9 @@ export const getPdfFileAction = async ({ .getUtilities() .formatDocketNumberWithSuffix(caseDetail); - const pdfBlob = await applicationContext + const { + url, + } = await applicationContext .getUseCases() .createCourtIssuedOrderPdfFromHtmlInteractor({ applicationContext, @@ -34,10 +30,5 @@ export const getPdfFileAction = async ({ htmlString, }); - const pdfFile = new File([pdfBlob], documentTitle, { - type: 'application/pdf', - }); - const pdfUrl = router.createObjectURL(pdfFile); - - return { pdfFile, pdfUrl }; + return { pdfUrl: url }; }; diff --git a/web-client/src/presenter/actions/CourtIssuedOrder/getPdfFileAction.test.js b/web-client/src/presenter/actions/CourtIssuedOrder/getPdfUrlAction.test.js similarity index 68% rename from web-client/src/presenter/actions/CourtIssuedOrder/getPdfFileAction.test.js rename to web-client/src/presenter/actions/CourtIssuedOrder/getPdfUrlAction.test.js index 35a9c9b1ce2..c919dd28b2a 100644 --- a/web-client/src/presenter/actions/CourtIssuedOrder/getPdfFileAction.test.js +++ b/web-client/src/presenter/actions/CourtIssuedOrder/getPdfUrlAction.test.js @@ -1,9 +1,9 @@ import { applicationContextForClient } from '../../../../../shared/src/business/test/createTestApplicationContext'; -import { getPdfFileAction } from './getPdfFileAction'; +import { getPdfUrlAction } from './getPdfUrlAction'; import { presenter } from '../../presenter-mock'; import { runAction } from 'cerebral/test'; -describe('getPdfFileAction', () => { +describe('getPdfUrlAction', () => { let createObjectURLStub; beforeAll(() => { @@ -18,15 +18,20 @@ describe('getPdfFileAction', () => { it('throws error if htmlString is empty', async () => { await expect( - runAction(getPdfFileAction, { + runAction(getPdfUrlAction, { props: { htmlString: '' }, state: {}, }), ).rejects.toThrow(); }); - it('gets the pdf file/blob for a court issued document', async () => { - await runAction(getPdfFileAction, { + it('gets the pdf file url for a court issued document', async () => { + const mockPdf = { url: 'www.example.com' }; + applicationContextForClient + .getUseCases() + .createCourtIssuedOrderPdfFromHtmlInteractor.mockReturnValue(mockPdf); + + const result = await runAction(getPdfUrlAction, { modules: { presenter, }, @@ -41,7 +46,6 @@ describe('getPdfFileAction', () => { expect( applicationContextForClient.getUtilities().formatDocketNumberWithSuffix, ).toBeCalled(); - expect(createObjectURLStub).toBeCalled(); - expect(global.File).toBeCalled(); + expect(result.output.pdfUrl).toBe(mockPdf.url); }); }); diff --git a/web-client/src/presenter/actions/CourtIssuedOrder/navigateToPrintPreviewAction.js b/web-client/src/presenter/actions/CourtIssuedOrder/navigateToPrintPreviewAction.js deleted file mode 100644 index ceb9fba9348..00000000000 --- a/web-client/src/presenter/actions/CourtIssuedOrder/navigateToPrintPreviewAction.js +++ /dev/null @@ -1,20 +0,0 @@ -import { state } from 'cerebral'; - -/** - * changes the route to view the print preview of a document related to the caseId - * - * @param {object} providers the providers object - * @param {object} providers.get the cerebral get method - * @param {object} providers.props the cerebral props that contain the props.caseId - * @param {object} providers.router the riot.router object that is used for changing the route - * @returns {Promise} async action - */ -export const navigateToPrintPreviewAction = async ({ get, props, router }) => { - const caseId = - props.caseId || - (props.caseDetail - ? props.caseDetail.caseId - : get(state.caseDetail.docketNumber)); - - await router.route(`/print-preview/${caseId}`); -}; diff --git a/web-client/src/presenter/actions/CourtIssuedOrder/navigateToPrintPreviewAction.test.js b/web-client/src/presenter/actions/CourtIssuedOrder/navigateToPrintPreviewAction.test.js deleted file mode 100644 index d4f6176c599..00000000000 --- a/web-client/src/presenter/actions/CourtIssuedOrder/navigateToPrintPreviewAction.test.js +++ /dev/null @@ -1,47 +0,0 @@ -import { navigateToPrintPreviewAction } from './navigateToPrintPreviewAction'; -import { presenter } from '../../presenter-mock'; -import { runAction } from 'cerebral/test'; - -describe('navigateToPrintPreviewAction', () => { - it('navigates to the print preview URL with props.caseId', async () => { - const routeStub = jest.fn().mockResolvedValue(true); - presenter.providers.router = { route: routeStub }; - await runAction(navigateToPrintPreviewAction, { - modules: { - presenter, - }, - props: { - caseId: '123-19', - }, - }); - expect(routeStub).toHaveBeenCalledWith('/print-preview/123-19'); - }); - - it('navigates to the print preview URL with props.caseDetail.caseId', async () => { - const routeStub = jest.fn().mockResolvedValue(true); - presenter.providers.router = { route: routeStub }; - await runAction(navigateToPrintPreviewAction, { - modules: { - presenter, - }, - props: { - caseDetail: { caseId: '123-19' }, - }, - }); - expect(routeStub).toHaveBeenCalledWith('/print-preview/123-19'); - }); - - it('navigates to the print preview URL with state.caseDetail.docketNumber', async () => { - const routeStub = jest.fn().mockResolvedValue(true); - presenter.providers.router = { route: routeStub }; - await runAction(navigateToPrintPreviewAction, { - modules: { - presenter, - }, - state: { - caseDetail: { docketNumber: '123-19' }, - }, - }); - expect(routeStub).toHaveBeenCalledWith('/print-preview/123-19'); - }); -}); diff --git a/web-client/src/presenter/actions/CourtIssuedOrder/shouldRefreshOrderPdfAction.js b/web-client/src/presenter/actions/CourtIssuedOrder/shouldRefreshOrderPdfAction.js deleted file mode 100644 index bf8e35adf9f..00000000000 --- a/web-client/src/presenter/actions/CourtIssuedOrder/shouldRefreshOrderPdfAction.js +++ /dev/null @@ -1,18 +0,0 @@ -import { state } from 'cerebral'; - -/** - * returns path.yes if the currentTab is preview to refresh the order pdf; returns no otherwise - * - * @param {object} providers the providers object - * @param {Function} providers.get the cerebral get function - * @param {object} providers.path the cerebral path object - * @returns {Function} the path to take in the sequence - */ -export const shouldRefreshOrderPdfAction = ({ get, path }) => { - const currentTab = get(state.createOrderTab); - - if (currentTab === 'preview') { - return path.yes(); - } - return path.no(); -}; diff --git a/web-client/src/presenter/actions/CourtIssuedOrder/shouldRefreshOrderPdfAction.test.js b/web-client/src/presenter/actions/CourtIssuedOrder/shouldRefreshOrderPdfAction.test.js deleted file mode 100644 index 488ff326335..00000000000 --- a/web-client/src/presenter/actions/CourtIssuedOrder/shouldRefreshOrderPdfAction.test.js +++ /dev/null @@ -1,35 +0,0 @@ -import { presenter } from '../../presenter-mock'; -import { runAction } from 'cerebral/test'; -import { shouldRefreshOrderPdfAction } from './shouldRefreshOrderPdfAction'; - -describe('shouldRefreshOrderPdfAction', () => { - const noStub = jest.fn(); - const yesStub = jest.fn(); - - beforeAll(() => { - presenter.providers.path = { - no: noStub, - yes: yesStub, - }; - }); - - it('should return path.yes if createOrderTab is preview', async () => { - await runAction(shouldRefreshOrderPdfAction, { - modules: { presenter }, - state: { createOrderTab: 'preview' }, - }); - - expect(yesStub).toBeCalled(); - expect(noStub).not.toBeCalled(); - }); - - it('should return path.no if createOrderTab is not preview', async () => { - await runAction(shouldRefreshOrderPdfAction, { - modules: { presenter }, - state: { createOrderTab: 'generate' }, - }); - - expect(noStub).toBeCalled(); - expect(yesStub).not.toBeCalled(); - }); -}); diff --git a/web-client/src/presenter/actions/EditDocketRecord/setDocketEntryFormForDocketEditAction.js b/web-client/src/presenter/actions/EditDocketRecord/setDocketEntryFormForDocketEditAction.js index 7584bfe78c3..fe8ce13b693 100644 --- a/web-client/src/presenter/actions/EditDocketRecord/setDocketEntryFormForDocketEditAction.js +++ b/web-client/src/presenter/actions/EditDocketRecord/setDocketEntryFormForDocketEditAction.js @@ -11,6 +11,7 @@ import { state } from 'cerebral'; * @returns {void} sets state for docket entry edit */ export const setDocketEntryFormForDocketEditAction = ({ + applicationContext, get, props, store, @@ -35,6 +36,16 @@ export const setDocketEntryFormForDocketEditAction = ({ } } + if (docketEntryFormData.date) { + const deconstructedDate = applicationContext + .getUtilities() + .deconstructDate(docketEntryFormData.date); + docketEntryFormData = { + ...docketEntryFormData, + ...deconstructedDate, + }; + } + docketEntryFormData.lodged = !!docketEntryFormData.lodged; store.set(state.form, docketEntryFormData); diff --git a/web-client/src/presenter/actions/EditDocketRecord/setDocketEntryFormForDocketEditAction.test.js b/web-client/src/presenter/actions/EditDocketRecord/setDocketEntryFormForDocketEditAction.test.js index 2b8210c295b..6f042a32428 100644 --- a/web-client/src/presenter/actions/EditDocketRecord/setDocketEntryFormForDocketEditAction.test.js +++ b/web-client/src/presenter/actions/EditDocketRecord/setDocketEntryFormForDocketEditAction.test.js @@ -9,6 +9,7 @@ describe('setDocketEntryFormForDocketEditAction', () => { it("sets the given document's edit state on form.state", async () => { const editState = { caseId: '123', + date: '2020-01-01T05:00:00.000Z', documentId: '123-abc-123-abc', eventCode: 'OPP', lodged: true, @@ -16,6 +17,7 @@ describe('setDocketEntryFormForDocketEditAction', () => { }; const result = await runAction(setDocketEntryFormForDocketEditAction, { + modules: { presenter }, props: { documentId: '123-abc-123-abc', }, @@ -43,10 +45,14 @@ describe('setDocketEntryFormForDocketEditAction', () => { const expectedResult = { caseId: '123', + date: '2020-01-01T05:00:00.000Z', + day: '1', documentId: '123-abc-123-abc', eventCode: 'OPP', lodged: true, + month: '1', testKey: 'testValue', + year: '2020', }; expect(result.state.form).toEqual(expectedResult); @@ -62,6 +68,7 @@ describe('setDocketEntryFormForDocketEditAction', () => { }; const result = await runAction(setDocketEntryFormForDocketEditAction, { + modules: { presenter }, props: { documentId: '123-abc-123-abc', }, @@ -99,6 +106,7 @@ describe('setDocketEntryFormForDocketEditAction', () => { it('sets an empty object on form.state if no document matches the given documentId', async () => { const result = await runAction(setDocketEntryFormForDocketEditAction, { + modules: { presenter }, props: { documentId: '111-aaa-111-aaa', }, diff --git a/web-client/src/presenter/actions/EditDocketRecordEntry/setDocketEntryMetaFormForEditAction.js b/web-client/src/presenter/actions/EditDocketRecordEntry/setDocketEntryMetaFormForEditAction.js index cd26eec9908..e75ee943243 100644 --- a/web-client/src/presenter/actions/EditDocketRecordEntry/setDocketEntryMetaFormForEditAction.js +++ b/web-client/src/presenter/actions/EditDocketRecordEntry/setDocketEntryMetaFormForEditAction.js @@ -26,9 +26,13 @@ export const setDocketEntryMetaFormForEditAction = ({ if (date) { const { day, month, year } = deconstructDate(date); - deconstructedDate[`${fieldName}Day`] = day; - deconstructedDate[`${fieldName}Month`] = month; - deconstructedDate[`${fieldName}Year`] = year; + const dayFieldName = fieldName ? `${fieldName}Day` : 'day'; + const monthFieldName = fieldName ? `${fieldName}Month` : 'month'; + const yearFieldName = fieldName ? `${fieldName}Year` : 'year'; + + deconstructedDate[dayFieldName] = day; + deconstructedDate[monthFieldName] = month; + deconstructedDate[yearFieldName] = year; } return deconstructedDate; }; @@ -40,16 +44,16 @@ export const setDocketEntryMetaFormForEditAction = ({ store.set(state.docketRecordIndex, docketRecordIndex); if (docketRecordEntry.documentId) { - const documentDetail = documents.find( - document => docketRecordEntry.documentId === document.documentId, - ); + const documentDetail = + documents.find( + document => docketRecordEntry.documentId === document.documentId, + ) || {}; // TODO: Abstract this (also in getFormattedCaseDetail) if (docketRecordEntry.servedPartiesCode) { documentDetail.servedPartiesCode = docketRecordEntry.servedPartiesCode; } else { if ( - documentDetail && !!documentDetail.servedAt && documentDetail.servedParties && documentDetail.servedParties.length > 0 @@ -66,14 +70,14 @@ export const setDocketEntryMetaFormForEditAction = ({ ...documentDetail, lodged: !!documentDetail.lodged, ...deconstructDateWrapper( - (documentDetail && documentDetail.filingDate) || - docketRecordEntry.filingDate, + documentDetail.filingDate || docketRecordEntry.filingDate, 'filingDate', ), ...deconstructDateWrapper( - documentDetail && documentDetail.certificateOfServiceDate, + documentDetail.certificateOfServiceDate, 'certificateOfService', ), + ...deconstructDateWrapper(documentDetail.date), }); // TODO: add to unit test diff --git a/web-client/src/presenter/actions/EditDocketRecordEntry/setDocketEntryMetaFormForEditAction.test.js b/web-client/src/presenter/actions/EditDocketRecordEntry/setDocketEntryMetaFormForEditAction.test.js index bcd99474efd..f4d994724ad 100644 --- a/web-client/src/presenter/actions/EditDocketRecordEntry/setDocketEntryMetaFormForEditAction.test.js +++ b/web-client/src/presenter/actions/EditDocketRecordEntry/setDocketEntryMetaFormForEditAction.test.js @@ -43,7 +43,7 @@ describe('setDocketEntryMetaFormForEditAction', () => { filingDate: '2020-01-01', lodged: false, servedAt: '2020-01-01', - servedParties: [{}], + servedParties: [{ name: 'Party Man' }], }, { certificateOfService: true, diff --git a/web-client/src/presenter/actions/EditDocketRecordEntry/updateDocketEntryMetaAction.js b/web-client/src/presenter/actions/EditDocketRecordEntry/updateDocketEntryMetaAction.js index 3f1c1d3739c..7e39281a096 100644 --- a/web-client/src/presenter/actions/EditDocketRecordEntry/updateDocketEntryMetaAction.js +++ b/web-client/src/presenter/actions/EditDocketRecordEntry/updateDocketEntryMetaAction.js @@ -1,12 +1,13 @@ import { state } from 'cerebral'; /** - * update props from modal state to pass to through sequence + * calls use case to update docket entry meta * * @param {object} providers the providers object - * @param {object} providers.applicationContext the application context needed for getting the utility method - * @param {object} providers.path the cerebral path which contains the next path in the sequence (path of success or error) - * @returns {object} the new props + * @param {object} providers.applicationContext the application context + * @param {Function} providers.get the cerebral get function + * @param {object} providers.path the cerebral path which contains the next path in the sequence + * @returns {Function} the next path in the sequence */ export const updateDocketEntryMetaAction = async ({ applicationContext, diff --git a/web-client/src/presenter/actions/FileDocument/generatePrintableFilingReceiptAction.js b/web-client/src/presenter/actions/FileDocument/generatePrintableFilingReceiptAction.js index 927f3bbe46b..0b2f6048462 100644 --- a/web-client/src/presenter/actions/FileDocument/generatePrintableFilingReceiptAction.js +++ b/web-client/src/presenter/actions/FileDocument/generatePrintableFilingReceiptAction.js @@ -17,54 +17,14 @@ export const generatePrintableFilingReceiptAction = async ({ props, }) => { const { documentsFiled } = props; - const { Document } = applicationContext.getEntityConstructors(); - const caseDetail = get(state.caseDetail); - - const getDocumentInfo = documentData => { - const document = new Document(documentData, { applicationContext }); - document.generateFiledBy(caseDetail); - return { - attachments: document.attachments, - certificateOfService: document.certificateOfService, - certificateOfServiceDate: document.certificateOfServiceDate, - documentTitle: document.documentTitle, - filedBy: document.filedBy, - objections: document.objections, - receivedAt: document.receivedAt, - }; - }; - - const documents = { - caseId: documentsFiled.caseId, - docketNumber: documentsFiled.docketNumber, - primaryDocument: getDocumentInfo(documentsFiled), - supportingDocuments: [], - }; - - if (documentsFiled.hasSupportingDocuments) { - documents.supportingDocuments = documentsFiled.supportingDocuments.map( - supportingDocument => getDocumentInfo(supportingDocument), - ); - } - - if (documentsFiled.secondaryDocumentFile) { - documents.secondaryDocument = getDocumentInfo( - documentsFiled.secondaryDocument, - ); - } - - if (documentsFiled.hasSecondarySupportingDocuments) { - documents.secondarySupportingDocuments = documentsFiled.secondarySupportingDocuments.map( - secondarySupportingDocument => - getDocumentInfo(secondarySupportingDocument), - ); - } + const caseId = get(state.caseDetail.caseId); const filingReceiptUrl = await applicationContext .getUseCases() .generatePrintableFilingReceiptInteractor({ applicationContext, - documents, + caseId, + documentsFiled, }); return { printReceiptLink: filingReceiptUrl }; diff --git a/web-client/src/presenter/actions/FileDocument/generatePrintableFilingReceiptAction.test.js b/web-client/src/presenter/actions/FileDocument/generatePrintableFilingReceiptAction.test.js index c7cc6473233..bbe10d28e2d 100644 --- a/web-client/src/presenter/actions/FileDocument/generatePrintableFilingReceiptAction.test.js +++ b/web-client/src/presenter/actions/FileDocument/generatePrintableFilingReceiptAction.test.js @@ -30,90 +30,4 @@ describe('generatePrintableFilingReceiptAction', () => { applicationContext.getUseCases().generatePrintableFilingReceiptInteractor, ).toHaveBeenCalled(); }); - - it('should generate a receipt with supporting documents', async () => { - await runAction(generatePrintableFilingReceiptAction, { - modules: { - presenter, - }, - props: { - documentsFiled: { - caseId: '123', - docketNumber: '123-19', - hasSupportingDocuments: true, - primaryDocumentFile: {}, - supportingDocuments: [{}], - }, - }, - state: { - form: { - category: 'Motion', - documentType: 'Motion for Judgment on the Pleadings', - }, - }, - }); - - expect( - applicationContext.getUseCases().generatePrintableFilingReceiptInteractor - .mock.calls[0][0].documents, - ).toHaveProperty('supportingDocuments'); - }); - - it('should generate a receipt with a secondary document', async () => { - await runAction(generatePrintableFilingReceiptAction, { - modules: { - presenter, - }, - props: { - documentsFiled: { - caseId: '123', - docketNumber: '123-19', - primaryDocumentFile: {}, - secondaryDocument: {}, - secondaryDocumentFile: {}, - }, - }, - state: { - form: { - category: 'Motion', - documentType: 'Motion for Judgment on the Pleadings', - }, - }, - }); - - expect( - applicationContext.getUseCases().generatePrintableFilingReceiptInteractor - .mock.calls[0][0].documents, - ).toHaveProperty('secondaryDocument'); - }); - - it('should generate a receipt with secondary supporting documents', async () => { - await runAction(generatePrintableFilingReceiptAction, { - modules: { - presenter, - }, - props: { - documentsFiled: { - caseId: '123', - docketNumber: '123-19', - hasSecondarySupportingDocuments: true, - primaryDocumentFile: {}, - secondaryDocument: {}, - secondaryDocumentFile: {}, - secondarySupportingDocuments: [{}], - }, - }, - state: { - form: { - category: 'Motion', - documentType: 'Motion for Judgment on the Pleadings', - }, - }, - }); - - expect( - applicationContext.getUseCases().generatePrintableFilingReceiptInteractor - .mock.calls[0][0].documents, - ).toHaveProperty('secondarySupportingDocuments'); - }); }); diff --git a/web-client/src/presenter/actions/Public/generatePublicDocketRecordPdfUrlAction.js b/web-client/src/presenter/actions/Public/generatePublicDocketRecordPdfUrlAction.js index 16d7e561630..5c0ea4adc4a 100644 --- a/web-client/src/presenter/actions/Public/generatePublicDocketRecordPdfUrlAction.js +++ b/web-client/src/presenter/actions/Public/generatePublicDocketRecordPdfUrlAction.js @@ -1,29 +1,25 @@ import { state } from 'cerebral'; /** - * invokes the generate public docket record endpoint to get back the pdf + * invokes the generate public docket record endpoint to get back the pdf url * * @param {object} providers the providers object * @param {Function} providers.get the cerebral get function - * @param {object} providers.router the router objected needed to create an object url * @returns {object} the pdfUrl */ export const generatePublicDocketRecordPdfUrlAction = async ({ applicationContext, get, - router, }) => { const caseDetail = get(state.caseDetail); - const docketRecordPdf = await applicationContext + const { + url, + } = await applicationContext .getUseCases() .generatePublicDocketRecordPdfInteractor({ applicationContext, caseId: caseDetail.caseId, }); - const pdfFile = new Blob([docketRecordPdf], { type: 'application/pdf' }); - - const pdfUrl = router.createObjectURL(pdfFile); - - return { pdfUrl }; + return { pdfUrl: url }; }; diff --git a/web-client/src/presenter/actions/Public/generatePublicDocketRecordPdfUrlAction.test.js b/web-client/src/presenter/actions/Public/generatePublicDocketRecordPdfUrlAction.test.js index b18aec6348b..01420cf81ca 100644 --- a/web-client/src/presenter/actions/Public/generatePublicDocketRecordPdfUrlAction.test.js +++ b/web-client/src/presenter/actions/Public/generatePublicDocketRecordPdfUrlAction.test.js @@ -1,21 +1,19 @@ -import { applicationContextForClient } from '../../../../../shared/src/business/test/createTestApplicationContext'; +import { applicationContextForClient as applicationContext } from '../../../../../shared/src/business/test/createTestApplicationContext'; import { generatePublicDocketRecordPdfUrlAction } from './generatePublicDocketRecordPdfUrlAction'; import { presenter } from '../../presenter-public'; import { runAction } from 'cerebral/test'; describe('generatePublicDocketRecordPdfUrlAction', () => { - let createObjectURLStub; beforeAll(() => { - global.Blob = jest.fn(); - createObjectURLStub = jest.fn().mockReturnValue('pdf url'); - - presenter.providers.applicationContext = applicationContextForClient; - presenter.providers.router = { - createObjectURL: createObjectURLStub, - }; + presenter.providers.applicationContext = applicationContext; }); it('generates a public docket record pdf url', async () => { + const mockPdf = { url: 'www.example.com' }; + applicationContext + .getUseCases() + .generatePublicDocketRecordPdfInteractor.mockReturnValue(mockPdf); + const result = await runAction(generatePublicDocketRecordPdfUrlAction, { modules: { presenter, @@ -28,13 +26,10 @@ describe('generatePublicDocketRecordPdfUrlAction', () => { }); expect(result.output).toMatchObject({ - pdfUrl: 'pdf url', + pdfUrl: mockPdf.url, }); expect( - applicationContextForClient.getUseCases() - .generatePublicDocketRecordPdfInteractor, + applicationContext.getUseCases().generatePublicDocketRecordPdfInteractor, ).toBeCalled(); - expect(global.Blob).toBeCalled(); - expect(createObjectURLStub).toBeCalled(); }); }); diff --git a/web-client/src/presenter/actions/StartCaseInternal/canNavigateToReviewPetitionFromPaperScreenAction.js b/web-client/src/presenter/actions/StartCaseInternal/canNavigateToReviewPetitionFromPaperScreenAction.js deleted file mode 100644 index ba130659dde..00000000000 --- a/web-client/src/presenter/actions/StartCaseInternal/canNavigateToReviewPetitionFromPaperScreenAction.js +++ /dev/null @@ -1,8 +0,0 @@ -import { chooseByTruthyStateActionFactory } from '../editUploadCourtIssuedDocument/chooseByTruthyStateActionFactory'; - -/** - * allow navigation if the form is filled in. This is to prevent refresh staying on the page. - */ -export const canNavigateToReviewPetitionFromPaperScreenAction = chooseByTruthyStateActionFactory( - 'form.partyType', -); diff --git a/web-client/src/presenter/actions/StartCaseInternal/getInternalCaseCaptionForCaseInfoTabAction.js b/web-client/src/presenter/actions/StartCaseInternal/getCaseCaptionForCaseInfoTabAction.js similarity index 69% rename from web-client/src/presenter/actions/StartCaseInternal/getInternalCaseCaptionForCaseInfoTabAction.js rename to web-client/src/presenter/actions/StartCaseInternal/getCaseCaptionForCaseInfoTabAction.js index 8d0b16d888d..bd53d2e4f7d 100644 --- a/web-client/src/presenter/actions/StartCaseInternal/getInternalCaseCaptionForCaseInfoTabAction.js +++ b/web-client/src/presenter/actions/StartCaseInternal/getCaseCaptionForCaseInfoTabAction.js @@ -8,12 +8,14 @@ import { state } from 'cerebral'; * @param {Function} providers.get the cerebral get function * @returns {object} contains the caseCaption */ -export const getInternalCaseCaptionForCaseInfoTabAction = ({ +export const getCaseCaptionForCaseInfoTabAction = ({ applicationContext, get, }) => { - const { Case } = applicationContext.getEntityConstructors(); - let caseCaption = Case.getCaseCaption(get(state.form)) || ''; + const caseDetail = get(state.form); + + const caseCaption = + applicationContext.getUtilities().getCaseCaption(caseDetail) || ''; return { caseCaption }; }; diff --git a/web-client/src/presenter/actions/caseDetailEdit/getCaseCaptionForCaseInfoTabAction.test.js b/web-client/src/presenter/actions/StartCaseInternal/getCaseCaptionForCaseInfoTabAction.test.js similarity index 100% rename from web-client/src/presenter/actions/caseDetailEdit/getCaseCaptionForCaseInfoTabAction.test.js rename to web-client/src/presenter/actions/StartCaseInternal/getCaseCaptionForCaseInfoTabAction.test.js diff --git a/web-client/src/presenter/actions/StartCaseInternal/getInternalCaseCaptionForCaseInfoTabAction.test.js b/web-client/src/presenter/actions/StartCaseInternal/getInternalCaseCaptionForCaseInfoTabAction.test.js deleted file mode 100644 index 9fac3002273..00000000000 --- a/web-client/src/presenter/actions/StartCaseInternal/getInternalCaseCaptionForCaseInfoTabAction.test.js +++ /dev/null @@ -1,42 +0,0 @@ -import { applicationContextForClient as applicationContext } from '../../../../../shared/src/business/test/createTestApplicationContext.js'; -import { getInternalCaseCaptionForCaseInfoTabAction } from './getInternalCaseCaptionForCaseInfoTabAction'; -import { presenter } from '../../presenter-mock'; -import { runAction } from 'cerebral/test'; - -describe('getInternalCaseCaptionForCaseInfoTabAction', () => { - presenter.providers.applicationContext = applicationContext; - const { PARTY_TYPES } = applicationContext.getConstants(); - - it('should return an empty string when party type has not been selected', async () => { - const result = await runAction(getInternalCaseCaptionForCaseInfoTabAction, { - modules: { - presenter, - }, - state: { - form: { - partyType: '', - }, - }, - }); - - expect(result.output.caseCaption).toBe(''); - }); - - it('should return a generated case caption when party type has been selected', async () => { - const result = await runAction(getInternalCaseCaptionForCaseInfoTabAction, { - modules: { - presenter, - }, - state: { - form: { - contactPrimary: { - name: 'Carl Fredricksen', - }, - partyType: PARTY_TYPES.petitioner, - }, - }, - }); - - expect(result.output.caseCaption).toBe('Carl Fredricksen, Petitioner'); - }); -}); diff --git a/web-client/src/presenter/actions/StartCaseInternal/navigateToReviewPetitionFromPaperAction.js b/web-client/src/presenter/actions/StartCaseInternal/navigateToReviewPetitionFromPaperAction.js deleted file mode 100644 index 7f79cf96db4..00000000000 --- a/web-client/src/presenter/actions/StartCaseInternal/navigateToReviewPetitionFromPaperAction.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * changes the route to view the review-petition - * - * @param {object} providers the providers object - * @param {object} providers.router the riot.router object that is used for changing the route - * @returns {Promise} async action - */ -export const navigateToReviewPetitionFromPaperAction = async ({ router }) => { - await router.route('file-a-petition/review-petition'); -}; diff --git a/web-client/src/presenter/actions/StartCaseInternal/navigateToReviewPetitionFromPaperAction.test.js b/web-client/src/presenter/actions/StartCaseInternal/navigateToReviewPetitionFromPaperAction.test.js deleted file mode 100644 index 5d0e6cc7751..00000000000 --- a/web-client/src/presenter/actions/StartCaseInternal/navigateToReviewPetitionFromPaperAction.test.js +++ /dev/null @@ -1,25 +0,0 @@ -import { navigateToReviewPetitionFromPaperAction } from './navigateToReviewPetitionFromPaperAction'; -import { presenter } from '../../presenter-mock'; -import { runAction } from 'cerebral/test'; - -describe('navigateToReviewPetitionFromPaperAction', () => { - let routeStub; - - beforeAll(() => { - routeStub = jest.fn(); - - presenter.providers.router = { - route: routeStub, - }; - }); - - it('navigates to review petition url', async () => { - await runAction(navigateToReviewPetitionFromPaperAction, { - modules: { - presenter, - }, - }); - - expect(routeStub.mock.calls.length).toEqual(1); - }); -}); diff --git a/web-client/src/presenter/actions/caseDetailEdit/setCaseCaptionForCaseInfoTabAction.js b/web-client/src/presenter/actions/StartCaseInternal/setCaseCaptionForCaseInfoTabAction.js similarity index 100% rename from web-client/src/presenter/actions/caseDetailEdit/setCaseCaptionForCaseInfoTabAction.js rename to web-client/src/presenter/actions/StartCaseInternal/setCaseCaptionForCaseInfoTabAction.js diff --git a/web-client/src/presenter/actions/caseDetailEdit/setCaseCaptionForCaseInfoTabAction.test.js b/web-client/src/presenter/actions/StartCaseInternal/setCaseCaptionForCaseInfoTabAction.test.js similarity index 100% rename from web-client/src/presenter/actions/caseDetailEdit/setCaseCaptionForCaseInfoTabAction.test.js rename to web-client/src/presenter/actions/StartCaseInternal/setCaseCaptionForCaseInfoTabAction.test.js diff --git a/web-client/src/presenter/actions/StartCaseInternal/setInternalCaseCaptionForCaseInfoTabAction.js b/web-client/src/presenter/actions/StartCaseInternal/setInternalCaseCaptionForCaseInfoTabAction.js deleted file mode 100644 index 2b20a5190f7..00000000000 --- a/web-client/src/presenter/actions/StartCaseInternal/setInternalCaseCaptionForCaseInfoTabAction.js +++ /dev/null @@ -1,15 +0,0 @@ -import { state } from 'cerebral'; - -/** - * Sets the state.form.caseCaption to the props.caseCaption passed in. - * - * @param {object} providers the providers object - * @param {Function} providers.props the cerebral props object used for passing in props.caseCaption - * @param {Function} providers.store the cerebral store used for setting the state.form.caseCaption - */ -export const setInternalCaseCaptionForCaseInfoTabAction = ({ - props, - store, -}) => { - store.set(state.form.caseCaption, props.caseCaption); -}; diff --git a/web-client/src/presenter/actions/StartCaseInternal/setInternalCaseCaptionForCaseInfoTabAction.test.js b/web-client/src/presenter/actions/StartCaseInternal/setInternalCaseCaptionForCaseInfoTabAction.test.js deleted file mode 100644 index 10ffb86b237..00000000000 --- a/web-client/src/presenter/actions/StartCaseInternal/setInternalCaseCaptionForCaseInfoTabAction.test.js +++ /dev/null @@ -1,14 +0,0 @@ -import { runAction } from 'cerebral/test'; -import { setInternalCaseCaptionForCaseInfoTabAction } from './setInternalCaseCaptionForCaseInfoTabAction'; - -describe('setInternalCaseCaptionForCaseInfoTabAction', () => { - it('should set state.form.caseCaption to the passed in props.caseCaption if the tab is caseInfo', async () => { - const result = await runAction(setInternalCaseCaptionForCaseInfoTabAction, { - props: { - caseCaption: 'something something', - }, - }); - - expect(result.state.form.caseCaption).toEqual('something something'); - }); -}); diff --git a/web-client/src/presenter/actions/TrialSession/canSetTrialSessionToCalendarAction.js b/web-client/src/presenter/actions/TrialSession/canSetTrialSessionToCalendarAction.js index b9d22bc9274..eb4694794ba 100644 --- a/web-client/src/presenter/actions/TrialSession/canSetTrialSessionToCalendarAction.js +++ b/web-client/src/presenter/actions/TrialSession/canSetTrialSessionToCalendarAction.js @@ -15,7 +15,10 @@ export const canSetTrialSessionToCalendarAction = async ({ path, }) => { const trialSession = get(state.trialSession); - const canSetAsCalendared = applicationContext + const { + canSetAsCalendared, + emptyFields, + } = applicationContext .getUseCases() .canSetTrialSessionAsCalendaredInteractor({ applicationContext, @@ -26,11 +29,6 @@ export const canSetTrialSessionToCalendarAction = async ({ return path.yes(); } - const { TrialSession } = applicationContext.getEntityConstructors(); - const trialSessionEntity = new TrialSession(trialSession, { - applicationContext, - }); - const emptyFields = trialSessionEntity.getEmptyFields(); const addressProperties = ['address1', 'city', 'state', 'postalCode']; const missingAddressProperties = addressProperties.filter(property => emptyFields.includes(property), diff --git a/web-client/src/presenter/actions/TrialSession/canSetTrialSessionToCalendarAction.test.js b/web-client/src/presenter/actions/TrialSession/canSetTrialSessionToCalendarAction.test.js index 6b86059c55c..06f897353ef 100644 --- a/web-client/src/presenter/actions/TrialSession/canSetTrialSessionToCalendarAction.test.js +++ b/web-client/src/presenter/actions/TrialSession/canSetTrialSessionToCalendarAction.test.js @@ -1,4 +1,4 @@ -import { TrialSession } from '../../../../../shared/src/business/entities/trialSessions/TrialSession'; +import { applicationContextForClient as applicationContext } from '../../../../../shared/src/business/test/createTestApplicationContext'; import { canSetTrialSessionToCalendarAction } from './canSetTrialSessionToCalendarAction'; import { presenter } from '../../presenter-mock'; import { runAction } from 'cerebral/test'; @@ -13,24 +13,14 @@ const VALID_TRIAL_SESSION = { }; describe('canSetTrialSessionToCalendarAction', () => { - let canSetTrialSessionAsCalendaredInteractorStub; let pathNoStub; let pathYesStub; beforeAll(() => { - canSetTrialSessionAsCalendaredInteractorStub = jest.fn(); pathNoStub = jest.fn(); pathYesStub = jest.fn(); - presenter.providers.applicationContext = { - getEntityConstructors: () => ({ - TrialSession, - }), - getUniqueId: () => 'easy-as-abc-123', - getUseCases: () => ({ - canSetTrialSessionAsCalendaredInteractor: canSetTrialSessionAsCalendaredInteractorStub, - }), - }; + presenter.providers.applicationContext = applicationContext; presenter.providers.path = { no: pathNoStub, @@ -39,7 +29,12 @@ describe('canSetTrialSessionToCalendarAction', () => { }); it('should return the no path when the trial session address is not valid and a judge has not been selected', async () => { - canSetTrialSessionAsCalendaredInteractorStub.mockReturnValue(false); + applicationContext + .getUseCases() + .canSetTrialSessionAsCalendaredInteractor.mockReturnValue({ + canSetAsCalendared: false, + emptyFields: ['address1', 'judge'], + }); await runAction(canSetTrialSessionToCalendarAction, { modules: { @@ -55,7 +50,9 @@ describe('canSetTrialSessionToCalendarAction', () => { }, }); - expect(canSetTrialSessionAsCalendaredInteractorStub).toHaveBeenCalled(); + expect( + applicationContext.getUseCases().canSetTrialSessionAsCalendaredInteractor, + ).toHaveBeenCalled(); expect(pathNoStub).toHaveBeenCalledWith({ alertWarning: { message: 'Provide an address and a judge to set this trial session.', @@ -64,7 +61,12 @@ describe('canSetTrialSessionToCalendarAction', () => { }); it('should return the no path when the trial session address is not valid', async () => { - canSetTrialSessionAsCalendaredInteractorStub.mockReturnValue(false); + applicationContext + .getUseCases() + .canSetTrialSessionAsCalendaredInteractor.mockReturnValue({ + canSetAsCalendared: false, + emptyFields: ['address1'], + }); await runAction(canSetTrialSessionToCalendarAction, { modules: { @@ -81,7 +83,9 @@ describe('canSetTrialSessionToCalendarAction', () => { }, }); - expect(canSetTrialSessionAsCalendaredInteractorStub).toHaveBeenCalled(); + expect( + applicationContext.getUseCases().canSetTrialSessionAsCalendaredInteractor, + ).toHaveBeenCalled(); expect(pathNoStub).toHaveBeenCalledWith({ alertWarning: { message: 'Provide an address to set this trial session.', @@ -90,7 +94,12 @@ describe('canSetTrialSessionToCalendarAction', () => { }); it('should return the no path when a judge has not been selected', async () => { - canSetTrialSessionAsCalendaredInteractorStub.mockReturnValue(false); + applicationContext + .getUseCases() + .canSetTrialSessionAsCalendaredInteractor.mockReturnValue({ + canSetAsCalendared: false, + emptyFields: ['judge'], + }); await runAction(canSetTrialSessionToCalendarAction, { modules: { @@ -108,7 +117,9 @@ describe('canSetTrialSessionToCalendarAction', () => { }, }); - expect(canSetTrialSessionAsCalendaredInteractorStub).toHaveBeenCalled(); + expect( + applicationContext.getUseCases().canSetTrialSessionAsCalendaredInteractor, + ).toHaveBeenCalled(); expect(pathNoStub).toHaveBeenCalledWith({ alertWarning: { message: 'Provide a judge to set this trial session.', @@ -117,7 +128,12 @@ describe('canSetTrialSessionToCalendarAction', () => { }); it('should return the yes path if all criteria for calendaring a trial session have been met', async () => { - canSetTrialSessionAsCalendaredInteractorStub.mockReturnValue(true); + applicationContext + .getUseCases() + .canSetTrialSessionAsCalendaredInteractor.mockReturnValue({ + canSetAsCalendared: true, + emptyFields: [], + }); await runAction(canSetTrialSessionToCalendarAction, { modules: { @@ -128,7 +144,9 @@ describe('canSetTrialSessionToCalendarAction', () => { }, }); - expect(canSetTrialSessionAsCalendaredInteractorStub).toHaveBeenCalled(); + expect( + applicationContext.getUseCases().canSetTrialSessionAsCalendaredInteractor, + ).toHaveBeenCalled(); expect(pathYesStub).toHaveBeenCalled(); }); }); diff --git a/web-client/src/presenter/actions/TrialSession/generateTrialCalendarPdfUrlAction.js b/web-client/src/presenter/actions/TrialSession/generateTrialCalendarPdfUrlAction.js index 8d486c17802..853cb16a976 100644 --- a/web-client/src/presenter/actions/TrialSession/generateTrialCalendarPdfUrlAction.js +++ b/web-client/src/presenter/actions/TrialSession/generateTrialCalendarPdfUrlAction.js @@ -1,6 +1,6 @@ import { state } from 'cerebral'; /** - * get the pdf file and pdf blob url from the passed in htmlString + * get the trial calendar pdf url * * @param {object} providers the providers object * @param {Function} providers.get the cerebral get function @@ -9,20 +9,17 @@ import { state } from 'cerebral'; export const generateTrialCalendarPdfUrlAction = async ({ applicationContext, get, - router, }) => { const trialSession = get(state.trialSession); - const trialCalendarPdf = await applicationContext + const { + url, + } = await applicationContext .getUseCases() .generateTrialCalendarPdfInteractor({ applicationContext, trialSessionId: trialSession.trialSessionId, }); - const pdfFile = new Blob([trialCalendarPdf], { type: 'application/pdf' }); - - const pdfUrl = router.createObjectURL(pdfFile); - - return { pdfUrl }; + return { pdfUrl: url }; }; diff --git a/web-client/src/presenter/actions/TrialSession/generateTrialCalendarPdfUrlAction.test.js b/web-client/src/presenter/actions/TrialSession/generateTrialCalendarPdfUrlAction.test.js index 0fc41dce7a9..c23545f6d03 100644 --- a/web-client/src/presenter/actions/TrialSession/generateTrialCalendarPdfUrlAction.test.js +++ b/web-client/src/presenter/actions/TrialSession/generateTrialCalendarPdfUrlAction.test.js @@ -4,26 +4,17 @@ import { presenter } from '../../presenter-mock'; import { runAction } from 'cerebral/test'; describe('generateTrialCalendarPdfUrlAction', () => { - let createObjectURLStub; - let fakeData = - 'JVBERi0xLjEKJcKlwrHDqwoKMSAwIG9iagogIDw8IC9UeXBlIC9DYXRhbG9nCiAgICAgL1BhZ2VzIDIgMCBSCiAgPj4KZW5kb2JqCgoyIDAgb2JqCiAgPDwgL1R5cGUgL1BhZ2VzCiAgICAgL0tpZHMgWzMgMCBSXQogICAgIC9Db3VudCAxCiAgICAgL01lZGlhQm94IFswIDAgMzAwIDE0NF0KICA+PgplbmRvYmoKCjMgMCBvYmoKICA8PCAgL1R5cGUgL1BhZ2UKICAgICAgL1BhcmVudCAyIDAgUgogICAgICAvUmVzb3VyY2VzCiAgICAgICA8PCAvRm9udAogICAgICAgICAgIDw8IC9GMQogICAgICAgICAgICAgICA8PCAvVHlwZSAvRm9udAogICAgICAgICAgICAgICAgICAvU3VidHlwZSAvVHlwZTEKICAgICAgICAgICAgICAgICAgL0Jhc2VGb250IC9UaW1lcy1Sb21hbgogICAgICAgICAgICAgICA+PgogICAgICAgICAgID4+CiAgICAgICA+PgogICAgICAvQ29udGVudHMgNCAwIFIKICA+PgplbmRvYmoKCjQgMCBvYmoKICA8PCAvTGVuZ3RoIDg0ID4+CnN0cmVhbQogIEJUCiAgICAvRjEgMTggVGYKICAgIDUgODAgVGQKICAgIChDb25ncmF0aW9ucywgeW91IGZvdW5kIHRoZSBFYXN0ZXIgRWdnLikgVGoKICBFVAplbmRzdHJlYW0KZW5kb2JqCgp4cmVmCjAgNQowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAwMTggMDAwMDAgbiAKMDAwMDAwMDA3NyAwMDAwMCBuIAowMDAwMDAwMTc4IDAwMDAwIG4gCjAwMDAwMDA0NTcgMDAwMDAgbiAKdHJhaWxlcgogIDw8ICAvUm9vdCAxIDAgUgogICAgICAvU2l6ZSA1CiAgPj4Kc3RhcnR4cmVmCjU2NQolJUVPRgo='; + const mockPdfUrl = { url: 'www.example.com' }; beforeAll(() => { - createObjectURLStub = jest.fn().mockReturnValue('pdf-url-123'); - global.window = global; - global.Blob = () => {}; - presenter.providers.applicationContext = applicationContext; - presenter.providers.router = { - createObjectURL: createObjectURLStub, - }; applicationContext .getUseCases() - .generateTrialCalendarPdfInteractor.mockResolvedValue(fakeData); + .generateTrialCalendarPdfInteractor.mockResolvedValue(mockPdfUrl); }); - it('generates trial calendar pdf url', async () => { + it('returns the trial calendar pdf url', async () => { const result = await runAction(generateTrialCalendarPdfUrlAction, { modules: { presenter, @@ -38,9 +29,8 @@ describe('generateTrialCalendarPdfUrlAction', () => { expect( applicationContext.getUseCases().generateTrialCalendarPdfInteractor, ).toHaveBeenCalled(); - expect(createObjectURLStub).toHaveBeenCalled(); expect(result.output).toMatchObject({ - pdfUrl: 'pdf-url-123', + pdfUrl: mockPdfUrl.url, }); }); }); diff --git a/web-client/src/presenter/actions/TrialSession/runTrialSessionPlanningReportAction.js b/web-client/src/presenter/actions/TrialSession/runTrialSessionPlanningReportAction.js index ba078a76664..4d6ed6e4cd0 100644 --- a/web-client/src/presenter/actions/TrialSession/runTrialSessionPlanningReportAction.js +++ b/web-client/src/presenter/actions/TrialSession/runTrialSessionPlanningReportAction.js @@ -10,11 +10,12 @@ import { state } from 'cerebral'; export const runTrialSessionPlanningReportAction = async ({ applicationContext, get, - router, }) => { const { term, year } = get(state.modal); - const planningReportPdf = await applicationContext + const { + url, + } = await applicationContext .getUseCases() .runTrialSessionPlanningReportInteractor({ applicationContext, @@ -22,9 +23,5 @@ export const runTrialSessionPlanningReportAction = async ({ year, }); - const pdfFile = new Blob([planningReportPdf], { type: 'application/pdf' }); - - const pdfUrl = router.createObjectURL(pdfFile); - - return { pdfUrl }; + return { pdfUrl: url }; }; diff --git a/web-client/src/presenter/actions/TrialSession/runTrialSessionPlanningReportAction.test.js b/web-client/src/presenter/actions/TrialSession/runTrialSessionPlanningReportAction.test.js index 9716e3bdd66..1831a40f08c 100644 --- a/web-client/src/presenter/actions/TrialSession/runTrialSessionPlanningReportAction.test.js +++ b/web-client/src/presenter/actions/TrialSession/runTrialSessionPlanningReportAction.test.js @@ -5,21 +5,15 @@ import { runTrialSessionPlanningReportAction } from './runTrialSessionPlanningRe describe('runTrialSessionPlanningReportAction', () => { beforeAll(() => { - global.window = global; - global.Blob = () => {}; - const fakeData = - 'JVBERi0xLjEKJcKlwrHDqwoKMSAwIG9iagogIDw8IC9UeXBlIC9DYXRhbG9nCiAgICAgL1BhZ2VzIDIgMCBSCiAgPj4KZW5kb2JqCgoyIDAgb2JqCiAgPDwgL1R5cGUgL1BhZ2VzCiAgICAgL0tpZHMgWzMgMCBSXQogICAgIC9Db3VudCAxCiAgICAgL01lZGlhQm94IFswIDAgMzAwIDE0NF0KICA+PgplbmRvYmoKCjMgMCBvYmoKICA8PCAgL1R5cGUgL1BhZ2UKICAgICAgL1BhcmVudCAyIDAgUgogICAgICAvUmVzb3VyY2VzCiAgICAgICA8PCAvRm9udAogICAgICAgICAgIDw8IC9GMQogICAgICAgICAgICAgICA8PCAvVHlwZSAvRm9udAogICAgICAgICAgICAgICAgICAvU3VidHlwZSAvVHlwZTEKICAgICAgICAgICAgICAgICAgL0Jhc2VGb250IC9UaW1lcy1Sb21hbgogICAgICAgICAgICAgICA+PgogICAgICAgICAgID4+CiAgICAgICA+PgogICAgICAvQ29udGVudHMgNCAwIFIKICA+PgplbmRvYmoKCjQgMCBvYmoKICA8PCAvTGVuZ3RoIDg0ID4+CnN0cmVhbQogIEJUCiAgICAvRjEgMTggVGYKICAgIDUgODAgVGQKICAgIChDb25ncmF0aW9ucywgeW91IGZvdW5kIHRoZSBFYXN0ZXIgRWdnLikgVGoKICBFVAplbmRzdHJlYW0KZW5kb2JqCgp4cmVmCjAgNQowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAwMTggMDAwMDAgbiAKMDAwMDAwMDA3NyAwMDAwMCBuIAowMDAwMDAwMTc4IDAwMDAwIG4gCjAwMDAwMDA0NTcgMDAwMDAgbiAKdHJhaWxlcgogIDw8ICAvUm9vdCAxIDAgUgogICAgICAvU2l6ZSA1CiAgPj4Kc3RhcnR4cmVmCjU2NQolJUVPRgo='; + const mockPdfUrl = 'www.example.com'; presenter.providers.applicationContext = applicationContext; - presenter.providers.router = { - createObjectURL: jest.fn().mockReturnValue('123456-abcdef'), - }; applicationContext .getUseCases() - .runTrialSessionPlanningReportInteractor.mockResolvedValue(fakeData); + .runTrialSessionPlanningReportInteractor.mockResolvedValue(mockPdfUrl); }); - it('creates a pdf and returns an object URL', async () => { + it('returns a url to the newly created report pdf', async () => { const result = await runAction(runTrialSessionPlanningReportAction, { modules: { presenter, @@ -34,7 +28,6 @@ describe('runTrialSessionPlanningReportAction', () => { expect( applicationContext.getUseCases().runTrialSessionPlanningReportInteractor, ).toHaveBeenCalled(); - expect(presenter.providers.router.createObjectURL).toHaveBeenCalled(); expect(result.output).toHaveProperty('pdfUrl'); }); }); diff --git a/web-client/src/presenter/actions/TrialSessionWorkingCopy/setAddEditUserCaseNoteModalStateFromDetailAction.js b/web-client/src/presenter/actions/TrialSessionWorkingCopy/setAddEditUserCaseNoteModalStateFromDetailAction.js index 3f821b0ff71..dbef6da1f31 100644 --- a/web-client/src/presenter/actions/TrialSessionWorkingCopy/setAddEditUserCaseNoteModalStateFromDetailAction.js +++ b/web-client/src/presenter/actions/TrialSessionWorkingCopy/setAddEditUserCaseNoteModalStateFromDetailAction.js @@ -21,15 +21,13 @@ export const setAddEditUserCaseNoteModalStateFromDetailAction = ({ const { caseCaption, docketNumber, docketNumberSuffix } = get( state.caseDetail, ); - const caseCaptionNames = applicationContext.getCaseCaptionNames( - caseCaption || '', - ); + const caseTitle = applicationContext.getCaseTitle(caseCaption || ''); store.set( state.modal.docketNumber, `${docketNumber}${docketNumberSuffix ? docketNumberSuffix : ''}`, ); - store.set(state.modal.caseCaptionNames, caseCaptionNames); + store.set(state.modal.caseTitle, caseTitle); store.set(state.modal.caseId, caseId); store.set(state.modal.notes, notes); }; diff --git a/web-client/src/presenter/actions/TrialSessionWorkingCopy/setAddEditUserCaseNoteModalStateFromDetailAction.test.js b/web-client/src/presenter/actions/TrialSessionWorkingCopy/setAddEditUserCaseNoteModalStateFromDetailAction.test.js index 154954ecec1..71a3fced9b5 100644 --- a/web-client/src/presenter/actions/TrialSessionWorkingCopy/setAddEditUserCaseNoteModalStateFromDetailAction.test.js +++ b/web-client/src/presenter/actions/TrialSessionWorkingCopy/setAddEditUserCaseNoteModalStateFromDetailAction.test.js @@ -25,7 +25,7 @@ describe('setAddEditUserCaseNoteModalStateFromDetailAction', () => { }, ); - expect(result.state.modal.caseCaptionNames).toEqual('Sisqo'); + expect(result.state.modal.caseTitle).toEqual('Sisqo'); expect(result.state.modal.caseId).toEqual( 'c54ba5a9-b37b-479d-9201-067ec6e335bb', ); @@ -50,7 +50,7 @@ describe('setAddEditUserCaseNoteModalStateFromDetailAction', () => { }, ); - expect(result.state.modal.caseCaptionNames).toEqual(''); + expect(result.state.modal.caseTitle).toEqual(''); expect(result.state.modal.caseId).toEqual( 'c54ba5a9-b37b-479d-9201-067ec6e335bb', ); diff --git a/web-client/src/presenter/actions/TrialSessionWorkingCopy/setAddEditUserCaseNoteModalStateFromListAction.js b/web-client/src/presenter/actions/TrialSessionWorkingCopy/setAddEditUserCaseNoteModalStateFromListAction.js index 1027e9a05bd..a9bd5ef6d93 100644 --- a/web-client/src/presenter/actions/TrialSessionWorkingCopy/setAddEditUserCaseNoteModalStateFromListAction.js +++ b/web-client/src/presenter/actions/TrialSessionWorkingCopy/setAddEditUserCaseNoteModalStateFromListAction.js @@ -28,11 +28,11 @@ export const setAddEditUserCaseNoteModalStateFromListAction = ({ caseId, }) || {}; - const caseCaptionNames = applicationContext.getCaseCaptionNames( + const caseTitle = applicationContext.getCaseTitle( caseDetail.caseCaption || '', ); - store.set(state.modal.caseCaptionNames, caseCaptionNames); + store.set(state.modal.caseTitle, caseTitle); store.set(state.modal.caseId, caseId); store.set(state.modal.notes, notes); }; diff --git a/web-client/src/presenter/actions/TrialSessionWorkingCopy/setAddEditUserCaseNoteModalStateFromListAction.test.js b/web-client/src/presenter/actions/TrialSessionWorkingCopy/setAddEditUserCaseNoteModalStateFromListAction.test.js index 4e66c460e1a..bf8b21388d0 100644 --- a/web-client/src/presenter/actions/TrialSessionWorkingCopy/setAddEditUserCaseNoteModalStateFromListAction.test.js +++ b/web-client/src/presenter/actions/TrialSessionWorkingCopy/setAddEditUserCaseNoteModalStateFromListAction.test.js @@ -35,14 +35,14 @@ describe('setAddEditUserCaseNoteModalStateFromListAction', () => { }, ); - expect(result.state.modal.caseCaptionNames).toEqual('Sisqo'); + expect(result.state.modal.caseTitle).toEqual('Sisqo'); expect(result.state.modal.caseId).toEqual( 'c54ba5a9-b37b-479d-9201-067ec6e335bb', ); expect(result.state.modal.notes).toEqual('i got some notes'); }); - it('defaults caseCaptionNames to empty string if the case is not on state.trialSession.calendaredCases', async () => { + it('defaults caseTitle to empty string if the case is not on state.trialSession.calendaredCases', async () => { const result = await runAction( setAddEditUserCaseNoteModalStateFromListAction, { @@ -66,7 +66,7 @@ describe('setAddEditUserCaseNoteModalStateFromListAction', () => { }, ); - expect(result.state.modal.caseCaptionNames).toEqual(''); + expect(result.state.modal.caseTitle).toEqual(''); expect(result.state.modal.caseId).toEqual( 'c54ba5a9-b37b-479d-9201-067ec6e335bb', ); diff --git a/web-client/src/presenter/actions/caseConsolidation/canConsolidateAction.js b/web-client/src/presenter/actions/caseConsolidation/canConsolidateAction.js index 76fb2b3b491..ebfdcf92da0 100644 --- a/web-client/src/presenter/actions/caseConsolidation/canConsolidateAction.js +++ b/web-client/src/presenter/actions/caseConsolidation/canConsolidateAction.js @@ -20,12 +20,10 @@ export const canConsolidateAction = async ({ }); } - const { Case } = applicationContext.getEntityConstructors(); - - const caseEntity = new Case(caseDetail, { applicationContext }); - - const results = caseEntity.getConsolidationStatus({ - caseEntity: caseToConsolidate, + const results = applicationContext.getUseCases().canConsolidateInteractor({ + applicationContext, + caseToConsolidate, + currentCase: caseDetail, }); if (results.canConsolidate) { diff --git a/web-client/src/presenter/actions/caseConsolidation/canConsolidateAction.test.js b/web-client/src/presenter/actions/caseConsolidation/canConsolidateAction.test.js index 0d665f6823e..af5ee6db959 100644 --- a/web-client/src/presenter/actions/caseConsolidation/canConsolidateAction.test.js +++ b/web-client/src/presenter/actions/caseConsolidation/canConsolidateAction.test.js @@ -1,4 +1,4 @@ -import { applicationContextForClient } from '../../../../../shared/src/business/test/createTestApplicationContext'; +import { applicationContextForClient as applicationContext } from '../../../../../shared/src/business/test/createTestApplicationContext'; import { canConsolidateAction } from './canConsolidateAction'; import { presenter } from '../../presenter-mock'; import { runAction } from 'cerebral/test'; @@ -6,27 +6,14 @@ import { runAction } from 'cerebral/test'; describe('canConsolidateAction', () => { let yesStub; let noStub; - let consolidationStub; beforeAll(() => { yesStub = jest.fn(); noStub = jest.fn(); - consolidationStub = jest.fn(); presenter.providers.path = { error: noStub, success: yesStub }; - const currentEntityConstructors = applicationContextForClient.getEntityConstructors(); - presenter.providers.applicationContext = { - ...applicationContextForClient, - getEntityConstructors: () => ({ - ...currentEntityConstructors, - Case: () => { - return { - getConsolidationStatus: consolidationStub, - }; - }, - }), - }; + presenter.providers.applicationContext = applicationContext; }); it('should return false when no case is confirmed', async () => { @@ -41,7 +28,7 @@ describe('canConsolidateAction', () => { }); it('should return false when cases are not consolidatable', async () => { - consolidationStub.mockReturnValue({ + applicationContext.getUseCases().canConsolidateInteractor.mockReturnValue({ canConsolidate: false, reason: 'Something', }); @@ -61,10 +48,11 @@ describe('canConsolidateAction', () => { }); it('should return yes when case is consolidatable', async () => { - consolidationStub.mockReturnValue({ + applicationContext.getUseCases().canConsolidateInteractor.mockReturnValue({ canConsolidate: true, reason: '', }); + await runAction(canConsolidateAction, { modules: { presenter, diff --git a/web-client/src/presenter/actions/caseConsolidation/getConsolidatedCasesByCaseAction.js b/web-client/src/presenter/actions/caseConsolidation/getConsolidatedCasesByCaseAction.js index 92b436cc6b9..3b5279e64e9 100644 --- a/web-client/src/presenter/actions/caseConsolidation/getConsolidatedCasesByCaseAction.js +++ b/web-client/src/presenter/actions/caseConsolidation/getConsolidatedCasesByCaseAction.js @@ -16,15 +16,16 @@ export const getConsolidatedCasesByCaseAction = async ({ let consolidatedCases = []; if (leadCaseId) { - consolidatedCases = await applicationContext + const unsortedConsolidatedCases = await applicationContext .getUseCases() .getConsolidatedCasesByCaseInteractor({ applicationContext, caseId: leadCaseId, }); - const { Case } = applicationContext.getEntityConstructors(); - consolidatedCases = Case.sortByDocketNumber(consolidatedCases); + consolidatedCases = unsortedConsolidatedCases.sort( + applicationContext.getUtilities().compareCasesByDocketNumber, + ); } return { consolidatedCases }; diff --git a/web-client/src/presenter/actions/caseDetailEdit/getCaseCaptionForCaseInfoTabAction.js b/web-client/src/presenter/actions/caseDetailEdit/getCaseCaptionForCaseInfoTabAction.js deleted file mode 100644 index d87cc448091..00000000000 --- a/web-client/src/presenter/actions/caseDetailEdit/getCaseCaptionForCaseInfoTabAction.js +++ /dev/null @@ -1,21 +0,0 @@ -import { state } from 'cerebral'; - -/** - * Fetches the case caption using the getCaseCaption helper method - * - * @param {object} providers the providers object - * @param {Function} providers.applicationContext application context to get Case entity - * @param {Function} providers.get the cerebral get function - * @returns {object} contains the caseCaption - */ -export const getCaseCaptionForCaseInfoTabAction = ({ - applicationContext, - get, -}) => { - const { Case } = applicationContext.getEntityConstructors(); - const caseCaption = Case.getCaseCaption(get(state.form)) || ''; - - // NOTE: case caption should never have the postfix value. Perhaps you're looking for case title? - - return { caseCaption }; -}; diff --git a/web-client/src/presenter/actions/caseDetailEdit/navigateToEditSavedPetitionAction.js b/web-client/src/presenter/actions/caseDetailEdit/navigateToEditSavedPetitionAction.js deleted file mode 100644 index 2854a09d449..00000000000 --- a/web-client/src/presenter/actions/caseDetailEdit/navigateToEditSavedPetitionAction.js +++ /dev/null @@ -1,28 +0,0 @@ -import { state } from 'cerebral'; - -/** - * changes the route to view the edit saved document detail - * - * @param {object} providers the providers object - * @param {object} providers.get cerebral get function - * @param {object} providers.props cerebral props object - * @param {object} providers.router the riot.router object that is used for changing the route - * @returns {Promise} async action - */ -export const navigateToEditSavedPetitionAction = async ({ - get, - props, - router, -}) => { - const documentId = get(state.documentId); - const docketNumber = get(state.form.docketNumber); - const { tab } = props; - - if (documentId && docketNumber) { - await router.route( - `/case-detail/${docketNumber}/documents/${documentId}/edit-saved${ - tab ? `?tab=${tab}` : '' - }`, - ); - } -}; diff --git a/web-client/src/presenter/actions/caseDetailEdit/navigateToEditSavedPetitionAction.test.js b/web-client/src/presenter/actions/caseDetailEdit/navigateToEditSavedPetitionAction.test.js deleted file mode 100644 index b44c9485ccf..00000000000 --- a/web-client/src/presenter/actions/caseDetailEdit/navigateToEditSavedPetitionAction.test.js +++ /dev/null @@ -1,75 +0,0 @@ -import { navigateToEditSavedPetitionAction } from './navigateToEditSavedPetitionAction'; -import { presenter } from '../../presenter-mock'; -import { runAction } from 'cerebral/test'; - -describe('navigateToEditSavedPetitionAction', () => { - let routeStub; - - beforeAll(() => { - routeStub = jest.fn(); - - presenter.providers.router = { - route: routeStub, - }; - }); - - it('navigates to the edit saved document detail view', async () => { - await runAction(navigateToEditSavedPetitionAction, { - modules: { presenter }, - state: { - documentId: 'document-id-123', - form: { - docketNumber: '101-12', - }, - }, - }); - - expect(routeStub.mock.calls[0][0]).toEqual( - '/case-detail/101-12/documents/document-id-123/edit-saved', - ); - }); - - it('navigates to the edit saved document detail view with the appropriate tab', async () => { - await runAction(navigateToEditSavedPetitionAction, { - modules: { presenter }, - props: { - tab: 'caseInfo', - }, - state: { - documentId: 'document-id-123', - form: { - docketNumber: '101-12', - }, - }, - }); - - expect(routeStub.mock.calls[0][0]).toEqual( - '/case-detail/101-12/documents/document-id-123/edit-saved?tab=caseInfo', - ); - }); - - it('does not navigate to the edit saved document detail view if document id is not provided', async () => { - await runAction(navigateToEditSavedPetitionAction, { - modules: { presenter }, - state: { - form: { - docketNumber: '101-12', - }, - }, - }); - - expect(routeStub).not.toHaveBeenCalled(); - }); - - it('does not navigate to the edit saved document detail view if docketNumber is not provided', async () => { - await runAction(navigateToEditSavedPetitionAction, { - modules: { presenter }, - state: { - documentId: 'document-id-123', - form: {}, - }, - }); - - expect(routeStub).not.toHaveBeenCalled(); - }); -}); diff --git a/web-client/src/presenter/actions/chooseWorkQueueAction.js b/web-client/src/presenter/actions/chooseWorkQueueAction.js index 2758ad4d9fa..1545f93563e 100644 --- a/web-client/src/presenter/actions/chooseWorkQueueAction.js +++ b/web-client/src/presenter/actions/chooseWorkQueueAction.js @@ -20,11 +20,11 @@ export const chooseWorkQueueAction = ({ get, path, props, store }) => { ); } - if (props && props.queue) { + if (props.queue) { store.set(state.workQueueToDisplay.queue, props.queue); } - if (props && props.box) { + if (props.box) { store.set(state.workQueueToDisplay.box, props.box); } diff --git a/web-client/src/presenter/actions/generateDocketRecordPdfUrlAction.js b/web-client/src/presenter/actions/generateDocketRecordPdfUrlAction.js index 20d1030db40..d2c0ba53f4e 100644 --- a/web-client/src/presenter/actions/generateDocketRecordPdfUrlAction.js +++ b/web-client/src/presenter/actions/generateDocketRecordPdfUrlAction.js @@ -9,25 +9,20 @@ import { state } from 'cerebral'; export const generateDocketRecordPdfUrlAction = async ({ applicationContext, get, - router, }) => { const caseDetail = get(state.caseDetail); const docketRecordSort = get( state.sessionMetadata.docketRecordSort[caseDetail.caseId], ); - const docketRecordPdf = await applicationContext - .getUseCases() - .generateDocketRecordPdfInteractor({ - applicationContext, - caseId: caseDetail.caseId, - docketRecordSort, - includePartyDetail: true, - }); + const { + url, + } = await applicationContext.getUseCases().generateDocketRecordPdfInteractor({ + applicationContext, + caseId: caseDetail.caseId, + docketRecordSort, + includePartyDetail: true, + }); - const pdfFile = new Blob([docketRecordPdf], { type: 'application/pdf' }); - - const pdfUrl = router.createObjectURL(pdfFile); - - return { pdfUrl }; + return { pdfUrl: url }; }; diff --git a/web-client/src/presenter/actions/generateDocketRecordPdfUrlAction.test.js b/web-client/src/presenter/actions/generateDocketRecordPdfUrlAction.test.js index 1cb0049b470..17ccd9ee1cd 100644 --- a/web-client/src/presenter/actions/generateDocketRecordPdfUrlAction.test.js +++ b/web-client/src/presenter/actions/generateDocketRecordPdfUrlAction.test.js @@ -3,22 +3,15 @@ import { generateDocketRecordPdfUrlAction } from './generateDocketRecordPdfUrlAc import { presenter } from '../presenter-mock'; import { runAction } from 'cerebral/test'; -const mockCreateObjectUrl = jest.fn(); - describe('generateDocketRecordPdfUrlAction', () => { + const mockPdfUrl = { url: 'www.example.com' }; beforeAll(() => { presenter.providers.applicationContext = applicationContext; + applicationContext + .getUseCases() + .generateDocketRecordPdfInteractor.mockResolvedValue(mockPdfUrl); global.window = global; - - global.Blob = () => {}; - - presenter.providers.router = { - createObjectURL: () => { - mockCreateObjectUrl(); - return '123456-abcdef'; - }, - }; }); it('creates a pdf and returns an object URL', async () => { @@ -43,10 +36,7 @@ describe('generateDocketRecordPdfUrlAction', () => { }, }, }); - expect( - applicationContext.getUseCases().generateDocketRecordPdfInteractor, - ).toHaveBeenCalled(); - expect(mockCreateObjectUrl).toHaveBeenCalled(); - expect(result.output).toHaveProperty('pdfUrl'); + + expect(result.output.pdfUrl).toBe(mockPdfUrl.url); }); }); diff --git a/web-client/src/presenter/actions/getPaperServiceSuccessMessageAction.js b/web-client/src/presenter/actions/getPaperServiceSuccessMessageAction.js new file mode 100644 index 00000000000..53991d4726a --- /dev/null +++ b/web-client/src/presenter/actions/getPaperServiceSuccessMessageAction.js @@ -0,0 +1,13 @@ +/** + * returns alertSuccess message for paper service + * + * @returns {object} the paper service success message + */ +export const getPaperServiceSuccessMessageAction = () => { + return { + alertSuccess: { + message: + 'This document has been served. Remember to print all documents for parties with paper service.', + }, + }; +}; diff --git a/web-client/src/presenter/actions/navigateToPrintPreviewAction.js b/web-client/src/presenter/actions/navigateToPrintPaperServiceAction.js similarity index 71% rename from web-client/src/presenter/actions/navigateToPrintPreviewAction.js rename to web-client/src/presenter/actions/navigateToPrintPaperServiceAction.js index ecd3d60faaa..7bd9757c734 100644 --- a/web-client/src/presenter/actions/navigateToPrintPreviewAction.js +++ b/web-client/src/presenter/actions/navigateToPrintPaperServiceAction.js @@ -7,8 +7,8 @@ import { state } from 'cerebral'; * @param {object} providers.router the riot.router object that is used for changing the route * @returns {Promise} asynchronous action */ -export const navigateToPrintPreviewAction = async ({ get, router }) => { +export const navigateToPrintPaperServiceAction = async ({ get, router }) => { const docketNumber = get(state.caseDetail.docketNumber); - await router.route(`/print-preview/${docketNumber}`); + await router.route(`/print-paper-service/${docketNumber}`); }; diff --git a/web-client/src/presenter/actions/navigateToPrintPreviewAction.test.js b/web-client/src/presenter/actions/navigateToPrintPaperServiceAction.test.js similarity index 63% rename from web-client/src/presenter/actions/navigateToPrintPreviewAction.test.js rename to web-client/src/presenter/actions/navigateToPrintPaperServiceAction.test.js index 3570d55639b..c9d4d513aa9 100644 --- a/web-client/src/presenter/actions/navigateToPrintPreviewAction.test.js +++ b/web-client/src/presenter/actions/navigateToPrintPaperServiceAction.test.js @@ -1,8 +1,8 @@ -import { navigateToPrintPreviewAction } from './navigateToPrintPreviewAction'; +import { navigateToPrintPaperServiceAction } from './navigateToPrintPaperServiceAction'; import { presenter } from '../presenter-mock'; import { runAction } from 'cerebral/test'; -describe('navigateToPrintPreviewAction', () => { +describe('navigateToPrintPaperServiceAction', () => { let routeStub; beforeAll(() => { @@ -14,7 +14,7 @@ describe('navigateToPrintPreviewAction', () => { }); it('navigates to print preview for the state.caseDetail.docketNumber', async () => { - await runAction(navigateToPrintPreviewAction, { + await runAction(navigateToPrintPaperServiceAction, { modules: { presenter, }, @@ -25,6 +25,6 @@ describe('navigateToPrintPreviewAction', () => { }, }); - expect(routeStub).toHaveBeenCalledWith('/print-preview/101-20'); + expect(routeStub).toHaveBeenCalledWith('/print-paper-service/101-20'); }); }); diff --git a/web-client/src/presenter/actions/serveCourtIssuedDocumentAction.js b/web-client/src/presenter/actions/serveCourtIssuedDocumentAction.js index 84e8388ccca..965159d0489 100644 --- a/web-client/src/presenter/actions/serveCourtIssuedDocumentAction.js +++ b/web-client/src/presenter/actions/serveCourtIssuedDocumentAction.js @@ -12,12 +12,13 @@ import { state } from 'cerebral'; export const serveCourtIssuedDocumentAction = async ({ applicationContext, get, - router, }) => { const documentId = get(state.documentId); const caseId = get(state.caseDetail.caseId); - const paperServicePdfData = await applicationContext + const { + pdfUrl, + } = await applicationContext .getUseCases() .serveCourtIssuedDocumentInteractor({ applicationContext, @@ -25,18 +26,6 @@ export const serveCourtIssuedDocumentAction = async ({ documentId, }); - let pdfUrl = null; - if ( - paperServicePdfData && - (paperServicePdfData.size > 0 || paperServicePdfData.length > 0) - ) { - const pdfFile = new Blob([paperServicePdfData], { - type: 'application/pdf', - }); - - pdfUrl = router.createObjectURL(pdfFile); - } - return { alertSuccess: { message: 'Document served. ', diff --git a/web-client/src/presenter/actions/serveCourtIssuedDocumentAction.test.js b/web-client/src/presenter/actions/serveCourtIssuedDocumentAction.test.js index 6be992907e0..a9032e50913 100644 --- a/web-client/src/presenter/actions/serveCourtIssuedDocumentAction.test.js +++ b/web-client/src/presenter/actions/serveCourtIssuedDocumentAction.test.js @@ -6,28 +6,16 @@ import { serveCourtIssuedDocumentAction } from './serveCourtIssuedDocumentAction describe('serveCourtIssuedDocumentAction', () => { global.window = global; global.Blob = () => {}; - let mockCreateObjectUrl; + let mockPdfUrl = { pdfUrl: 'www.example.com' }; beforeAll(() => { presenter.providers.applicationContext = applicationContext; - - mockCreateObjectUrl = jest.fn(); - presenter.providers.router = { - createObjectURL: () => { - mockCreateObjectUrl(); - return '123456-abcdef'; - }, - }; - }); - - it('should call the interactor that serves court issued documents and generate a pdf url if a result is returned', async () => { applicationContext .getUseCases() - .serveCourtIssuedDocumentInteractor.mockReturnValue({ - size: 123, - type: 'FakeBlob', - }); + .serveCourtIssuedDocumentInteractor.mockImplementation(() => mockPdfUrl); + }); + it('should call the interactor that serves court issued documents and generate a pdf url if a result is returned', async () => { const result = await runAction(serveCourtIssuedDocumentAction, { modules: { presenter, @@ -45,18 +33,15 @@ describe('serveCourtIssuedDocumentAction', () => { }, }); - expect(mockCreateObjectUrl).toHaveBeenCalled(); expect( applicationContext.getUseCases().serveCourtIssuedDocumentInteractor.mock .calls.length, ).toEqual(1); - expect(result.output.pdfUrl).not.toBe(null); + expect(result.output.pdfUrl).toBe(mockPdfUrl.pdfUrl); }); it('should call the interactor that serves court issued documents and not generate a pdf url if a result is not returned', async () => { - applicationContext - .getUseCases() - .serveCourtIssuedDocumentInteractor.mockReturnValue(null); + mockPdfUrl = { pdfUrl: null }; const result = await runAction(serveCourtIssuedDocumentAction, { modules: { diff --git a/web-client/src/presenter/actions/setCaseOnFormUsingStateAction.js b/web-client/src/presenter/actions/setCaseOnFormUsingStateAction.js new file mode 100644 index 00000000000..5f97d075cb4 --- /dev/null +++ b/web-client/src/presenter/actions/setCaseOnFormUsingStateAction.js @@ -0,0 +1,12 @@ +import { state } from 'cerebral'; + +/** + * sets state.caseDetail on state.form + * + * @param {object} providers the providers object + * @param {Function} providers.get the cerebral get function + * @param {object} providers.store the cerebral store + */ +export const setCaseOnFormUsingStateAction = async ({ get, store }) => { + store.set(state.form, get(state.caseDetail)); +}; diff --git a/web-client/src/presenter/actions/setCaseOnFormUsingStateAction.test.js b/web-client/src/presenter/actions/setCaseOnFormUsingStateAction.test.js new file mode 100644 index 00000000000..8d9c802e7e7 --- /dev/null +++ b/web-client/src/presenter/actions/setCaseOnFormUsingStateAction.test.js @@ -0,0 +1,18 @@ +import { runAction } from 'cerebral/test'; +import { setCaseOnFormUsingStateAction } from './setCaseOnFormUsingStateAction'; + +describe('setCaseOnFormUsingStateAction', () => { + it('sets caseDetail on state.form from props', async () => { + const { state } = await runAction(setCaseOnFormUsingStateAction, { + state: { + caseDetail: { + caseId: '1234', + }, + }, + }); + + expect(state.form).toEqual({ + caseId: '1234', + }); + }); +}); diff --git a/web-client/src/presenter/actions/setFormDateAction.js b/web-client/src/presenter/actions/setFormDateAction.js new file mode 100644 index 00000000000..e32e75429da --- /dev/null +++ b/web-client/src/presenter/actions/setFormDateAction.js @@ -0,0 +1,16 @@ +import { state } from 'cerebral'; + +/** + * sets and unsets state.form.date from props.computedDate + * + * @param {object} providers the providers object + * @param {object} providers.props the cerebral props object + * @param {object} providers.store the cerebral store + */ +export const setFormDateAction = ({ props, store }) => { + if (props.computedDate) { + store.set(state.form.date, props.computedDate); + } else { + store.unset(state.form.date); + } +}; diff --git a/web-client/src/presenter/actions/validateCaseAssociationRequestAction.test.js b/web-client/src/presenter/actions/validateCaseAssociationRequestAction.test.js index 5072c50c733..8e7bdc1f534 100644 --- a/web-client/src/presenter/actions/validateCaseAssociationRequestAction.test.js +++ b/web-client/src/presenter/actions/validateCaseAssociationRequestAction.test.js @@ -14,7 +14,7 @@ describe('validateCaseAssociationRequest', () => { mockCaseAssociationRequest = { certificateOfService: true, - certificateOfServiceDate: '1212-12-12', + certificateOfServiceDate: '1987-08-06T07:53.009Z', documentTitle: 'Entry of Appearance', documentType: 'Entry of Appearance', eventCode: '123', diff --git a/web-client/src/presenter/computeds/addDocketEntryHelper.js b/web-client/src/presenter/computeds/addDocketEntryHelper.js index f310c3a6440..f1298afca68 100644 --- a/web-client/src/presenter/computeds/addDocketEntryHelper.js +++ b/web-client/src/presenter/computeds/addDocketEntryHelper.js @@ -119,8 +119,9 @@ export const addDocketEntryHelper = (get, applicationContext) => { optionsForCategory.showSecondaryDocumentForm = true; } - const { Document } = applicationContext.getEntityConstructors(); - const showTrackOption = !Document.isPendingOnCreation(form); + const showTrackOption = !applicationContext + .getUtilities() + .isPendingOnCreation(form); return { certificateOfServiceDateFormatted, diff --git a/web-client/src/presenter/computeds/advancedSearchHelper.js b/web-client/src/presenter/computeds/advancedSearchHelper.js index 2d7ada88810..558515889e5 100644 --- a/web-client/src/presenter/computeds/advancedSearchHelper.js +++ b/web-client/src/presenter/computeds/advancedSearchHelper.js @@ -16,9 +16,7 @@ export const formatSearchResultRecord = (result, { applicationContext }) => { result.docketNumberSuffix ? result.docketNumberSuffix : '' }`; - result.caseCaptionNames = applicationContext.getCaseCaptionNames( - result.caseCaption || '', - ); + result.caseTitle = applicationContext.getCaseTitle(result.caseCaption || ''); result.fullStateNamePrimary = US_STATES[result.contactPrimary.state] || result.contactPrimary.state; @@ -43,6 +41,8 @@ export const formatOrderSearchResultRecord = ( .getUtilities() .formatDateString(result.filingDate, 'MMDDYY'); + result.caseTitle = applicationContext.getCaseTitle(result.caseCaption || ''); + result.docketNumberWithSuffix = `${result.docketNumber}${ result.docketNumberSuffix ? result.docketNumberSuffix : '' }`; @@ -99,6 +99,7 @@ export const advancedSearchHelper = (get, applicationContext) => { export const advancedOrderSearchHelper = (get, applicationContext) => { let paginatedResults = {}; const searchResults = get(state.searchResults); + const isPublic = get(state.isPublic); if (searchResults) { paginatedResults = paginationHelper( @@ -113,7 +114,10 @@ export const advancedOrderSearchHelper = (get, applicationContext) => { ); } - return paginatedResults; + return { + ...paginatedResults, + isPublic, + }; }; const paginationHelper = (searchResults, currentPage, pageSize) => { diff --git a/web-client/src/presenter/computeds/advancedSearchHelper.test.js b/web-client/src/presenter/computeds/advancedSearchHelper.test.js index 2395b63760c..42763540ff3 100644 --- a/web-client/src/presenter/computeds/advancedSearchHelper.test.js +++ b/web-client/src/presenter/computeds/advancedSearchHelper.test.js @@ -190,7 +190,7 @@ describe('advancedSearchHelper', () => { }); expect(result.formattedSearchResults).toMatchObject([ { - caseCaptionNames: 'Test Petitioner', + caseTitle: 'Test Petitioner', contactPrimaryName: 'Daenerys Stormborn of the House Targaryen, First of Her Name, the Unburnt, Queen of the Andals and the First Men, Khaleesi of the Great Grass Sea, Breaker of Chains, and Mother of Dragons', contactSecondaryName: undefined, @@ -199,7 +199,7 @@ describe('advancedSearchHelper', () => { fullStateNamePrimary: 'Tennessee', }, { - caseCaptionNames: 'Test Petitioner & Another Petitioner', + caseTitle: 'Test Petitioner & Another Petitioner', contactPrimaryName: 'Daenerys Stormborn of the House Targaryen, First of Her Name, the Unburnt, Queen of the Andals and the First Men, Khaleesi of the Great Grass Sea, Breaker of Chains, and Mother of Dragons', contactSecondaryName: 'Another Person', @@ -247,7 +247,7 @@ describe('advancedSearchHelper', () => { expect(result.formattedSearchResults.length).toEqual(1); expect(result.formattedSearchResults).toMatchObject([ { - caseCaptionNames: 'Test Petitioner', + caseTitle: 'Test Petitioner', contactPrimaryName: 'Daenerys Stormborn of the House Targaryen, First of Her Name, the Unburnt, Queen of the Andals and the First Men, Khaleesi of the Great Grass Sea, Breaker of Chains, and Mother of Dragons', docketNumberWithSuffix: '101-19', @@ -304,7 +304,7 @@ describe('advancedSearchHelper', () => { expect(result.formattedSearchResults.length).toEqual(4); expect(result.formattedSearchResults).toMatchObject([ { - caseCaptionNames: 'Test Petitioner', + caseTitle: 'Test Petitioner', contactPrimaryName: 'Daenerys Stormborn of the House Targaryen, First of Her Name, the Unburnt, Queen of the Andals and the First Men, Khaleesi of the Great Grass Sea, Breaker of Chains, and Mother of Dragons', contactSecondaryName: undefined, @@ -313,7 +313,7 @@ describe('advancedSearchHelper', () => { fullStateNamePrimary: 'Tennessee', }, { - caseCaptionNames: 'Test Petitioner & Another Petitioner', + caseTitle: 'Test Petitioner & Another Petitioner', contactPrimaryName: 'Daenerys Stormborn of the House Targaryen, First of Her Name, the Unburnt, Queen of the Andals and the First Men, Khaleesi of the Great Grass Sea, Breaker of Chains, and Mother of Dragons', contactSecondaryName: 'Another Person', @@ -322,7 +322,7 @@ describe('advancedSearchHelper', () => { fullStateNamePrimary: 'Texas', }, { - caseCaptionNames: 'Test Petitioner & Another Petitioner', + caseTitle: 'Test Petitioner & Another Petitioner', contactPrimaryName: 'Test Petitioner', contactSecondaryName: 'Another Petitioner', docketNumberWithSuffix: '101-18W', @@ -331,7 +331,7 @@ describe('advancedSearchHelper', () => { fullStateNameSecondary: 'Tennessee', }, { - caseCaptionNames: '', + caseTitle: '', contactPrimaryName: undefined, contactSecondaryName: 'Another Person', docketNumberWithSuffix: '102-18W', @@ -421,6 +421,29 @@ describe('advancedOrderSearchHelper', () => { }); }); + it('returns isPublic false if state.isPublic is not defined', () => { + const result = runCompute(advancedOrderSearchHelper, { + state: { + advancedSearchForm: { currentPage: 1 }, + searchResults: [], + }, + }); + + expect(result.isPublic).toBeFalsy(); + }); + + it('returns isPublic true if state.isPublic is true', () => { + const result = runCompute(advancedOrderSearchHelper, { + state: { + advancedSearchForm: { currentPage: 1 }, + isPublic: true, + searchResults: [], + }, + }); + + expect(result).toBeTruthy(); + }); + it('returns showNoMatches false, showSearchResults true, and the resultsCount when searchResults are not empty', () => { const result = runCompute(advancedOrderSearchHelper, { state: { @@ -452,6 +475,7 @@ describe('advancedOrderSearchHelper', () => { advancedSearchForm: { currentPage: 1 }, searchResults: [ { + caseCaption: 'Test Petitioner, Petitioner', docketNumber: '101-19', docketNumberSuffix: 'Z', documentContents: 'Test Petitioner, Petitioner', @@ -460,6 +484,7 @@ describe('advancedOrderSearchHelper', () => { judge: 'Judge Buch', }, { + caseCaption: 'Test Petitioner, Petitioner', docketNumber: '102-19', docketNumberSuffix: 'P', documentContents: 'Test Petitioner, Petitioner', @@ -473,6 +498,7 @@ describe('advancedOrderSearchHelper', () => { expect(result.formattedSearchResults).toMatchObject([ { + caseTitle: 'Test Petitioner', docketNumber: '101-19', docketNumberSuffix: 'Z', docketNumberWithSuffix: '101-19Z', @@ -483,6 +509,7 @@ describe('advancedOrderSearchHelper', () => { judge: 'Judge Buch', }, { + caseTitle: 'Test Petitioner', docketNumber: '102-19', docketNumberSuffix: 'P', docketNumberWithSuffix: '102-19P', diff --git a/web-client/src/presenter/computeds/blockedCasesReportHelper.js b/web-client/src/presenter/computeds/blockedCasesReportHelper.js index 7d8fcddd534..1f4bae3bafd 100644 --- a/web-client/src/presenter/computeds/blockedCasesReportHelper.js +++ b/web-client/src/presenter/computeds/blockedCasesReportHelper.js @@ -34,7 +34,7 @@ export const blockedCasesReportHelper = (get, applicationContext) => { .map(blockedCase => { return { ...setFormattedBlockDates(blockedCase), - caseName: applicationContext.getCaseCaptionNames( + caseTitle: applicationContext.getCaseTitle( blockedCase.caseCaption || '', ), docketNumberWithSuffix: diff --git a/web-client/src/presenter/computeds/blockedCasesReportHelper.test.js b/web-client/src/presenter/computeds/blockedCasesReportHelper.test.js index 92506e90c0a..e69e80af953 100644 --- a/web-client/src/presenter/computeds/blockedCasesReportHelper.test.js +++ b/web-client/src/presenter/computeds/blockedCasesReportHelper.test.js @@ -36,7 +36,7 @@ describe('blockedCasesReportHelper', () => { expect(result).toMatchObject({ blockedCasesCount: 3 }); }); - it('formats blocked cases with caseName, docketNumberWithSuffix, and blockedDateFormatted and sorts by docket number', () => { + it('formats blocked cases with caseTitle, docketNumberWithSuffix, and blockedDateFormatted and sorts by docket number', () => { const result = runCompute(blockedCasesReportHelper, { state: { blockedCases: [ @@ -89,7 +89,7 @@ describe('blockedCasesReportHelper', () => { caseCaption: 'Tatum Craig, Wayne Obrien, Partnership Representative, Petitioner(s)', caseId: '3', - caseName: 'Tatum Craig, Wayne Obrien, Partnership Representative', + caseTitle: 'Tatum Craig, Wayne Obrien, Partnership Representative', docketNumber: '103-18', docketNumberSuffix: 'S', docketNumberWithSuffix: '103-18S', @@ -102,7 +102,7 @@ describe('blockedCasesReportHelper', () => { blockedDateEarliest: '03/05/18', caseCaption: 'Selma Horn & Cairo Harris, Petitioners', caseId: '2', - caseName: 'Selma Horn & Cairo Harris', + caseTitle: 'Selma Horn & Cairo Harris', docketNumber: '102-19', docketNumberWithSuffix: '102-19', }, @@ -112,7 +112,7 @@ describe('blockedCasesReportHelper', () => { blockedDateEarliest: '03/05/19', caseCaption: 'Bob Barker, Petitioner', caseId: '4', - caseName: 'Bob Barker', + caseTitle: 'Bob Barker', docketNumber: '104-19', docketNumberWithSuffix: '104-19', }, @@ -122,7 +122,7 @@ describe('blockedCasesReportHelper', () => { blockedDateEarliest: '03/01/19', caseCaption: 'Brett Osborne, Petitioner', caseId: '1', - caseName: 'Brett Osborne', + caseTitle: 'Brett Osborne', docketNumber: '105-19', docketNumberWithSuffix: '105-19', }, diff --git a/web-client/src/presenter/computeds/caseDeadlineReportHelper.js b/web-client/src/presenter/computeds/caseDeadlineReportHelper.js index 1e83c8dca21..d2ed4d31b74 100644 --- a/web-client/src/presenter/computeds/caseDeadlineReportHelper.js +++ b/web-client/src/presenter/computeds/caseDeadlineReportHelper.js @@ -64,9 +64,7 @@ export const caseDeadlineReportHelper = (get, applicationContext) => { associatedJudgeFormatted: applicationContext .getUtilities() .formatJudgeName(d.associatedJudge), - caseCaptionNames: applicationContext.getCaseCaptionNames( - d.caseCaption || '', - ), + caseTitle: applicationContext.getCaseTitle(d.caseCaption || ''), deadlineDateReal: applicationContext .getUtilities() .prepareDateFromString(d.deadlineDate), diff --git a/web-client/src/presenter/computeds/caseDetailHelper.js b/web-client/src/presenter/computeds/caseDetailHelper.js index faa9fa8ed2a..d469dcdc81f 100644 --- a/web-client/src/presenter/computeds/caseDetailHelper.js +++ b/web-client/src/presenter/computeds/caseDetailHelper.js @@ -3,7 +3,7 @@ import { state } from 'cerebral'; export const caseDetailHelper = (get, applicationContext) => { const user = applicationContext.getCurrentUser(); - const { PARTY_TYPES, USER_ROLES } = applicationContext.getConstants(); + const { USER_ROLES } = applicationContext.getConstants(); const caseDetail = get(state.caseDetail); const caseDeadlines = get(state.caseDeadlines) || []; const documentDetailTab = @@ -49,11 +49,6 @@ export const caseDetailHelper = (get, applicationContext) => { } } - const showCaseNameForPrimary = ![ - PARTY_TYPES.petitioner, - PARTY_TYPES.petitionerDeceasedSpouse, - ].includes(caseDetail.partyType); - let showEditContacts = false; if (user.role === USER_ROLES.petitioner) { @@ -114,7 +109,6 @@ export const caseDetailHelper = (get, applicationContext) => { showCaseDeadlinesInternal, showCaseDeadlinesInternalEmpty, showCaseInformationExternal: isExternalUser, - showCaseNameForPrimary, showDocketRecordInProgressState: !isExternalUser, showDocumentStatus: !caseDetail.irsSendDate, showEditContacts, diff --git a/web-client/src/presenter/computeds/fileDocumentHelper.js b/web-client/src/presenter/computeds/fileDocumentHelper.js index a4e7c9e828e..8cd36ebf2c2 100644 --- a/web-client/src/presenter/computeds/fileDocumentHelper.js +++ b/web-client/src/presenter/computeds/fileDocumentHelper.js @@ -125,9 +125,8 @@ export const fileDocumentHelper = (get, applicationContext) => { docketNumber, })); - const sortedDocketNumbers = applicationContext - .getEntityConstructors() - .Case.sortByDocketNumber(selectedDocketNumbers) + const sortedDocketNumbers = selectedDocketNumbers + .sort(applicationContext.getUtilities().compareCasesByDocketNumber) .map(({ docketNumber }) => docketNumber); formattedDocketNumbers = [ diff --git a/web-client/src/presenter/computeds/formattedCaseDetail.js b/web-client/src/presenter/computeds/formattedCaseDetail.js index bbc43a6ab3a..13f31e4c5b1 100644 --- a/web-client/src/presenter/computeds/formattedCaseDetail.js +++ b/web-client/src/presenter/computeds/formattedCaseDetail.js @@ -14,11 +14,11 @@ export const formattedCaseDetail = (get, applicationContext) => { .isExternalUser(user.role); const permissions = get(state.permissions); const userAssociatedWithCase = get(state.screenMetadata.isAssociated); - const { Document } = applicationContext.getEntityConstructors(); + const { SYSTEM_GENERATED_DOCUMENT_TYPES } = applicationContext.getConstants(); const systemGeneratedEventCodes = Object.keys( - Document.SYSTEM_GENERATED_DOCUMENT_TYPES, + SYSTEM_GENERATED_DOCUMENT_TYPES, ).map(key => { - return Document.SYSTEM_GENERATED_DOCUMENT_TYPES[key].eventCode; + return SYSTEM_GENERATED_DOCUMENT_TYPES[key].eventCode; }); const { @@ -111,8 +111,6 @@ export const formattedCaseDetail = (get, applicationContext) => { permissions.DOCKET_ENTRY ) { editLink = '/edit'; - } else if (document.isPetition && !document.servedAt) { - editLink = '/edit-saved'; } } diff --git a/web-client/src/presenter/computeds/formattedCaseDetail.test.js b/web-client/src/presenter/computeds/formattedCaseDetail.test.js index 7b89df48eb0..f0fb4f00743 100644 --- a/web-client/src/presenter/computeds/formattedCaseDetail.test.js +++ b/web-client/src/presenter/computeds/formattedCaseDetail.test.js @@ -506,7 +506,7 @@ describe('formattedCaseDetail', () => { expect(result.formattedDocketEntries).toMatchObject([ { - editLink: '/edit-saved', + editLink: '', showDocumentEditLink: true, }, { @@ -732,7 +732,7 @@ describe('formattedCaseDetail', () => { validationErrors: {}, }, }); - expect(result.caseName).toEqual(''); + expect(result.caseTitle).toEqual(''); }); it("should remove ', Petitioner' from caseCaption", () => { @@ -747,7 +747,7 @@ describe('formattedCaseDetail', () => { validationErrors: {}, }, }); - expect(result.caseName).toEqual('Sisqo'); + expect(result.caseTitle).toEqual('Sisqo'); }); it("should remove ', Petitioners' from caseCaption", () => { @@ -762,7 +762,7 @@ describe('formattedCaseDetail', () => { validationErrors: {}, }, }); - expect(result.caseName).toEqual('Sisqo and friends'); + expect(result.caseTitle).toEqual('Sisqo and friends'); }); it("should remove ', Petitioner(s)' from caseCaption", () => { @@ -777,7 +777,7 @@ describe('formattedCaseDetail', () => { validationErrors: {}, }, }); - expect(result.caseName).toEqual("Sisqo's entourage,"); + expect(result.caseTitle).toEqual("Sisqo's entourage,"); }); }); diff --git a/web-client/src/presenter/computeds/formattedTrialSessionDetails.test.js b/web-client/src/presenter/computeds/formattedTrialSessionDetails.test.js index 792e8aadaa5..55eb91a73a1 100644 --- a/web-client/src/presenter/computeds/formattedTrialSessionDetails.test.js +++ b/web-client/src/presenter/computeds/formattedTrialSessionDetails.test.js @@ -259,19 +259,19 @@ describe('formattedTrialSessionDetails', () => { expect(result.formattedEligibleCases[0].docketNumberWithSuffix).toEqual( '101-18', ); - expect(result.formattedEligibleCases[0].caseCaptionNames).toEqual( + expect(result.formattedEligibleCases[0].caseTitle).toEqual( 'Test Petitioner', ); expect(result.formattedEligibleCases[1].docketNumberWithSuffix).toEqual( '101-18W', ); - expect(result.formattedEligibleCases[1].caseCaptionNames).toEqual( + expect(result.formattedEligibleCases[1].caseTitle).toEqual( 'Daenerys Stormborn of the House Targaryen, First of Her Name, the Unburnt, Queen of the Andals and the First Men, Khaleesi of the Great Grass Sea, Breaker of Chains, and Mother of Dragons & Someone Else', ); expect(result.formattedEligibleCases[2].docketNumberWithSuffix).toEqual( '103-19', ); - expect(result.formattedEligibleCases[2].caseCaptionNames).toEqual(''); + expect(result.formattedEligibleCases[2].caseTitle).toEqual(''); }); it('formats docket numbers with suffixes and case caption names without postfix on calendared cases and splits them by open and closed cases', () => { @@ -296,9 +296,9 @@ describe('formattedTrialSessionDetails', () => { }); expect(result.allCases.length).toEqual(2); expect(result.allCases[0].docketNumberWithSuffix).toEqual('101-18'); - expect(result.allCases[0].caseCaptionNames).toEqual('Test Petitioner'); + expect(result.allCases[0].caseTitle).toEqual('Test Petitioner'); expect(result.allCases[1].docketNumberWithSuffix).toEqual('101-18W'); - expect(result.allCases[1].caseCaptionNames).toEqual( + expect(result.allCases[1].caseTitle).toEqual( 'Daenerys Stormborn of the House Targaryen, First of Her Name, the Unburnt, Queen of the Andals and the First Men, Khaleesi of the Great Grass Sea, Breaker of Chains, and Mother of Dragons & Someone Else', ); diff --git a/web-client/src/presenter/computeds/reviewPetitionFromPaperHelper.js b/web-client/src/presenter/computeds/reviewPetitionFromPaperHelper.js deleted file mode 100644 index 50f4918fef8..00000000000 --- a/web-client/src/presenter/computeds/reviewPetitionFromPaperHelper.js +++ /dev/null @@ -1,68 +0,0 @@ -import { state } from 'cerebral'; - -export const reviewPetitionFromPaperHelper = (get, applicationContext) => { - let irsNoticeDateFormatted; - const { - dateReceived, - hasVerifiedIrsNotice, - irsNoticeDate, - petitionPaymentDate, - petitionPaymentMethod, - petitionPaymentStatus, - preferredTrialCity, - ...form - } = get(state.form); - - const { PAYMENT_STATUS } = applicationContext.getConstants(); - - const receivedAtFormatted = applicationContext - .getUtilities() - .formatDateString(dateReceived, 'MMDDYYYY'); - - const hasIrsNoticeFormatted = hasVerifiedIrsNotice ? 'Yes' : 'No'; - - const shouldShowIrsNoticeDate = hasVerifiedIrsNotice === true; - - const petitionPaymentStatusFormatted = - petitionPaymentStatus === PAYMENT_STATUS.PAID - ? `Paid ${applicationContext - .getUtilities() - .formatDateString( - petitionPaymentDate, - 'MMDDYYYY', - )} ${petitionPaymentMethod}` - : 'Not paid'; - - const preferredTrialCityFormatted = preferredTrialCity - ? preferredTrialCity - : 'No requested place of trial'; - - if (shouldShowIrsNoticeDate) { - irsNoticeDateFormatted = applicationContext - .getUtilities() - .formatDateString(irsNoticeDate, 'MMDDYYYY'); - } - - // orders needed summary - let hasOrders = [ - 'orderForAmendedPetition', - 'orderForAmendedPetitionAndFilingFee', - 'orderForFilingFee', - 'orderForOds', - 'orderForRatification', - 'orderDesignatingPlaceOfTrial', - 'orderToShowCause', - 'noticeOfAttachments', - 'orderDesignatingPlaceOfTrial', - ].some(key => Boolean(form[key])); - - return { - hasIrsNoticeFormatted, - hasOrders, - irsNoticeDateFormatted, - petitionPaymentStatusFormatted, - preferredTrialCityFormatted, - receivedAtFormatted, - shouldShowIrsNoticeDate, - }; -}; diff --git a/web-client/src/presenter/computeds/reviewPetitionFromPaperHelper.test.js b/web-client/src/presenter/computeds/reviewPetitionFromPaperHelper.test.js deleted file mode 100644 index 79d801ea372..00000000000 --- a/web-client/src/presenter/computeds/reviewPetitionFromPaperHelper.test.js +++ /dev/null @@ -1,104 +0,0 @@ -import { applicationContext } from '../../applicationContext'; -import { reviewPetitionFromPaperHelper as reviewPetitionFromPaperHelperComputed } from './reviewPetitionFromPaperHelper'; -import { runCompute } from 'cerebral/test'; -import { withAppContextDecorator } from '../../withAppContext'; - -const { PAYMENT_STATUS } = applicationContext.getConstants(); - -const reviewPetitionFromPaperHelper = withAppContextDecorator( - reviewPetitionFromPaperHelperComputed, - { - ...applicationContext, - getConstants: () => { - return { - ...applicationContext.getConstants(), - }; - }, - }, -); - -describe('reviewPetitionFromPaperHelper', () => { - it('returns defaults when there is no form', () => { - const result = runCompute(reviewPetitionFromPaperHelper, { - state: { - form: {}, - }, - }); - expect(result).toEqual({ - hasIrsNoticeFormatted: 'No', - hasOrders: false, - irsNoticeDateFormatted: undefined, - petitionPaymentStatusFormatted: 'Not paid', - preferredTrialCityFormatted: 'No requested place of trial', - receivedAtFormatted: undefined, - shouldShowIrsNoticeDate: false, - }); - }); - - it('return formatted/computed values based on form inputs', () => { - const result = runCompute(reviewPetitionFromPaperHelper, { - state: { - form: { - dateReceived: '2020-01-05T03:30:45.007Z', - hasVerifiedIrsNotice: true, - irsNoticeDate: '2020-01-05T03:30:45.007Z', - mailingDate: '2020-01-05T03:30:45.007Z', - petitionPaymentDate: '2020-03-14T14:02:04.007Z', - petitionPaymentMethod: 'pay.gov', - petitionPaymentStatus: PAYMENT_STATUS.PAID, - preferredTrialCity: 'Cooper Station', - }, - }, - }); - - expect(result).toEqual({ - hasIrsNoticeFormatted: 'Yes', - hasOrders: false, - irsNoticeDateFormatted: '01/04/2020', - petitionPaymentStatusFormatted: 'Paid 03/14/2020 pay.gov', - preferredTrialCityFormatted: 'Cooper Station', - receivedAtFormatted: '01/04/2020', - shouldShowIrsNoticeDate: true, - }); - }); - - it('should show orders needed summary if there are orders selected', () => { - const result = runCompute(reviewPetitionFromPaperHelper, { - state: { - form: { - orderForFilingFee: true, - }, - }, - }); - - expect(result).toEqual({ - hasIrsNoticeFormatted: 'No', - hasOrders: true, - irsNoticeDateFormatted: undefined, - petitionPaymentStatusFormatted: 'Not paid', - preferredTrialCityFormatted: 'No requested place of trial', - receivedAtFormatted: undefined, - shouldShowIrsNoticeDate: false, - }); - }); - - it('should show orders needed summary when order designating place of trial has been selected', () => { - const result = runCompute(reviewPetitionFromPaperHelper, { - state: { - form: { - orderDesignatingPlaceOfTrial: true, - }, - }, - }); - - expect(result).toEqual({ - hasIrsNoticeFormatted: 'No', - hasOrders: true, - irsNoticeDateFormatted: undefined, - petitionPaymentStatusFormatted: 'Not paid', - preferredTrialCityFormatted: 'No requested place of trial', - receivedAtFormatted: undefined, - shouldShowIrsNoticeDate: false, - }); - }); -}); diff --git a/web-client/src/presenter/computeds/reviewSavedPetitionHelper.js b/web-client/src/presenter/computeds/reviewSavedPetitionHelper.js index c6172d83417..3c490eea869 100644 --- a/web-client/src/presenter/computeds/reviewSavedPetitionHelper.js +++ b/web-client/src/presenter/computeds/reviewSavedPetitionHelper.js @@ -10,6 +10,7 @@ export const reviewSavedPetitionHelper = (get, applicationContext) => { petitionPaymentDate, petitionPaymentMethod, petitionPaymentStatus, + petitionPaymentWaivedDate, preferredTrialCity, receivedAt, ...caseDetail @@ -22,21 +23,30 @@ export const reviewSavedPetitionHelper = (get, applicationContext) => { const receivedAtFormatted = applicationContext .getUtilities() - .formatDateString(receivedAt, 'MMDDYYYY'); + .formatDateString(receivedAt, 'MMDDYY'); const hasIrsNoticeFormatted = hasVerifiedIrsNotice ? 'Yes' : 'No'; const shouldShowIrsNoticeDate = hasVerifiedIrsNotice === true; - const petitionPaymentStatusFormatted = - petitionPaymentStatus === PAYMENT_STATUS.PAID - ? `Paid ${applicationContext - .getUtilities() - .formatDateString( - petitionPaymentDate, - 'MMDDYYYY', - )} ${petitionPaymentMethod}` - : 'Not paid'; + let petitionPaymentStatusFormatted; + switch (petitionPaymentStatus) { + case PAYMENT_STATUS.PAID: + petitionPaymentStatusFormatted = `Paid ${applicationContext + .getUtilities() + .formatDateString( + petitionPaymentDate, + 'MMDDYY', + )} ${petitionPaymentMethod}`; + break; + case PAYMENT_STATUS.WAIVED: + petitionPaymentStatusFormatted = `Waived ${applicationContext + .getUtilities() + .formatDateString(petitionPaymentWaivedDate, 'MMDDYY')}`; + break; + default: + petitionPaymentStatusFormatted = 'Not paid'; + } const preferredTrialCityFormatted = preferredTrialCity ? preferredTrialCity @@ -45,7 +55,7 @@ export const reviewSavedPetitionHelper = (get, applicationContext) => { if (shouldShowIrsNoticeDate) { irsNoticeDateFormatted = applicationContext .getUtilities() - .formatDateString(irsNoticeDate, 'MMDDYYYY'); + .formatDateString(irsNoticeDate, 'MMDDYY'); } const documentsByType = (documents || []).reduce((acc, document) => { @@ -60,8 +70,7 @@ export const reviewSavedPetitionHelper = (get, applicationContext) => { 'orderForFilingFee', 'orderForOds', 'orderForRatification', - // TODO: see OrdersNeededSummary.jsx - // 'orderDesignatingPlaceOfTrial', + 'orderDesignatingPlaceOfTrial', 'orderToShowCause', 'noticeOfAttachments', ].some(key => Boolean(caseDetail[key])); @@ -73,8 +82,13 @@ export const reviewSavedPetitionHelper = (get, applicationContext) => { const ownershipDisclosureFile = documentsByType[INITIAL_DOCUMENT_TYPES.ownershipDisclosure.documentType]; const stinFile = documentsByType[INITIAL_DOCUMENT_TYPES.stin.documentType]; + const applicationForWaiverOfFilingFeeFile = + documentsByType[ + INITIAL_DOCUMENT_TYPES.applicationForWaiverOfFilingFee.documentType + ]; return { + applicationForWaiverOfFilingFeeFile, hasIrsNoticeFormatted, hasOrders, irsNoticeDateFormatted, diff --git a/web-client/src/presenter/computeds/reviewSavedPetitionHelper.test.js b/web-client/src/presenter/computeds/reviewSavedPetitionHelper.test.js index 1a544cb4d53..77b0106ff81 100644 --- a/web-client/src/presenter/computeds/reviewSavedPetitionHelper.test.js +++ b/web-client/src/presenter/computeds/reviewSavedPetitionHelper.test.js @@ -57,6 +57,11 @@ describe('reviewSavedPetitionHelper', () => { INITIAL_DOCUMENT_TYPES.ownershipDisclosure.documentType, }, { documentType: INITIAL_DOCUMENT_TYPES.stin.documentType }, + { + documentType: + INITIAL_DOCUMENT_TYPES.applicationForWaiverOfFilingFee + .documentType, + }, ], hasVerifiedIrsNotice: true, irsNoticeDate: '2020-01-05T03:30:45.007Z', @@ -70,18 +75,22 @@ describe('reviewSavedPetitionHelper', () => { }); expect(result).toEqual({ + applicationForWaiverOfFilingFeeFile: { + documentType: + INITIAL_DOCUMENT_TYPES.applicationForWaiverOfFilingFee.documentType, + }, hasIrsNoticeFormatted: 'Yes', hasOrders: true, - irsNoticeDateFormatted: '01/04/2020', + irsNoticeDateFormatted: '01/04/20', ownershipDisclosureFile: { documentType: INITIAL_DOCUMENT_TYPES.ownershipDisclosure.documentType, }, petitionFile: { documentType: INITIAL_DOCUMENT_TYPES.petition.documentType, }, - petitionPaymentStatusFormatted: 'Paid 03/14/2020 pay.gov', + petitionPaymentStatusFormatted: 'Paid 03/14/20 pay.gov', preferredTrialCityFormatted: 'No requested place of trial', - receivedAtFormatted: '01/04/2020', + receivedAtFormatted: '01/04/20', requestForPlaceOfTrialFile: { documentType: INITIAL_DOCUMENT_TYPES.requestForPlaceOfTrial.documentType, @@ -137,4 +146,29 @@ describe('reviewSavedPetitionHelper', () => { stinFile: undefined, }); }); + + [ + 'orderForAmendedPetition', + 'orderForAmendedPetitionAndFilingFee', + 'orderForFilingFee', + 'orderForOds', + 'orderForRatification', + 'orderToShowCause', + 'noticeOfAttachments', + 'orderDesignatingPlaceOfTrial', + ].forEach(order => { + it(`verify hasOrders is true if ${order} is set`, () => { + const result = runCompute(reviewSavedPetitionHelper, { + state: { + form: { + [order]: true, + }, + }, + }); + + expect(result).toMatchObject({ + hasOrders: true, + }); + }); + }); }); diff --git a/web-client/src/presenter/computeds/startCaseHelper.js b/web-client/src/presenter/computeds/startCaseHelper.js index 608aa9e2ac4..8d57254fe1a 100644 --- a/web-client/src/presenter/computeds/startCaseHelper.js +++ b/web-client/src/presenter/computeds/startCaseHelper.js @@ -35,14 +35,14 @@ export const startCaseHelper = (get, applicationContext) => { } const hasContactSecondary = - form.contactSecondary && Object.keys(form.contactSecondary).length > 0; + form.contactSecondary && form.contactSecondary.name; - const { Case } = applicationContext.getEntityConstructors(); - const caseCaption = Case.getCaseCaption(form) || ''; - const caseName = Case.getCaseCaptionNames(caseCaption); + const caseCaption = + applicationContext.getUtilities().getCaseCaption(form) || ''; + const caseTitle = applicationContext.getCaseTitle(caseCaption); return { - caseName, + caseTitle, contactPrimaryLabel, contactSecondaryLabel, deceasedSpouseLegend: @@ -60,7 +60,7 @@ export const startCaseHelper = (get, applicationContext) => { ? 'Did you receive a notice from the IRS?' : 'Do you have a notice from the IRS?', showBusinessFilingTypeOptions: form.filingType === 'A business', - showCaseNameForPrimary: !hasContactSecondary, + showCaseTitleForPrimary: !hasContactSecondary, showEstateFilingOptions: form.otherType === 'An estate or trust', showHasIrsNoticeOptions: form.hasIrsNotice === true, showMinorIncompetentFilingOptions: diff --git a/web-client/src/presenter/presenter-public.js b/web-client/src/presenter/presenter-public.js index 583ba8fba1a..08aeb67f2b0 100644 --- a/web-client/src/presenter/presenter-public.js +++ b/web-client/src/presenter/presenter-public.js @@ -16,6 +16,7 @@ import { submitPublicCaseAdvancedSearchSequence } from './sequences/public/submi import { submitPublicOrderAdvancedSearchSequence } from './sequences/public/submitPublicOrderAdvancedSearchSequence'; import { toggleBetaBarSequence } from './sequences/toggleBetaBarSequence'; import { toggleUsaBannerDetailsSequence } from './sequences/toggleUsaBannerDetailsSequence'; +import { updateAdvancedOrderSearchFormValueSequence } from './sequences/updateAdvancedOrderSearchFormValueSequence'; import { updateAdvancedSearchFormValueSequence } from './sequences/updateAdvancedSearchFormValueSequence'; import { updateDocketNumberSearchFormSequence } from './sequences/updateDocketNumberSearchFormSequence'; import { validateCaseAdvancedSearchFormSequence } from './sequences/validateCaseAdvancedSearchFormSequence'; @@ -40,6 +41,7 @@ export const presenter = { submitPublicOrderAdvancedSearchSequence, toggleBetaBarSequence, toggleUsaBannerDetailsSequence, + updateAdvancedOrderSearchFormValueSequence, updateAdvancedSearchFormValueSequence, updateDocketNumberSearchFormSequence, validateCaseAdvancedSearchFormSequence, diff --git a/web-client/src/presenter/presenter.js b/web-client/src/presenter/presenter.js index 6e5cd9144c0..a2a6942e661 100644 --- a/web-client/src/presenter/presenter.js +++ b/web-client/src/presenter/presenter.js @@ -46,13 +46,11 @@ import { completeStartCaseWizardStepSequence } from './sequences/completeStartCa import { confirmStayLoggedInSequence } from './sequences/confirmStayLoggedInSequence'; import { contactPrimaryCountryTypeChangeSequence } from './sequences/contactPrimaryCountryTypeChangeSequence'; import { contactSecondaryCountryTypeChangeSequence } from './sequences/contactSecondaryCountryTypeChangeSequence'; -import { convertHtml2PdfAndOpenInNewTabSequence } from './sequences/convertHtml2PdfAndOpenInNewTabSequence'; import { convertHtml2PdfSequence } from './sequences/convertHtml2PdfSequence'; import { copyPrimaryContactSequence } from './sequences/copyPrimaryContactSequence'; import { countryTypeFormContactChangeSequence } from './sequences/countryTypeFormContactChangeSequence'; import { countryTypeUserContactChangeSequence } from './sequences/countryTypeUserContactChangeSequence'; import { createCaseDeadlineSequence } from './sequences/createCaseDeadlineSequence'; -import { createCaseFromPaperAndServeToIrsSequence } from './sequences/createCaseFromPaperAndServeToIrsSequence'; import { createWorkItemSequence } from './sequences/createWorkItemSequence'; import { deleteCaseDeadlineSequence } from './sequences/deleteCaseDeadlineSequence'; import { deleteCaseNoteSequence } from './sequences/deleteCaseNoteSequence'; @@ -69,8 +67,7 @@ import { editUploadCourtIssuedDocumentSequence } from './sequences/editUploadCou import { fetchPendingItemsSequence } from './sequences/pending/fetchPendingItemsSequence'; import { fetchUserNotificationsSequence } from './sequences/fetchUserNotificationsSequence'; import { formCancelToggleCancelSequence } from './sequences/formCancelToggleCancelSequence'; -import { generateCaseCaptionForSavedPetitionSequence } from './sequences/generateCaseCaptionForSavedPetitionSequence'; -import { generateInternalCaseCaptionSequence } from './sequences/generateInternalCaseCaptionSequence'; +import { generateCaseCaptionSequence } from './sequences/generateCaseCaptionSequence'; import { generatePdfFromScanSessionSequence } from './sequences/generatePdfFromScanSessionSequence'; import { getBlockedCasesByTrialLocationSequence } from './sequences/getBlockedCasesByTrialLocationSequence'; import { getCaseInventoryReportSequence } from './sequences/getCaseInventoryReportSequence'; @@ -111,14 +108,13 @@ import { gotoPdfPreviewSequence } from './sequences/gotoPdfPreviewSequence'; import { gotoPendingReportSequence } from './sequences/gotoPendingReportSequence'; import { gotoPractitionerDetailSequence } from './sequences/gotoPractitionerDetailSequence'; import { gotoPrimaryContactEditSequence } from './sequences/gotoPrimaryContactEditSequence'; -import { gotoPrintPreviewSequence } from './sequences/gotoPrintPreviewSequence'; +import { gotoPrintPaperServiceSequence } from './sequences/gotoPrintPaperServiceSequence'; import { gotoPrintableCaseConfirmationSequence } from './sequences/gotoPrintableCaseConfirmationSequence'; import { gotoPrintableCaseInventoryReportSequence } from './sequences/gotoPrintableCaseInventoryReportSequence'; import { gotoPrintableDocketRecordSequence } from './sequences/gotoPrintableDocketRecordSequence'; import { gotoPrintablePendingReportForCaseSequence } from './sequences/gotoPrintablePendingReportForCaseSequence'; import { gotoPrintablePendingReportSequence } from './sequences/gotoPrintablePendingReportSequence'; import { gotoRequestAccessSequence } from './sequences/gotoRequestAccessSequence'; -import { gotoReviewPetitionFromPaperSequence } from './sequences/gotoReviewPetitionFromPaperSequence'; import { gotoReviewSavedPetitionSequence } from './sequences/gotoReviewSavedPetitionSequence'; import { gotoSecondaryContactEditSequence } from './sequences/gotoSecondaryContactEditSequence'; import { gotoSelectDocumentTypeSequence } from './sequences/gotoSelectDocumentTypeSequence'; @@ -138,11 +134,11 @@ import { loadPdfSequence } from './sequences/PDFPreviewModal/loadPdfSequence'; import { loginWithCodeSequence } from './sequences/loginWithCodeSequence'; import { loginWithTokenSequence } from './sequences/loginWithTokenSequence'; import { navigateBackSequence } from './sequences/navigateBackSequence'; +import { navigateToCaseDetailFromPaperServiceSequence } from './sequences/navigateToCaseDetailFromPaperServiceSequence'; import { navigateToCaseDetailSequence } from './sequences/navigateToCaseDetailSequence'; import { navigateToEditOrderSequence } from './sequences/navigateToEditOrderSequence'; -import { navigateToEditSavedPetitionSequence } from './sequences/navigateToEditSavedPetitionSequence'; import { navigateToPathSequence } from './sequences/navigateToPathSequence'; -import { navigateToPrintPreviewSequence } from './sequences/navigateToPrintPreviewSequence'; +import { navigateToPrintPaperServiceSequence } from './sequences/navigateToPrintPaperServiceSequence'; import { navigateToPrintableCaseConfirmationSequence } from './sequences/navigateToPrintableCaseConfirmationSequence'; import { navigateToPrintableDocketRecordSequence } from './sequences/navigateToPrintableDocketRecordSequence'; import { navigateToReviewSavedPetitionSequence } from './sequences/navigateToReviewSavedPetitionSequence'; @@ -196,7 +192,7 @@ import { printTrialCalendarSequence } from './sequences/printTrialCalendarSequen import { prioritizeCaseSequence } from './sequences/prioritizeCaseSequence'; import { redirectToLoginSequence } from './sequences/redirectToLoginSequence'; import { refreshCaseSequence } from './sequences/refreshCaseSequence'; -import { refreshPdfWhenSwitchingCreateOrderTabSequence } from './sequences/refreshPdfWhenSwitchingCreateOrderTabSequence'; +import { refreshPdfSequence } from './sequences/refreshPdfSequence'; import { removeBatchSequence } from './sequences/removeBatchSequence'; import { removeCaseDetailPendingItemSequence } from './sequences/removeCaseDetailPendingItemSequence'; import { removeCaseFromTrialSequence } from './sequences/removeCaseFromTrialSequence'; @@ -208,7 +204,6 @@ import { rescanBatchSequence } from './sequences/rescanBatchSequence'; import { resetCaseMenuSequence } from './sequences/resetCaseMenuSequence'; import { resetHeaderAccordionsSequence } from './sequences/resetHeaderAccordionsSequence'; import { reviewExternalDocumentInformationSequence } from './sequences/reviewExternalDocumentInformationSequence'; -import { reviewPetitionFromPaperSequence } from './sequences/reviewPetitionFromPaperSequence'; import { reviewRequestAccessInformationSequence } from './sequences/reviewRequestAccessInformationSequence'; import { runTrialSessionPlanningReportSequence } from './sequences/runTrialSessionPlanningReportSequence'; import { saveCaseAndServeToIrsSequence } from './sequences/saveCaseAndServeToIrsSequence'; @@ -280,6 +275,7 @@ import { submitFilePetitionSequence } from './sequences/submitFilePetitionSequen import { submitForwardSequence } from './sequences/submitForwardSequence'; import { submitLoginSequence } from './sequences/submitLoginSequence'; import { submitOrderAdvancedSearchSequence } from './sequences/submitOrderAdvancedSearchSequence'; +import { submitPetitionFromPaperSequence } from './sequences/submitPetitionFromPaperSequence'; import { submitPractitionerBarNumberSearchSequence } from './sequences/submitPractitionerBarNumberSearchSequence'; import { submitPractitionerNameSearchSequence } from './sequences/submitPractitionerNameSearchSequence'; import { submitRemoveConsolidatedCasesSequence } from './sequences/submitRemoveConsolidatedCasesSequence'; @@ -300,13 +296,13 @@ import { unblockCaseFromTrialSequence } from './sequences/unblockCaseFromTrialSe import { unidentifiedUserErrorSequence } from './sequences/unidentifiedUserErrorSequence'; import { unprioritizeCaseSequence } from './sequences/unprioritizeCaseSequence'; import { unsetWorkQueueIsInternalSequence } from './sequences/unsetWorkQueueIsInternalSequence'; +import { updateAdvancedOrderSearchFormValueSequence } from './sequences/updateAdvancedOrderSearchFormValueSequence'; import { updateAdvancedSearchFormValueSequence } from './sequences/updateAdvancedSearchFormValueSequence'; import { updateBatchDownloadProgressSequence } from './sequences/updateBatchDownloadProgressSequence'; import { updateCaseAssociationFormValueSequence } from './sequences/updateCaseAssociationFormValueSequence'; import { updateCaseDeadlineSequence } from './sequences/updateCaseDeadlineSequence'; import { updateCaseNoteSequence } from './sequences/updateCaseNoteSequence'; import { updateCasePartyTypeSequence } from './sequences/updateCasePartyTypeSequence'; -import { updateCaseValueAndInternalCaseCaptionSequence } from './sequences/updateCaseValueAndInternalCaseCaptionSequence'; import { updateCaseWorkingCopyUserNoteSequence } from './sequences/updateCaseWorkingCopyUserNoteSequence'; import { updateCompleteFormValueSequence } from './sequences/updateCompleteFormValueSequence'; import { updateCourtIssuedDocketEntryFormValueSequence } from './sequences/updateCourtIssuedDocketEntryFormValueSequence'; @@ -316,7 +312,7 @@ import { updateDocketEntryMetaDocumentFormValueSequence } from './sequences/upda import { updateDocketNumberSearchFormSequence } from './sequences/updateDocketNumberSearchFormSequence'; import { updateFileDocumentWizardFormValueSequence } from './sequences/updateFileDocumentWizardFormValueSequence'; import { updateFormPartyTypeSequence } from './sequences/updateFormPartyTypeSequence'; -import { updateFormValueAndInternalCaseCaptionSequence } from './sequences/updateFormValueAndInternalCaseCaptionSequence'; +import { updateFormValueAndCaseCaptionSequence } from './sequences/updateFormValueAndCaseCaptionSequence'; import { updateFormValueAndSecondaryContactInfoSequence } from './sequences/updateFormValueAndSecondaryContactInfoSequence'; import { updateFormValueSequence } from './sequences/updateFormValueSequence'; import { updateForwardFormValueSequence } from './sequences/updateForwardFormValueSequence'; @@ -437,13 +433,11 @@ export const presenter = { confirmStayLoggedInSequence, contactPrimaryCountryTypeChangeSequence, contactSecondaryCountryTypeChangeSequence, - convertHtml2PdfAndOpenInNewTabSequence, convertHtml2PdfSequence, copyPrimaryContactSequence, countryTypeFormContactChangeSequence, countryTypeUserContactChangeSequence, createCaseDeadlineSequence, - createCaseFromPaperAndServeToIrsSequence, createWorkItemSequence, deleteCaseDeadlineSequence, deleteCaseNoteSequence, @@ -460,8 +454,7 @@ export const presenter = { fetchPendingItemsSequence, fetchUserNotificationsSequence, formCancelToggleCancelSequence, - generateCaseCaptionForSavedPetitionSequence, - generateInternalCaseCaptionSequence, + generateCaseCaptionSequence, generatePdfFromScanSessionSequence, getBlockedCasesByTrialLocationSequence, getCaseInventoryReportSequence, @@ -502,14 +495,13 @@ export const presenter = { gotoPendingReportSequence, gotoPractitionerDetailSequence, gotoPrimaryContactEditSequence, - gotoPrintPreviewSequence, + gotoPrintPaperServiceSequence, gotoPrintableCaseConfirmationSequence, gotoPrintableCaseInventoryReportSequence, gotoPrintableDocketRecordSequence, gotoPrintablePendingReportForCaseSequence, gotoPrintablePendingReportSequence, gotoRequestAccessSequence, - gotoReviewPetitionFromPaperSequence, gotoReviewSavedPetitionSequence, gotoSecondaryContactEditSequence, gotoSelectDocumentTypeSequence, @@ -529,11 +521,11 @@ export const presenter = { loginWithCodeSequence, loginWithTokenSequence, navigateBackSequence, + navigateToCaseDetailFromPaperServiceSequence, navigateToCaseDetailSequence, navigateToEditOrderSequence, - navigateToEditSavedPetitionSequence, navigateToPathSequence, - navigateToPrintPreviewSequence, + navigateToPrintPaperServiceSequence, navigateToPrintableCaseConfirmationSequence, navigateToPrintableDocketRecordSequence, navigateToReviewSavedPetitionSequence, @@ -587,7 +579,7 @@ export const presenter = { prioritizeCaseSequence, redirectToLoginSequence, refreshCaseSequence, - refreshPdfWhenSwitchingCreateOrderTabSequence, + refreshPdfSequence, removeBatchSequence, removeCaseDetailPendingItemSequence, removeCaseFromTrialSequence, @@ -599,7 +591,6 @@ export const presenter = { resetCaseMenuSequence, resetHeaderAccordionsSequence, reviewExternalDocumentInformationSequence, - reviewPetitionFromPaperSequence, reviewRequestAccessInformationSequence, runTrialSessionPlanningReportSequence, saveCaseAndServeToIrsSequence, @@ -669,6 +660,7 @@ export const presenter = { submitForwardSequence, submitLoginSequence, submitOrderAdvancedSearchSequence, + submitPetitionFromPaperSequence, submitPractitionerBarNumberSearchSequence, submitPractitionerNameSearchSequence, submitRemoveConsolidatedCasesSequence, @@ -689,13 +681,13 @@ export const presenter = { unidentifiedUserErrorSequence, unprioritizeCaseSequence, unsetWorkQueueIsInternalSequence, + updateAdvancedOrderSearchFormValueSequence, updateAdvancedSearchFormValueSequence, updateBatchDownloadProgressSequence, updateCaseAssociationFormValueSequence, updateCaseDeadlineSequence, updateCaseNoteSequence, updateCasePartyTypeSequence, - updateCaseValueAndInternalCaseCaptionSequence, updateCaseWorkingCopyUserNoteSequence, updateCompleteFormValueSequence, updateCourtIssuedDocketEntryFormValueSequence, @@ -705,7 +697,7 @@ export const presenter = { updateDocketNumberSearchFormSequence, updateFileDocumentWizardFormValueSequence, updateFormPartyTypeSequence, - updateFormValueAndInternalCaseCaptionSequence, + updateFormValueAndCaseCaptionSequence, updateFormValueAndSecondaryContactInfoSequence, updateFormValueSequence, updateForwardFormValueSequence, diff --git a/web-client/src/presenter/sequences/advancedSearchTabChangeSequence.js b/web-client/src/presenter/sequences/advancedSearchTabChangeSequence.js index fa32a6e9c0c..f376cf734d9 100644 --- a/web-client/src/presenter/sequences/advancedSearchTabChangeSequence.js +++ b/web-client/src/presenter/sequences/advancedSearchTabChangeSequence.js @@ -1,7 +1,9 @@ +import { clearAlertsAction } from '../actions/clearAlertsAction'; import { clearSearchResultsAction } from '../actions/AdvancedSearch/clearSearchResultsAction'; import { defaultAdvancedSearchFormAction } from '../actions/AdvancedSearch/defaultAdvancedSearchFormAction'; export const advancedSearchTabChangeSequence = [ + clearAlertsAction, defaultAdvancedSearchFormAction, clearSearchResultsAction, ]; diff --git a/web-client/src/presenter/sequences/convertHtml2PdfSequence.js b/web-client/src/presenter/sequences/convertHtml2PdfSequence.js index cff925474b4..bd3d25d3322 100644 --- a/web-client/src/presenter/sequences/convertHtml2PdfSequence.js +++ b/web-client/src/presenter/sequences/convertHtml2PdfSequence.js @@ -1,6 +1,7 @@ import { clearPdfPreviewUrlAction } from '../actions/CourtIssuedOrder/clearPdfPreviewUrlAction'; import { createOrderAction } from '../actions/CourtIssuedOrder/createOrderAction'; -import { getPdfFileAction } from '../actions/CourtIssuedOrder/getPdfFileAction'; +import { getPdfFromUrlAction } from '../actions/CourtIssuedOrder/getPdfFromUrlAction'; +import { getPdfUrlAction } from '../actions/CourtIssuedOrder/getPdfUrlAction'; import { setMetadataAsPristineAction } from '../actions/setMetadataAsPristineAction'; import { setPdfFileAction } from '../actions/CourtIssuedOrder/setPdfFileAction'; import { setPdfPreviewUrlAction } from '../actions/CourtIssuedOrder/setPdfPreviewUrlAction'; @@ -9,7 +10,8 @@ import { showProgressSequenceDecorator } from '../utilities/sequenceHelpers'; export const convertHtml2PdfSequence = showProgressSequenceDecorator([ createOrderAction, clearPdfPreviewUrlAction, - getPdfFileAction, + getPdfUrlAction, + getPdfFromUrlAction, setPdfFileAction, setPdfPreviewUrlAction, setMetadataAsPristineAction, diff --git a/web-client/src/presenter/sequences/createCaseFromPaperAndServeToIrsSequence.js b/web-client/src/presenter/sequences/createCaseFromPaperAndServeToIrsSequence.js deleted file mode 100644 index 852464fad76..00000000000 --- a/web-client/src/presenter/sequences/createCaseFromPaperAndServeToIrsSequence.js +++ /dev/null @@ -1,64 +0,0 @@ -import { clearFormAction } from '../actions/clearFormAction'; -import { clearModalAction } from '../actions/clearModalAction'; -import { clearPdfPreviewUrlAction } from '../actions/CourtIssuedOrder/clearPdfPreviewUrlAction'; -import { closeFileUploadStatusModalAction } from '../actions/closeFileUploadStatusModalAction'; -import { computeDateReceivedAction } from '../actions/DocketEntry/computeDateReceivedAction'; -import { computeIrsNoticeDateAction } from '../actions/StartCaseInternal/computeIrsNoticeDateAction'; -import { computePetitionFeeDatesAction } from '../actions/StartCaseInternal/computePetitionFeeDatesAction'; -import { createCaseFromPaperAction } from '../actions/createCaseFromPaperAction'; -import { getServeToIrsAlertSuccessAction } from '../actions/StartCaseInternal/getServeToIrsAlertSuccessAction'; -import { isPrintPreviewPreparedAction } from '../actions/CourtIssuedOrder/isPrintPreviewPreparedAction'; -import { navigateToCaseDetailAction } from '../actions/navigateToCaseDetailAction'; -import { openFileUploadErrorModal } from '../actions/openFileUploadErrorModal'; -import { openFileUploadStatusModalAction } from '../actions/openFileUploadStatusModalAction'; -import { serveCaseToIrsAction } from '../actions/StartCaseInternal/serveCaseToIrsAction'; -import { setAlertSuccessAction } from '../actions/setAlertSuccessAction'; -import { setCaseAction } from '../actions/setCaseAction'; -import { setCaseConfirmationFormDocumentTitleAction } from '../actions/StartCaseInternal/setCaseConfirmationFormDocumentTitleAction'; -import { setCaseNotInProgressAction } from '../actions/StartCaseInternal/setCaseNotInProgressAction'; -import { setDocumentIdAction } from '../actions/setDocumentIdAction'; -import { setPdfPreviewUrlAction } from '../actions/CourtIssuedOrder/setPdfPreviewUrlAction'; -import { setPetitionIdAction } from '../actions/setPetitionIdAction'; -import { setSaveAlertsForNavigationAction } from '../actions/setSaveAlertsForNavigationAction'; -import { setShowModalFactoryAction } from '../actions/setShowModalFactoryAction'; -import { showProgressSequenceDecorator } from '../utilities/sequenceHelpers'; - -export const createCaseFromPaperAndServeToIrsSequence = [ - computeDateReceivedAction, - computeIrsNoticeDateAction, - computePetitionFeeDatesAction, - clearPdfPreviewUrlAction, - showProgressSequenceDecorator([ - openFileUploadStatusModalAction, - setCaseNotInProgressAction, - createCaseFromPaperAction, - { - error: [openFileUploadErrorModal], - success: [ - setCaseAction, - setPetitionIdAction, - setDocumentIdAction, - closeFileUploadStatusModalAction, - serveCaseToIrsAction, - { - electronic: [], - paper: [setPdfPreviewUrlAction], - }, - clearModalAction, - getServeToIrsAlertSuccessAction, - setAlertSuccessAction, - setSaveAlertsForNavigationAction, - navigateToCaseDetailAction, - isPrintPreviewPreparedAction, - { - no: [], - yes: [ - clearFormAction, - setCaseConfirmationFormDocumentTitleAction, - setShowModalFactoryAction('PaperServiceConfirmModal'), - ], - }, - ], - }, - ]), -]; diff --git a/web-client/src/presenter/sequences/generateCaseCaptionForSavedPetitionSequence.js b/web-client/src/presenter/sequences/generateCaseCaptionForSavedPetitionSequence.js deleted file mode 100644 index a3886d2738b..00000000000 --- a/web-client/src/presenter/sequences/generateCaseCaptionForSavedPetitionSequence.js +++ /dev/null @@ -1,7 +0,0 @@ -import { getCaseCaptionForCaseInfoTabAction } from '../actions/caseDetailEdit/getCaseCaptionForCaseInfoTabAction'; -import { setCaseCaptionForCaseInfoTabAction } from '../actions/caseDetailEdit/setCaseCaptionForCaseInfoTabAction'; - -export const generateCaseCaptionForSavedPetitionSequence = [ - getCaseCaptionForCaseInfoTabAction, - setCaseCaptionForCaseInfoTabAction, -]; diff --git a/web-client/src/presenter/sequences/generateCaseCaptionSequence.js b/web-client/src/presenter/sequences/generateCaseCaptionSequence.js new file mode 100644 index 00000000000..26ac72df0e3 --- /dev/null +++ b/web-client/src/presenter/sequences/generateCaseCaptionSequence.js @@ -0,0 +1,7 @@ +import { getCaseCaptionForCaseInfoTabAction } from '../actions/StartCaseInternal/getCaseCaptionForCaseInfoTabAction'; +import { setCaseCaptionForCaseInfoTabAction } from '../actions/StartCaseInternal/setCaseCaptionForCaseInfoTabAction'; + +export const generateCaseCaptionSequence = [ + getCaseCaptionForCaseInfoTabAction, + setCaseCaptionForCaseInfoTabAction, +]; diff --git a/web-client/src/presenter/sequences/generateInternalCaseCaptionSequence.js b/web-client/src/presenter/sequences/generateInternalCaseCaptionSequence.js deleted file mode 100644 index a587b964b28..00000000000 --- a/web-client/src/presenter/sequences/generateInternalCaseCaptionSequence.js +++ /dev/null @@ -1,7 +0,0 @@ -import { getInternalCaseCaptionForCaseInfoTabAction } from '../actions/StartCaseInternal/getInternalCaseCaptionForCaseInfoTabAction'; -import { setInternalCaseCaptionForCaseInfoTabAction } from '../actions/StartCaseInternal/setInternalCaseCaptionForCaseInfoTabAction'; - -export const generateInternalCaseCaptionSequence = [ - getInternalCaseCaptionForCaseInfoTabAction, - setInternalCaseCaptionForCaseInfoTabAction, -]; diff --git a/web-client/src/presenter/sequences/generateInternalCaseCaptionSequence.test.js b/web-client/src/presenter/sequences/generateInternalCaseCaptionSequence.test.js deleted file mode 100644 index 179fb726fc0..00000000000 --- a/web-client/src/presenter/sequences/generateInternalCaseCaptionSequence.test.js +++ /dev/null @@ -1,31 +0,0 @@ -import { CerebralTest } from 'cerebral/test'; -import { ContactFactory } from '../../../../shared/src/business/entities/contacts/ContactFactory'; -import { applicationContextForClient as applicationContext } from '../../../../shared/src/business/test/createTestApplicationContext'; -import { generateInternalCaseCaptionSequence } from '../sequences/generateInternalCaseCaptionSequence'; -import { presenter } from '../presenter-mock'; -describe('generateInternalCaseCaptionSequence', () => { - let test; - beforeAll(() => { - presenter.providers.applicationContext = applicationContext; - presenter.sequences = { - generateInternalCaseCaptionSequence, - }; - test = CerebralTest(presenter); - }); - it('should create and set a case caption for the case', async () => { - test.setState('form', { - contactPrimary: { - name: 'Carl Fredricksen', - }, - partyType: ContactFactory.PARTY_TYPES.petitioner, - }); - - await test.runSequence('generateInternalCaseCaptionSequence', { - tab: 'caseInfo', - }); - - expect(test.getState('form.caseCaption')).toBe( - 'Carl Fredricksen, Petitioner', - ); - }); -}); diff --git a/web-client/src/presenter/sequences/gotoEditCourtIssuedDocketEntrySequence.js b/web-client/src/presenter/sequences/gotoEditCourtIssuedDocketEntrySequence.js index 89afe74e6e8..ac40dbf1533 100644 --- a/web-client/src/presenter/sequences/gotoEditCourtIssuedDocketEntrySequence.js +++ b/web-client/src/presenter/sequences/gotoEditCourtIssuedDocketEntrySequence.js @@ -1,5 +1,7 @@ import { clearFormAction } from '../actions/clearFormAction'; import { clearScreenMetadataAction } from '../actions/clearScreenMetadataAction'; +import { computeFormDateAction } from '../actions/computeFormDateAction'; +import { generateCourtIssuedDocumentTitleAction } from '../actions/CourtIssuedDocketEntry/generateCourtIssuedDocumentTitleAction'; import { getCaseAction } from '../actions/getCaseAction'; import { getUsersInSectionAction } from '../actions/getUsersInSectionAction'; import { isLoggedInAction } from '../actions/isLoggedInAction'; @@ -23,6 +25,8 @@ export const gotoEditCourtIssuedDocketEntry = [ getCaseAction, setCaseAction, setDocketEntryFormForDocketEditAction, + computeFormDateAction, + generateCourtIssuedDocumentTitleAction, setDocumentIdAction, set(state.isEditingDocketEntry, true), setCurrentPageAction('CourtIssuedDocketEntry'), diff --git a/web-client/src/presenter/sequences/gotoPrintPreviewSequence.js b/web-client/src/presenter/sequences/gotoPrintPaperServiceSequence.js similarity index 87% rename from web-client/src/presenter/sequences/gotoPrintPreviewSequence.js rename to web-client/src/presenter/sequences/gotoPrintPaperServiceSequence.js index a5d7473a3bf..76986494c69 100644 --- a/web-client/src/presenter/sequences/gotoPrintPreviewSequence.js +++ b/web-client/src/presenter/sequences/gotoPrintPaperServiceSequence.js @@ -6,7 +6,7 @@ import { setAlertWarningAction } from '../actions/setAlertWarningAction'; import { setCaseAction } from '../actions/setCaseAction'; import { setCurrentPageAction } from '../actions/setCurrentPageAction'; -export const gotoPrintPreviewSequence = [ +export const gotoPrintPaperServiceSequence = [ setCurrentPageAction('Interstitial'), clearModalAction, clearFormAction, @@ -14,5 +14,5 @@ export const gotoPrintPreviewSequence = [ getCaseAction, setCaseAction, setAlertWarningAction, - setCurrentPageAction('PrintPreview'), + setCurrentPageAction('PrintPaperService'), ]; diff --git a/web-client/src/presenter/sequences/gotoReviewPetitionFromPaperSequence.js b/web-client/src/presenter/sequences/gotoReviewPetitionFromPaperSequence.js deleted file mode 100644 index dc98d4f428a..00000000000 --- a/web-client/src/presenter/sequences/gotoReviewPetitionFromPaperSequence.js +++ /dev/null @@ -1,12 +0,0 @@ -import { canNavigateToReviewPetitionFromPaperScreenAction } from '../actions/StartCaseInternal/canNavigateToReviewPetitionFromPaperScreenAction'; -import { getInitialNextStepAction } from '../actions/StartCaseInternal/getInitialNextStepAction'; -import { navigateToStartCaseWizardNextStepAction } from '../actions/StartCase/navigateToStartCaseWizardNextStepAction'; -import { setCurrentPageAction } from '../actions/setCurrentPageAction'; - -export const gotoReviewPetitionFromPaperSequence = [ - canNavigateToReviewPetitionFromPaperScreenAction, - { - no: [getInitialNextStepAction, navigateToStartCaseWizardNextStepAction], - yes: [setCurrentPageAction('ReviewPetitionFromPaper')], - }, -]; diff --git a/web-client/src/presenter/sequences/gotoReviewSavedPetitionSequence.js b/web-client/src/presenter/sequences/gotoReviewSavedPetitionSequence.js index 4102193e696..ecc0fe6e647 100644 --- a/web-client/src/presenter/sequences/gotoReviewSavedPetitionSequence.js +++ b/web-client/src/presenter/sequences/gotoReviewSavedPetitionSequence.js @@ -3,6 +3,7 @@ import { getCaseAction } from '../actions/getCaseAction'; import { navigateToDocumentDetailAction } from '../actions/navigateToDocumentDetailAction'; import { setCaseAction } from '../actions/setCaseAction'; import { setCaseOnFormAction } from '../actions/setCaseOnFormAction'; +import { setCaseOnFormUsingStateAction } from '../actions/setCaseOnFormUsingStateAction'; import { setCurrentPageAction } from '../actions/setCurrentPageAction'; import { shouldLoadCaseAction } from '../actions/shouldLoadCaseAction'; @@ -13,7 +14,7 @@ export const gotoReviewSavedPetitionSequence = [ yes: [ shouldLoadCaseAction, { - ignore: [], + ignore: [setCaseOnFormUsingStateAction], load: [getCaseAction, setCaseAction, setCaseOnFormAction], }, setCurrentPageAction('ReviewSavedPetition'), diff --git a/web-client/src/presenter/sequences/navigateToCaseDetailFromPaperServiceSequence.js b/web-client/src/presenter/sequences/navigateToCaseDetailFromPaperServiceSequence.js new file mode 100644 index 00000000000..63dcdcef914 --- /dev/null +++ b/web-client/src/presenter/sequences/navigateToCaseDetailFromPaperServiceSequence.js @@ -0,0 +1,11 @@ +import { getPaperServiceSuccessMessageAction } from '../actions/getPaperServiceSuccessMessageAction'; +import { navigateToCaseDetailAction } from '../actions/navigateToCaseDetailAction'; +import { setAlertSuccessAction } from '../actions/setAlertSuccessAction'; +import { setSaveAlertsForNavigationAction } from '../actions/setSaveAlertsForNavigationAction'; + +export const navigateToCaseDetailFromPaperServiceSequence = [ + setSaveAlertsForNavigationAction, + getPaperServiceSuccessMessageAction, + setAlertSuccessAction, + navigateToCaseDetailAction, +]; diff --git a/web-client/src/presenter/sequences/navigateToEditSavedPetitionSequence.js b/web-client/src/presenter/sequences/navigateToEditSavedPetitionSequence.js deleted file mode 100644 index b89eddbd806..00000000000 --- a/web-client/src/presenter/sequences/navigateToEditSavedPetitionSequence.js +++ /dev/null @@ -1,7 +0,0 @@ -import { navigateToEditSavedPetitionAction } from '../actions/caseDetailEdit/navigateToEditSavedPetitionAction'; -import { setDocumentDetailTabAction } from '../actions/setDocumentDetailTabAction'; - -export const navigateToEditSavedPetitionSequence = [ - navigateToEditSavedPetitionAction, - setDocumentDetailTabAction, -]; diff --git a/web-client/src/presenter/sequences/navigateToPrintPaperServiceSequence.js b/web-client/src/presenter/sequences/navigateToPrintPaperServiceSequence.js new file mode 100644 index 00000000000..025bfb8a4e9 --- /dev/null +++ b/web-client/src/presenter/sequences/navigateToPrintPaperServiceSequence.js @@ -0,0 +1,5 @@ +import { navigateToPrintPaperServiceAction } from '../actions/navigateToPrintPaperServiceAction'; + +export const navigateToPrintPaperServiceSequence = [ + navigateToPrintPaperServiceAction, +]; diff --git a/web-client/src/presenter/sequences/navigateToPrintPreviewSequence.js b/web-client/src/presenter/sequences/navigateToPrintPreviewSequence.js deleted file mode 100644 index bd5709b40be..00000000000 --- a/web-client/src/presenter/sequences/navigateToPrintPreviewSequence.js +++ /dev/null @@ -1,3 +0,0 @@ -import { navigateToPrintPreviewAction } from '../actions/navigateToPrintPreviewAction'; - -export const navigateToPrintPreviewSequence = [navigateToPrintPreviewAction]; diff --git a/web-client/src/presenter/sequences/noticeGenerationCompleteSequence.js b/web-client/src/presenter/sequences/noticeGenerationCompleteSequence.js index 0adf6462c4b..b037c0a9d89 100644 --- a/web-client/src/presenter/sequences/noticeGenerationCompleteSequence.js +++ b/web-client/src/presenter/sequences/noticeGenerationCompleteSequence.js @@ -2,14 +2,12 @@ import { clearModalAction } from '../actions/clearModalAction'; import { clearModalStateAction } from '../actions/clearModalStateAction'; import { getCaseAction } from '../actions/getCaseAction'; import { getNoticeGenerationSuccessMessageAction } from '../actions/TrialSession/getNoticeGenerationSuccessMessageAction'; - import { hasPaperAction } from '../actions/hasPaperAction'; -import { navigateToPdfPreviewAction } from '../actions/navigateToPdfPreviewAction'; +import { navigateToPrintPaperServiceAction } from '../actions/navigateToPrintPaperServiceAction'; import { setAlertSuccessAction } from '../actions/setAlertSuccessAction'; import { setAlertWarningAction } from '../actions/setAlertWarningAction'; -import { setCaseAction } from '../actions/setCaseAction'; - import { setAlternateBackLocationAction } from '../actions/setAlternateBackLocationAction'; +import { setCaseAction } from '../actions/setCaseAction'; import { setPdfPreviewUrlSequence } from './setPdfPreviewUrlSequence'; import { setTrialSessionCalendarAlertWarningAction } from '../actions/TrialSession/setTrialSessionCalendarAlertWarningAction'; import { shouldRefreshCaseAction } from '../actions/shouldRefreshCaseAction'; @@ -35,7 +33,7 @@ export const noticeGenerationCompleteSequence = [ paper: [ ...setPdfPreviewUrlSequence, setAlternateBackLocationAction, - navigateToPdfPreviewAction, + navigateToPrintPaperServiceAction, setTrialSessionCalendarAlertWarningAction, setAlertWarningAction, ], diff --git a/web-client/src/presenter/sequences/openPdfPreviewModalSequence.js b/web-client/src/presenter/sequences/openPdfPreviewModalSequence.js index ca0d8ebdcb4..e9bd3fe2878 100644 --- a/web-client/src/presenter/sequences/openPdfPreviewModalSequence.js +++ b/web-client/src/presenter/sequences/openPdfPreviewModalSequence.js @@ -1,7 +1,8 @@ import { getPDFForPreviewAction } from '../actions/getPDFForPreviewAction'; import { openPdfPreviewModalAction } from '../actions/openPdfPreviewModalAction'; +import { showProgressSequenceDecorator } from '../utilities/sequenceHelpers'; -export const openPdfPreviewModalSequence = [ +export const openPdfPreviewModalSequence = showProgressSequenceDecorator([ getPDFForPreviewAction, openPdfPreviewModalAction, -]; +]); diff --git a/web-client/src/presenter/sequences/convertHtml2PdfAndOpenInNewTabSequence.js b/web-client/src/presenter/sequences/refreshPdfSequence.js similarity index 53% rename from web-client/src/presenter/sequences/convertHtml2PdfAndOpenInNewTabSequence.js rename to web-client/src/presenter/sequences/refreshPdfSequence.js index 339f7ae4f4c..84f9af27639 100644 --- a/web-client/src/presenter/sequences/convertHtml2PdfAndOpenInNewTabSequence.js +++ b/web-client/src/presenter/sequences/refreshPdfSequence.js @@ -1,20 +1,18 @@ import { clearPdfPreviewUrlAction } from '../actions/CourtIssuedOrder/clearPdfPreviewUrlAction'; import { createOrderAction } from '../actions/CourtIssuedOrder/createOrderAction'; -import { getPdfFileAction } from '../actions/CourtIssuedOrder/getPdfFileAction'; -import { openPdfPreviewInNewTabAction } from '../actions/openPdfPreviewInNewTabAction'; +import { getPdfFromUrlAction } from '../actions/CourtIssuedOrder/getPdfFromUrlAction'; +import { getPdfUrlAction } from '../actions/CourtIssuedOrder/getPdfUrlAction'; import { setMetadataAsPristineAction } from '../actions/setMetadataAsPristineAction'; import { setPdfFileAction } from '../actions/CourtIssuedOrder/setPdfFileAction'; import { setPdfPreviewUrlAction } from '../actions/CourtIssuedOrder/setPdfPreviewUrlAction'; import { showProgressSequenceDecorator } from '../utilities/sequenceHelpers'; -export const convertHtml2PdfAndOpenInNewTabSequence = showProgressSequenceDecorator( - [ - createOrderAction, - clearPdfPreviewUrlAction, - getPdfFileAction, - setPdfFileAction, - setPdfPreviewUrlAction, - setMetadataAsPristineAction, - openPdfPreviewInNewTabAction, - ], -); +export const refreshPdfSequence = showProgressSequenceDecorator([ + createOrderAction, + clearPdfPreviewUrlAction, + getPdfUrlAction, + getPdfFromUrlAction, + setPdfFileAction, + setPdfPreviewUrlAction, + setMetadataAsPristineAction, +]); diff --git a/web-client/src/presenter/sequences/refreshPdfWhenSwitchingCreateOrderTabSequence.js b/web-client/src/presenter/sequences/refreshPdfWhenSwitchingCreateOrderTabSequence.js deleted file mode 100644 index d7f71dab4bf..00000000000 --- a/web-client/src/presenter/sequences/refreshPdfWhenSwitchingCreateOrderTabSequence.js +++ /dev/null @@ -1,23 +0,0 @@ -import { clearPdfPreviewUrlAction } from '../actions/CourtIssuedOrder/clearPdfPreviewUrlAction'; -import { createOrderAction } from '../actions/CourtIssuedOrder/createOrderAction'; -import { getPdfFileAction } from '../actions/CourtIssuedOrder/getPdfFileAction'; -import { setMetadataAsPristineAction } from '../actions/setMetadataAsPristineAction'; -import { setPdfFileAction } from '../actions/CourtIssuedOrder/setPdfFileAction'; -import { setPdfPreviewUrlAction } from '../actions/CourtIssuedOrder/setPdfPreviewUrlAction'; -import { shouldRefreshOrderPdfAction } from '../actions/CourtIssuedOrder/shouldRefreshOrderPdfAction'; -import { showProgressSequenceDecorator } from '../utilities/sequenceHelpers'; - -export const refreshPdfWhenSwitchingCreateOrderTabSequence = [ - shouldRefreshOrderPdfAction, - { - no: [], - yes: showProgressSequenceDecorator([ - createOrderAction, - clearPdfPreviewUrlAction, - getPdfFileAction, - setPdfFileAction, - setPdfPreviewUrlAction, - setMetadataAsPristineAction, - ]), - }, -]; diff --git a/web-client/src/presenter/sequences/serveCaseToIrsSequence.js b/web-client/src/presenter/sequences/serveCaseToIrsSequence.js index 6bad7a4b71e..96ba2ad43b0 100644 --- a/web-client/src/presenter/sequences/serveCaseToIrsSequence.js +++ b/web-client/src/presenter/sequences/serveCaseToIrsSequence.js @@ -1,3 +1,36 @@ +import { clearFormAction } from '../actions/clearFormAction'; +import { clearModalAction } from '../actions/clearModalAction'; +import { getServeToIrsAlertSuccessAction } from '../actions/StartCaseInternal/getServeToIrsAlertSuccessAction'; +import { isPrintPreviewPreparedAction } from '../actions/CourtIssuedOrder/isPrintPreviewPreparedAction'; +import { navigateToCaseDetailAction } from '../actions/navigateToCaseDetailAction'; import { serveCaseToIrsAction } from '../actions/StartCaseInternal/serveCaseToIrsAction'; +import { setAlertSuccessAction } from '../actions/setAlertSuccessAction'; +import { setCaseConfirmationFormDocumentTitleAction } from '../actions/StartCaseInternal/setCaseConfirmationFormDocumentTitleAction'; +import { setPdfPreviewUrlAction } from '../actions/CourtIssuedOrder/setPdfPreviewUrlAction'; +import { setSaveAlertsForNavigationAction } from '../actions/setSaveAlertsForNavigationAction'; +import { setShowModalFactoryAction } from '../actions/setShowModalFactoryAction'; +import { showProgressSequenceDecorator } from '../utilities/sequenceHelpers'; -export const serveCaseToIrsSequence = [serveCaseToIrsAction]; +export const serveCaseToIrsSequence = [ + showProgressSequenceDecorator([ + serveCaseToIrsAction, + { + electronic: [], + paper: [setPdfPreviewUrlAction], + }, + ]), + clearModalAction, + getServeToIrsAlertSuccessAction, + setAlertSuccessAction, + setSaveAlertsForNavigationAction, + navigateToCaseDetailAction, + isPrintPreviewPreparedAction, + { + no: [], + yes: [ + clearFormAction, + setCaseConfirmationFormDocumentTitleAction, + setShowModalFactoryAction('PaperServiceConfirmModal'), + ], + }, +]; diff --git a/web-client/src/presenter/sequences/serveCourtIssuedDocumentSequence.js b/web-client/src/presenter/sequences/serveCourtIssuedDocumentSequence.js index ea16b02eca2..ad73310eacd 100644 --- a/web-client/src/presenter/sequences/serveCourtIssuedDocumentSequence.js +++ b/web-client/src/presenter/sequences/serveCourtIssuedDocumentSequence.js @@ -4,7 +4,7 @@ import { clearPdfPreviewUrlAction } from '../actions/CourtIssuedOrder/clearPdfPr import { isEditingDocketEntryAction } from '../actions/CourtIssuedDocketEntry/isEditingDocketEntryAction'; import { isPrintPreviewPreparedAction } from '../actions/CourtIssuedOrder/isPrintPreviewPreparedAction'; import { navigateToCaseDetailAction } from '../actions/navigateToCaseDetailAction'; -import { navigateToPrintPreviewAction } from '../actions/CourtIssuedOrder/navigateToPrintPreviewAction'; +import { navigateToPrintPaperServiceAction } from '../actions/navigateToPrintPaperServiceAction'; import { serveCourtIssuedDocumentAction } from '../actions/serveCourtIssuedDocumentAction'; import { setAlertErrorAction } from '../actions/setAlertErrorAction'; import { setAlertSuccessAction } from '../actions/setAlertSuccessAction'; @@ -47,7 +47,7 @@ export const serveCourtIssuedDocumentSequence = [ isPrintPreviewPreparedAction, { no: [navigateToCaseDetailAction], - yes: [navigateToPrintPreviewAction], + yes: [navigateToPrintPaperServiceAction], }, ]), }, diff --git a/web-client/src/presenter/sequences/submitEditDocketEntryMetaSequence.js b/web-client/src/presenter/sequences/submitEditDocketEntryMetaSequence.js index 258284f460f..56d181f381c 100644 --- a/web-client/src/presenter/sequences/submitEditDocketEntryMetaSequence.js +++ b/web-client/src/presenter/sequences/submitEditDocketEntryMetaSequence.js @@ -4,6 +4,7 @@ import { clearModalAction } from '../actions/clearModalAction'; import { clearModalStateAction } from '../actions/clearModalStateAction'; import { computeCertificateOfServiceFormDateAction } from '../actions/FileDocument/computeCertificateOfServiceFormDateAction'; import { computeFilingFormDateAction } from '../actions/FileDocument/computeFilingFormDateAction'; +import { computeFormDateAction } from '../actions/computeFormDateAction'; import { generateCourtIssuedDocumentTitleAction } from '../actions/CourtIssuedDocketEntry/generateCourtIssuedDocumentTitleAction'; import { generateTitleAction } from '../actions/FileDocument/generateTitleAction'; import { getEditDocketEntryMetaAlertSuccessAction } from '../actions/EditDocketRecordEntry/getEditDocketEntryMetaAlertSuccessAction'; @@ -11,6 +12,7 @@ import { navigateToCaseDetailAction } from '../actions/navigateToCaseDetailActio import { primePropsFromEditDocketEntryMetaModalAction } from '../actions/EditDocketRecordEntry/primePropsFromEditDocketEntryMetaModalAction'; import { setAlertErrorAction } from '../actions/setAlertErrorAction'; import { setAlertSuccessAction } from '../actions/setAlertSuccessAction'; +import { setFormDateAction } from '../actions/setFormDateAction'; import { setSaveAlertsForNavigationAction } from '../actions/setSaveAlertsForNavigationAction'; import { setValidationAlertErrorsAction } from '../actions/setValidationAlertErrorsAction'; import { setValidationErrorsAction } from '../actions/setValidationErrorsAction'; @@ -25,6 +27,8 @@ export const submitEditDocketEntryMetaSequence = [ startShowValidationAction, computeFilingFormDateAction, computeCertificateOfServiceFormDateAction, + computeFormDateAction, + setFormDateAction, primePropsFromEditDocketEntryMetaModalAction, chooseMetaTypePathAction, { diff --git a/web-client/src/presenter/sequences/submitEditOrderTitleModalSequence.js b/web-client/src/presenter/sequences/submitEditOrderTitleModalSequence.js index a493bed06ff..b2c9fbebbff 100644 --- a/web-client/src/presenter/sequences/submitEditOrderTitleModalSequence.js +++ b/web-client/src/presenter/sequences/submitEditOrderTitleModalSequence.js @@ -1,6 +1,6 @@ import { clearAlertsAction } from '../actions/clearAlertsAction'; import { clearModalAction } from '../actions/clearModalAction'; -import { refreshPdfWhenSwitchingCreateOrderTabSequence } from './refreshPdfWhenSwitchingCreateOrderTabSequence'; +import { refreshPdfSequence } from './refreshPdfSequence'; import { setAlertErrorAction } from '../actions/setAlertErrorAction'; import { setCreateOrderModalDataOnFormAction } from '../actions/CourtIssuedOrder/setCreateOrderModalDataOnFormAction'; import { setValidationErrorsAction } from '../actions/setValidationErrorsAction'; @@ -16,7 +16,7 @@ export const submitEditOrderTitleModalSequence = [ success: [ clearModalAction, setCreateOrderModalDataOnFormAction, - refreshPdfWhenSwitchingCreateOrderTabSequence, + refreshPdfSequence, ], }, ]; diff --git a/web-client/src/presenter/sequences/reviewPetitionFromPaperSequence.js b/web-client/src/presenter/sequences/submitPetitionFromPaperSequence.js similarity index 52% rename from web-client/src/presenter/sequences/reviewPetitionFromPaperSequence.js rename to web-client/src/presenter/sequences/submitPetitionFromPaperSequence.js index 26b13a32a2f..f7cc3f29016 100644 --- a/web-client/src/presenter/sequences/reviewPetitionFromPaperSequence.js +++ b/web-client/src/presenter/sequences/submitPetitionFromPaperSequence.js @@ -1,18 +1,27 @@ +import { assignPetitionToAuthenticatedUserAction } from '../actions/WorkItem/assignPetitionToAuthenticatedUserAction'; import { checkForActiveBatchesAction } from '../actions/checkForActiveBatchesAction'; import { clearAlertsAction } from '../actions/clearAlertsAction'; +import { closeFileUploadStatusModalAction } from '../actions/closeFileUploadStatusModalAction'; import { computeDateReceivedAction } from '../actions/DocketEntry/computeDateReceivedAction'; import { computeIrsNoticeDateAction } from '../actions/StartCaseInternal/computeIrsNoticeDateAction'; import { computePetitionFeeDatesAction } from '../actions/StartCaseInternal/computePetitionFeeDatesAction'; -import { navigateToReviewPetitionFromPaperAction } from '../actions/StartCaseInternal/navigateToReviewPetitionFromPaperAction'; +import { createCaseFromPaperAction } from '../actions/createCaseFromPaperAction'; +import { navigateToReviewSavedPetitionAction } from '../actions/caseDetailEdit/navigateToReviewSavedPetitionAction'; +import { openFileUploadErrorModal } from '../actions/openFileUploadErrorModal'; import { setAlertErrorAction } from '../actions/setAlertErrorAction'; +import { setCaseAction } from '../actions/setCaseAction'; +import { setCaseInProgressAction } from '../actions/StartCaseInternal/setCaseInProgressAction'; +import { setDocumentIdAction } from '../actions/setDocumentIdAction'; +import { setPetitionIdAction } from '../actions/setPetitionIdAction'; import { setShowModalFactoryAction } from '../actions/setShowModalFactoryAction'; import { setValidationAlertErrorsAction } from '../actions/setValidationAlertErrorsAction'; import { setValidationErrorsAction } from '../actions/setValidationErrorsAction'; +import { showProgressSequenceDecorator } from '../utilities/sequenceHelpers'; import { startShowValidationAction } from '../actions/startShowValidationAction'; import { stopShowValidationAction } from '../actions/stopShowValidationAction'; import { validatePetitionFromPaperAction } from '../actions/validatePetitionFromPaperAction'; -export const reviewPetitionFromPaperSequence = [ +export const submitPetitionFromPaperSequence = [ checkForActiveBatchesAction, { hasActiveBatches: [setShowModalFactoryAction('UnfinishedScansModal')], @@ -31,7 +40,21 @@ export const reviewPetitionFromPaperSequence = [ ], success: [ stopShowValidationAction, - navigateToReviewPetitionFromPaperAction, + setCaseInProgressAction, + showProgressSequenceDecorator([ + createCaseFromPaperAction, + { + error: [openFileUploadErrorModal], + success: [ + setCaseAction, + assignPetitionToAuthenticatedUserAction, + setPetitionIdAction, + setDocumentIdAction, + closeFileUploadStatusModalAction, + navigateToReviewSavedPetitionAction, + ], + }, + ]), ], }, ], diff --git a/web-client/src/presenter/sequences/updateAdvancedOrderSearchFormValueSequence.js b/web-client/src/presenter/sequences/updateAdvancedOrderSearchFormValueSequence.js new file mode 100644 index 00000000000..c77328ef82a --- /dev/null +++ b/web-client/src/presenter/sequences/updateAdvancedOrderSearchFormValueSequence.js @@ -0,0 +1,6 @@ +import { props, state } from 'cerebral'; +import { set } from 'cerebral/factories'; + +export const updateAdvancedOrderSearchFormValueSequence = [ + set(state.advancedSearchForm['orderSearch'][props.key], props.value), +]; diff --git a/web-client/src/presenter/sequences/updateCaseValueAndInternalCaseCaptionSequence.js b/web-client/src/presenter/sequences/updateCaseValueAndInternalCaseCaptionSequence.js deleted file mode 100644 index e9d7098c578..00000000000 --- a/web-client/src/presenter/sequences/updateCaseValueAndInternalCaseCaptionSequence.js +++ /dev/null @@ -1,7 +0,0 @@ -import { generateCaseCaptionForSavedPetitionSequence } from './generateCaseCaptionForSavedPetitionSequence'; -import { setFormValueAction } from '../actions/setFormValueAction'; - -export const updateCaseValueAndInternalCaseCaptionSequence = [ - setFormValueAction, - generateCaseCaptionForSavedPetitionSequence, -]; diff --git a/web-client/src/presenter/sequences/updateFormValueAndCaseCaptionSequence.js b/web-client/src/presenter/sequences/updateFormValueAndCaseCaptionSequence.js new file mode 100644 index 00000000000..079248eec00 --- /dev/null +++ b/web-client/src/presenter/sequences/updateFormValueAndCaseCaptionSequence.js @@ -0,0 +1,7 @@ +import { generateCaseCaptionSequence } from './generateCaseCaptionSequence'; +import { updateFormValueSequence } from './updateFormValueSequence'; + +export const updateFormValueAndCaseCaptionSequence = [ + updateFormValueSequence, + generateCaseCaptionSequence, +]; diff --git a/web-client/src/presenter/sequences/updateFormValueAndInternalCaseCaptionSequence.js b/web-client/src/presenter/sequences/updateFormValueAndInternalCaseCaptionSequence.js deleted file mode 100644 index 3637e53740f..00000000000 --- a/web-client/src/presenter/sequences/updateFormValueAndInternalCaseCaptionSequence.js +++ /dev/null @@ -1,7 +0,0 @@ -import { generateInternalCaseCaptionSequence } from './generateInternalCaseCaptionSequence'; -import { updateFormValueSequence } from './updateFormValueSequence'; - -export const updateFormValueAndInternalCaseCaptionSequence = [ - updateFormValueSequence, - generateInternalCaseCaptionSequence, -]; diff --git a/web-client/src/presenter/state-public.js b/web-client/src/presenter/state-public.js index 6b1909c4a6a..8fc6bf7c3fb 100644 --- a/web-client/src/presenter/state-public.js +++ b/web-client/src/presenter/state-public.js @@ -28,6 +28,7 @@ export const state = { showUsaBannerDetails: false, }, currentPage: 'Interstitial', + isPublic: true, progressIndicator: { // used for the spinner that shows when waiting for network responses waitingForResponse: false, diff --git a/web-client/src/presenter/state.js b/web-client/src/presenter/state.js index 984fbdf165a..8415e330c94 100644 --- a/web-client/src/presenter/state.js +++ b/web-client/src/presenter/state.js @@ -57,7 +57,6 @@ import { pdfSignerHelper } from './computeds/pdfSignerHelper'; import { practitionerDetailHelper } from './computeds/practitionerDetailHelper'; import { practitionerSearchFormHelper } from './computeds/practitionerSearchFormHelper'; import { requestAccessHelper } from './computeds/requestAccessHelper'; -import { reviewPetitionFromPaperHelper } from './computeds/reviewPetitionFromPaperHelper'; import { reviewSavedPetitionHelper } from './computeds/reviewSavedPetitionHelper'; import { scanBatchPreviewerHelper } from './computeds/scanBatchPreviewerHelper'; import { scanHelper } from './computeds/scanHelper'; @@ -134,7 +133,6 @@ const helpers = { practitionerDetailHelper, practitionerSearchFormHelper, requestAccessHelper, - reviewPetitionFromPaperHelper, reviewSavedPetitionHelper, scanBatchPreviewerHelper, scanHelper, diff --git a/web-client/src/router.js b/web-client/src/router.js index 5effeb20bd9..5c21c9fc6e8 100644 --- a/web-client/src/router.js +++ b/web-client/src/router.js @@ -1,4 +1,4 @@ -import { forEach, isEmpty, set } from 'lodash'; +import { forEach, set } from 'lodash'; import { queryStringDecoder } from './utilities/queryStringDecoder'; import { setPageTitle } from './presenter/utilities/setPageTitle'; import route from 'riot-route'; @@ -138,32 +138,6 @@ const router = { }, ROLE_PERMISSIONS.UPDATE_CASE), ); - registerRoute( - '/case-detail/*/documents/*/edit-saved..', - ifHasAccess((docketNumber, documentId) => { - setPageTitle( - `${getPageTitleDocketPrefix( - docketNumber, - )} Edit saved document details`, - ); - - if (!isEmpty(app.getState('form'))) { - const { tab } = route.query(); - - return app.getSequence('gotoEditSavedPetitionSequence')({ - docketNumber, - documentId, - tab, - }); - } else { - return app.getSequence('gotoDocumentDetailSequence')({ - docketNumber, - documentId, - }); - } - }, ROLE_PERMISSIONS.UPDATE_CASE), - ); - registerRoute( '/case-detail/*/documents/*/review', ifHasAccess((docketNumber, documentId) => { @@ -693,10 +667,10 @@ const router = { ); registerRoute( - '/print-preview/*', + '/print-paper-service/*', ifHasAccess(docketNumber => { setPageTitle(`${getPageTitleDocketPrefix(docketNumber)} Print Service`); - return app.getSequence('gotoPrintPreviewSequence')({ + return app.getSequence('gotoPrintPaperServiceSequence')({ alertWarning: { message: 'Document electronically served. Print and mail all paper service documents now.', @@ -796,14 +770,6 @@ const router = { }), ); - registerRoute( - 'file-a-petition/review-petition', - ifHasAccess(() => { - setPageTitle('Review Petition'); - return app.getSequence('gotoReviewPetitionFromPaperSequence')(); - }), - ); - registerRoute( '/file-a-petition-pa11y/step-*', ifHasAccess(step => { diff --git a/web-client/src/routerPublic.js b/web-client/src/routerPublic.js index 7a6843dc3e6..945cb45ec26 100644 --- a/web-client/src/routerPublic.js +++ b/web-client/src/routerPublic.js @@ -23,7 +23,7 @@ const router = { initialize: app => { document.title = 'U.S. Tax Court'; - route('/', () => { + route('/..', () => { setPageTitle('Dashboard'); app.getSequence('gotoPublicSearchSequence')(); }); diff --git a/web-client/src/styles/custom.scss b/web-client/src/styles/custom.scss index 0ff783a453b..9dfa6b1dfbf 100644 --- a/web-client/src/styles/custom.scss +++ b/web-client/src/styles/custom.scss @@ -511,6 +511,10 @@ select[disabled] { color: color($theme-color-base); } +.small-column { + width: 1%; +} + .icon-column { width: 40px; } @@ -545,7 +549,7 @@ select[disabled] { width: 75px; height: 75px; padding: 20px; - background-color: color($theme-color-primary-dark); + background-color: color($theme-color-primary); border-radius: 55px; svg, @@ -590,13 +594,13 @@ select[disabled] { } .caseItem__icon { - position: absolute; top: 0; display: inline-block; - width: 75px; - height: 75px; - padding: 20px; - background-color: color($theme-color-primary-dark); + width: 40px; + height: 40px; + padding: 10px; + margin-right: 10px; + background-color: color($theme-color-primary); border-radius: 55px; svg, @@ -609,6 +613,7 @@ select[disabled] { margin-top: -3px; margin-left: 5px; } + } .svg-wrapper img.svg { @@ -617,9 +622,10 @@ select[disabled] { } @media only screen and (min-width: $medium-screen) { - width: 75px; - height: 75px; - padding: 20px; + width: 40px; + height: 40px; + padding: 8px; + margin-right: 10px; } } diff --git a/web-client/src/styles/icons.scss b/web-client/src/styles/icons.scss index 29fa044dd44..27138e3d064 100644 --- a/web-client/src/styles/icons.scss +++ b/web-client/src/styles/icons.scss @@ -2,6 +2,7 @@ margin-right: 0.5em; color: color($theme-color-base-darkest); } + button:not(.ustc-button--unstyled) .fa-file-pdf { color: $color-white; } @@ -37,6 +38,13 @@ button:not(.ustc-button--unstyled) .fa-file-pdf { color: color($theme-color-warning); } +.iconSealed { + margin-top: 4px; + margin-right: -22px; + color: color($theme-color-secondary-dark); + float: right; +} + .iconStatusUnassigned { color: color($theme-color-warning); } @@ -84,17 +92,17 @@ button:not(.ustc-button--unstyled) .fa-file-pdf { .bullet-icon-circle { width: 40px; height: 40px; - border: 2px solid color($theme-color-primary-dark); - background-color: color($theme-color-primary-dark); + border: 2px solid color($theme-color-accent-cool); + background-color: color($theme-color-accent-cool); border-radius: 25px; - color: color($theme-color-primary-dark); + color: color($theme-color-accent-cool); } .bullet-icon-wrapper { display: table-cell; - padding: 0 15px 30px 0; + padding: 15px 15px 30px 0; text-align: center; - vertical-align: middle; + vertical-align: top; } .description-wrapper { @@ -108,3 +116,6 @@ button:not(.ustc-button--unstyled) .fa-file-pdf { .icon-consolidated { color: color($theme-color-warning); } +.icon-upload { + color: $color-green; +} diff --git a/web-client/src/styles/tabs.scss b/web-client/src/styles/tabs.scss index ce8b8529811..21e89e242a0 100644 --- a/web-client/src/styles/tabs.scss +++ b/web-client/src/styles/tabs.scss @@ -13,7 +13,7 @@ } } - ul { + ul.ustc-ui-tabs { padding-left: 0; border-bottom: 1px solid color($theme-color-base-lighter); margin-top: 0; @@ -167,6 +167,7 @@ &:focus { border-bottom: none; background-color: none; + color: $color-white; span { padding-bottom: 0; @@ -185,13 +186,18 @@ cursor: default; &:hover { + color: color($theme-color-primary-darker); + span { - border-bottom: 3px solid color($theme-color-primary); + padding-bottom: 0; + border-bottom: 3px solid color($theme-color-primary-darker); } + } span { border-bottom: 3px solid color($theme-color-primary); + } } } diff --git a/web-client/src/styles/variables.scss b/web-client/src/styles/variables.scss index 96c0578da43..cf9e343fe36 100644 --- a/web-client/src/styles/variables.scss +++ b/web-client/src/styles/variables.scss @@ -29,4 +29,5 @@ $small-screen: 480px; $medium-screen: 640px; $large-screen: 1024px; + $table-column-width-small: 100px; diff --git a/web-client/src/ustc-ui/Accordion/Accordion.jsx b/web-client/src/ustc-ui/Accordion/Accordion.jsx index 048200bfeba..fac51653014 100644 --- a/web-client/src/ustc-ui/Accordion/Accordion.jsx +++ b/web-client/src/ustc-ui/Accordion/Accordion.jsx @@ -1,3 +1,4 @@ +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { connect } from '@cerebral/react'; import { decorateWithPostCallback } from '../utils/useCerebralState'; import { map } from '../utils/ElementChildren'; @@ -50,7 +51,15 @@ export const Accordion = connect( setTab = decorateWithPostCallback(setTab, onSelect); const renderTab = (child, index) => { - const { children, id, title } = child.props; + const { + children, + displayIcon = false, + iconClassName, + iconSize, + iconTypes, + id, + title, + } = child.props; let { itemName } = child.props; itemName = itemName || `item-${index}`; @@ -77,6 +86,15 @@ export const Accordion = connect( type="button" onClick={() => setTab(itemName)} > + {displayIcon && ( + + + + )} {title} diff --git a/web-client/src/ustc-ui/Button/Button.jsx b/web-client/src/ustc-ui/Button/Button.jsx index 46fa9ce76a2..fc401688ff6 100644 --- a/web-client/src/ustc-ui/Button/Button.jsx +++ b/web-client/src/ustc-ui/Button/Button.jsx @@ -13,6 +13,7 @@ export const Button = props => { iconSize = '1x', link, marginDirection = 'right', + overrideMargin = false, secondary, ...remainingProps } = props; @@ -21,7 +22,9 @@ export const Button = props => { const classes = classNames( className, - `usa-button margin-${marginDirection}-205`, + 'usa-button', + !overrideMargin && `margin-${marginDirection}-205`, + overrideMargin, icon && 'no-wrap', secondary && 'usa-button--outline', link && 'usa-button--unstyled ustc-button--unstyled', diff --git a/web-client/src/ustc-ui/Modal/BaseModal.jsx b/web-client/src/ustc-ui/Modal/BaseModal.jsx index 42b719c3094..8a295a413ce 100644 --- a/web-client/src/ustc-ui/Modal/BaseModal.jsx +++ b/web-client/src/ustc-ui/Modal/BaseModal.jsx @@ -38,7 +38,7 @@ export const BaseModal = connect( const blurDialog = event => { if (preventCancelOnBlur) { - return false; + return; } return runBlurSequence(event); }; diff --git a/web-client/src/ustc-ui/Tabs/Tabs.jsx b/web-client/src/ustc-ui/Tabs/Tabs.jsx index 2695bdf1993..d354ffb756d 100644 --- a/web-client/src/ustc-ui/Tabs/Tabs.jsx +++ b/web-client/src/ustc-ui/Tabs/Tabs.jsx @@ -47,7 +47,10 @@ export function TabsComponent({ defaultActiveTab || getDefaultAttribute(children, 'tabName'); if (bind) { - const useCerebralState = useCerebralStateFactory(simpleSetter, value); + const useCerebralState = useCerebralStateFactory( + simpleSetter, + value || defaultActiveTab, + ); [activeKey, setTab] = useCerebralState(bind, defaultActiveTab); } else { [activeKey, setTab] = useState(defaultActiveTab); @@ -61,7 +64,7 @@ export function TabsComponent({ const isActiveTab = tabName === activeKey; const tabContentId = asSwitch ? '' : `tabContent-${camelCase(tabName)}`; - var liClass = classNames({ + var liClass = classNames('ustc-ui-tabs', { active: isActiveTab, 'grid-col': boxed, }); @@ -143,7 +146,10 @@ export function TabsComponent({
{hasNav && ( diff --git a/web-client/src/views/AdvancedSearch/OrderSearch.jsx b/web-client/src/views/AdvancedSearch/OrderSearch.jsx index 2bdc79dcd27..27d145737d9 100644 --- a/web-client/src/views/AdvancedSearch/OrderSearch.jsx +++ b/web-client/src/views/AdvancedSearch/OrderSearch.jsx @@ -2,6 +2,8 @@ import { BindedSelect } from '../../ustc-ui/BindedSelect/BindedSelect'; import { Button } from '../../ustc-ui/Button/Button'; import { DateInput } from '../../ustc-ui/DateInput/DateInput'; import { FormGroup } from '../../ustc-ui/FormGroup/FormGroup'; +import { Mobile, NonMobile } from '../../ustc-ui/Responsive/Responsive'; +import { OrderSearchByKeyword } from './OrderSearchByKeyword'; import { connect } from '@cerebral/react'; import { sequences, state } from 'cerebral'; import React from 'react'; @@ -11,9 +13,10 @@ export const OrderSearch = connect( advancedSearchForm: state.advancedSearchForm, clearAdvancedSearchFormSequence: sequences.clearAdvancedSearchFormSequence, judges: state.judges, - updateAdvancedSearchFormValueSequence: - sequences.updateAdvancedSearchFormValueSequence, + updateAdvancedOrderSearchFormValueSequence: + sequences.updateAdvancedOrderSearchFormValueSequence, validateOrderSearchSequence: sequences.validateOrderSearchSequence, + validateStartDateSequence: sequences.validateStartDateSequence, validationErrors: state.validationErrors, }, function OrderSearch({ @@ -21,7 +24,7 @@ export const OrderSearch = connect( clearAdvancedSearchFormSequence, judges, submitAdvancedSearchSequence, - updateAdvancedSearchFormValueSequence, + updateAdvancedOrderSearchFormValueSequence, validateOrderSearchSequence, validationErrors, }) { @@ -39,181 +42,265 @@ export const OrderSearch = connect( }} >
-
-
-

Enter Keyword or Phrase

- -
+ +
+

Narrow your search (optional)

+ +
+
+ validateOrderSearchSequence()} onChange={e => { - updateAdvancedSearchFormValueSequence({ - formType: 'orderSearch', + updateAdvancedOrderSearchFormValueSequence({ key: e.target.name, value: e.target.value, }); }} /> - -
-
- -
-
- - -
-
-
- -
-
-

Narrow your search (optional)

- -
-
- - validateOrderSearchSequence()} - onChange={e => { - updateAdvancedSearchFormValueSequence({ - formType: 'orderSearch', - key: e.target.name, - value: e.target.value, - }); - }} - /> -
-
-
or
-
-
- - validateOrderSearchSequence()} - onChange={e => { - updateAdvancedSearchFormValueSequence({ - formType: 'orderSearch', - key: e.target.name, - value: e.target.value, - }); - }} - /> -
-
- -
-
diff --git a/web-client/src/views/AdvancedSearch/OrderSearchByKeyword.jsx b/web-client/src/views/AdvancedSearch/OrderSearchByKeyword.jsx new file mode 100644 index 00000000000..6b4119b8174 --- /dev/null +++ b/web-client/src/views/AdvancedSearch/OrderSearchByKeyword.jsx @@ -0,0 +1,48 @@ +import { FormGroup } from '../../ustc-ui/FormGroup/FormGroup'; +import { connect } from '@cerebral/react'; +import { sequences, state } from 'cerebral'; +import React from 'react'; + +export const OrderSearchByKeyword = connect( + { + advancedSearchForm: state.advancedSearchForm, + updateAdvancedOrderSearchFormValueSequence: + sequences.updateAdvancedOrderSearchFormValueSequence, + validateOrderSearchSequence: sequences.validateOrderSearchSequence, + }, + function OrderSearchByKeyword({ + advancedSearchForm, + updateAdvancedOrderSearchFormValueSequence, + validateOrderSearchSequence, + validationErrors, + }) { + return ( + <> +
+
+

Enter Keyword or Phrase

+ + + validateOrderSearchSequence()} + onChange={e => { + updateAdvancedOrderSearchFormValueSequence({ + key: e.target.name, + value: e.target.value, + }); + }} + /> + +
+
+ + ); + }, +); diff --git a/web-client/src/views/AdvancedSearch/OrderSearchResults.jsx b/web-client/src/views/AdvancedSearch/OrderSearchResults.jsx index 13e3c223aa1..10464d46157 100644 --- a/web-client/src/views/AdvancedSearch/OrderSearchResults.jsx +++ b/web-client/src/views/AdvancedSearch/OrderSearchResults.jsx @@ -1,5 +1,6 @@ import { Button } from '../../ustc-ui/Button/Button'; import { CaseLink } from '../../ustc-ui/CaseLink/CaseLink'; +import { Icon } from '../../ustc-ui/Icon/Icon'; import { connect } from '@cerebral/react'; import { sequences, state } from 'cerebral'; import React from 'react'; @@ -30,10 +31,12 @@ export const OrderSearchResults = connect( - + + + @@ -42,20 +45,37 @@ export const OrderSearchResults = connect( {advancedOrderSearchHelper.formattedSearchResults.map( (result, idx) => ( - + + - + + @@ -66,7 +86,11 @@ export const OrderSearchResults = connect( )} {advancedOrderSearchHelper.showLoadMore && ( - )} diff --git a/web-client/src/views/AdvancedSearch/SearchResults.jsx b/web-client/src/views/AdvancedSearch/SearchResults.jsx index 2ee73d29c79..79b53e4e0ab 100644 --- a/web-client/src/views/AdvancedSearch/SearchResults.jsx +++ b/web-client/src/views/AdvancedSearch/SearchResults.jsx @@ -63,7 +63,7 @@ export const SearchResults = connect( - + - + - +
Docket number Case title OrderPages Date Judge
{result.caseCaption}{result.caseTitle} {result.documentTitle} {result.numberOfPages} {result.formattedFiledDate} {result.formattedSignedJudgeName}
{result.formattedFiledDate}{result.caseCaptionNames}{result.caseTitle} {result.fullStateNamePrimary} {result.fullStateNameSecondary && ( @@ -76,7 +76,7 @@ export const SearchResults = connect( -
{result.caseCaptionNames}
+
{result.caseTitle}
Filed {result.formattedFiledDate}
diff --git a/web-client/src/views/AppComponent.jsx b/web-client/src/views/AppComponent.jsx index e0720fb1b6a..89dde23bc3f 100644 --- a/web-client/src/views/AppComponent.jsx +++ b/web-client/src/views/AppComponent.jsx @@ -43,12 +43,11 @@ import { Messages } from './Messages/Messages'; import { PendingReport } from './PendingReport/PendingReport'; import { PractitionerDetail } from './Practitioners/PractitionerDetail'; import { PrimaryContactEdit } from './PrimaryContactEdit'; -import { PrintPreview } from './CourtIssuedDocketEntry/PrintPreview'; +import { PrintPaperService } from './PrintPaperService'; import { PrintableCaseInventoryReport } from './CaseInventoryReport/PrintableCaseInventoryReport'; import { PrintableDocketRecord } from './DocketRecord/PrintableDocketRecord'; import { PrintableTrialCalendar } from './TrialSessionDetail/PrintableTrialCalendar'; import { RequestAccessWizard } from './RequestAccess/RequestAccessWizard'; -import { ReviewPetitionFromPaper } from './StartCaseInternal/ReviewPetitionFromPaper'; import { ReviewSavedPetition } from './CaseDetailEdit/ReviewSavedPetition'; import { SecondaryContactEdit } from './SecondaryContactEdit'; import { SelectDocumentType } from './FileDocument/SelectDocumentType'; @@ -111,12 +110,11 @@ const pages = { PendingReport, PractitionerDetail, PrimaryContactEdit, - PrintPreview, + PrintPaperService, PrintableCaseInventoryReport, PrintableDocketRecord, PrintableTrialCalendar, RequestAccessWizard, - ReviewPetitionFromPaper, ReviewSavedPetition, SecondaryContactEdit, SelectDocumentType, @@ -148,7 +146,7 @@ export const AppComponent = connect( e && e.preventDefault(); const header = document.querySelector('#main-content h1'); if (header) header.focus(); - return false; + return; }; useEffect(() => { diff --git a/web-client/src/views/AppComponentPublic.jsx b/web-client/src/views/AppComponentPublic.jsx index c709458d461..22ef69da456 100644 --- a/web-client/src/views/AppComponentPublic.jsx +++ b/web-client/src/views/AppComponentPublic.jsx @@ -31,7 +31,7 @@ export const AppComponentPublic = connect( e && e.preventDefault(); const header = document.querySelector('#main-content h1'); if (header) header.focus(); - return false; + return; }; useEffect(() => { diff --git a/web-client/src/views/BeforeStartingCase.jsx b/web-client/src/views/BeforeStartingCase.jsx index 6727f8ad671..7decf7f54dc 100644 --- a/web-client/src/views/BeforeStartingCase.jsx +++ b/web-client/src/views/BeforeStartingCase.jsx @@ -1,10 +1,7 @@ +import { Accordion, AccordionItem } from '../ustc-ui/Accordion/Accordion'; import { Button } from '../ustc-ui/Button/Button'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { MAX_FILE_SIZE_MB } from '../../../shared/src/persistence/s3/getUploadPolicy'; import { Mobile, NonMobile } from '../ustc-ui/Responsive/Responsive'; import React from 'react'; -import howToMergePDFs from '../pdfs/how-to-merge-pdfs.pdf'; -import paperclipSlashIcon from '../images/paperclip-no-icon.svg'; export const BeforeStartingCase = () => ( <> @@ -13,8 +10,8 @@ export const BeforeStartingCase = () => (

- File a Petition - Petition Filing Guide + Create a Case + How to Create a Case

@@ -22,187 +19,209 @@ export const BeforeStartingCase = () => (

- Tips for Preparing Documents Before You File + Instructions For Creating a Case

+

+ Before starting the filing process please review the helpful tips + provided below. This will help instruct you in what is needed and how to + go about proceeding with filing your Petition. +

-
-
-
- -
-

- 1. Are you authorized to file on behalf of this taxpayer? -

-
-

- To file a case on behalf of another taxpayer, you must be - authorized to litigate in this Court as provided by the Tax - Court Rules of Practice and Procedure (Rule 60). Enrolled - agents, certified public accountants, and powers of attorney - who are not admitted to practice before the Court are not - eligible to represent taxpayers. -

-
-
-
-
- -
-

- 2. Have the IRS Notice(s) Youʼve Received Available to Submit -

-
-

- If you’ve received an IRS notice, such as a Notice of - Deficiency or Notice of Determination, you’ll need to include - a copy with your Petition. The U.S. Tax Court must receive all - Petitions in a timely manner. The IRS notice shows the last - date to file or the number of days you have to file a - Petition.{' '} - - The Court must receive your electronically filed Petition no - later than 11:59 pm Eastern Time on the last date to file. - -

-
-
-
-
- -
-

- 3. Fill Out The Required Forms -

-
-

Petition Form

-

- Complete the Petition form,{' '} - - USTC Form 2 - - , or you can upload your own Petition that complies with the - requirements of the{' '} - - Tax Court Rules of Practice and Procedure - - . Do not include personal information (such - as Social Security Numbers, Taxpayer Identification Numbers, - or Employer Identification Numbers, birthdates, names of minor - children, or financial account information) in your Petition. -

-

Statement of Taxpayer Identification

-

- Complete the Statement of Taxpayer Identification form,{' '} - - USTC Form 4 - - . This is the only document that should contain your Social + + +

+ You may have received a notice in the mail from the Internal + Revenue Service (IRS). The IRS notice may show the last date to + file or the number of days you have to file a Petition. + + The Court must receive your electronically filed Petition no + later than 11:59 pm Eastern Time on the last date to file. + {' '} + Petitions received after this date are untimely and your case + may be dismissed for lack of jurisdiction. +

+ + + + +

+ You’ll be asked to upload your Statement of Taypayer + Identification Number (STIN)* form in Step 1 of creating a case. + This document is sent to the IRS to help them identify you, but + it’s never stored as public record. +

+

+ If you didn’t already fill out the form, you can download it + now. +

+

+ +
+ + *This is the only document that should contain your Social Security Number (SSN), Taxpayer Identification Number (TIN), - or Employer Identification Number (EIN). This document is sent - to the IRS to help identify you, but it’s never viewed by the - Court or stored as part of the public record. -

-

Ownership Disclosure Statement

-

- If you’re filing for a business, you’ll need to complete and - submit the Ownership Disclosure Statement,{' '} - - USTC Form 6 - - . -

-
-
-
-
-
-
- -
-

- 4. Remove Personal Information From Your Petition and IRS - Notice(s) -

-
-

- If the IRS notice includes personal information (such as + or Employer Identification Number (EIN).{' '} + Do not include your SSN, TIN, or EIN on any + other document you file with the Court. + +

+ + + + +

1. Complete Your Petition

+

+ This is the document that explains why you’re challenging the + IRS’s determination. You can complete the Court’s standard + Petition form or you can upload your own Petition that complies + with the requirements of the Tax Court Rules of Practice and + Procedure. +

+

+ If you didn’t already fill out the form, you can download it + now. +

+

+ +
+ + *Do not include personal information (such as Social Security Numbers, Taxpayer Identification Numbers, or - Employer Identification Numbers), remove or redact that - information before including it with your Petition. You can - remove this information by deleting it, marking through it so - itʼs illegible, or any other method that will prevent it from - being seen. -

-
-
- -
-
- -
-

- 5. Combine Your Petition and IRS Notice(s) Into a Single PDF -

-
-

- Scan your Petition and IRS notice into one Petition PDF or - combine them digitally. This is what youʼll upload to the - Court to start your case. Uploads are limited to{' '} - {MAX_FILE_SIZE_MB}MB.{' '} - - Learn more about how to merge files into one PDF. - -

-
-
-
-
-
- -
-
-

- 6. Donʼt Submit Extra Documents With Your Petition -

-
-

- Do not include any additional documents with + Employer Identification Numbers, birthdates, names of minor + children, or financial account information) in your Petition + or any other filing with the Court. + +

+

+ 2. Create a PDF of your Petition and IRS notice (if you received + one) +

+

+ Scan your Petition and IRS notice into one Petition PDF (max + file size of 250MB) or combine them digitally. + +
+ + *Do not include any additional documents with your Petition, except for the IRS notice. Documents that might be evidence can be submitted at a later time. -

-
-
-
+ +

+ + + + +

Joint Petition With A Spouse

+

+ To file a joint Petition with your spouse, you must have their + consent. Both you and your spouse must sign the Petition form. + If you do not have their consent, select “Myself” as the person + who is filing. +

+

Someone Else

+

+ To file a case on behalf of another taxpayer, you must be + authorized in this Court as provided by the Tax Court Rules of + Practice and Procedure (Rule 60). Enrolled agents, certified + public accountants, and powers of attorney who are not admitted + to practice before the Court are not eligible to represent + taxpayers. +

+

A Business

+

+ If you’re filing for a business, you’ll need to complete and + submit the Ownership Disclosure Statement. +

+

+ If you didn’t already fill out the form, you can download it + now. +

+

+ +

+
+
+

+ Next you’ll continue to follow the steps to upload your documents + and fill in the requested information that will create your case. +

- + diff --git a/web-client/src/views/BlockedCasesReport/BlockedCasesReport.jsx b/web-client/src/views/BlockedCasesReport/BlockedCasesReport.jsx index bdb6e362187..d06eee5bf55 100644 --- a/web-client/src/views/BlockedCasesReport/BlockedCasesReport.jsx +++ b/web-client/src/views/BlockedCasesReport/BlockedCasesReport.jsx @@ -58,7 +58,7 @@ export const BlockedCasesReport = connect(
{item.blockedDateEarliest}{item.caseName}{item.caseTitle} {item.status} {item.blockedReason} diff --git a/web-client/src/views/CaseDeadlines/CaseDeadlines.jsx b/web-client/src/views/CaseDeadlines/CaseDeadlines.jsx index 524a071816c..cfab2162912 100644 --- a/web-client/src/views/CaseDeadlines/CaseDeadlines.jsx +++ b/web-client/src/views/CaseDeadlines/CaseDeadlines.jsx @@ -84,7 +84,7 @@ export const CaseDeadlines = connect( {item.caseCaptionNames}{item.caseTitle} {item.description} {item.associatedJudgeFormatted} diff --git a/web-client/src/views/CaseDetail/AddEditCaseNoteModal.jsx b/web-client/src/views/CaseDetail/AddEditCaseNoteModal.jsx index f55a0369530..82e4d580473 100644 --- a/web-client/src/views/CaseDetail/AddEditCaseNoteModal.jsx +++ b/web-client/src/views/CaseDetail/AddEditCaseNoteModal.jsx @@ -28,7 +28,7 @@ export const AddEditCaseNoteModal = connect( onConfirmSequence={onConfirmSequence} >
- {`Docket ${modal.docketNumber}: ${modal.caseCaptionNames}`} + {`Docket ${modal.docketNumber}: ${modal.caseTitle}`}
(
-
{consolidatedCase.caseName}
+
{consolidatedCase.caseTitle}
))} diff --git a/web-client/src/views/CaseDetail/PaperServiceConfirmModal.jsx b/web-client/src/views/CaseDetail/PaperServiceConfirmModal.jsx index 702317e2835..0a7e5e85788 100644 --- a/web-client/src/views/CaseDetail/PaperServiceConfirmModal.jsx +++ b/web-client/src/views/CaseDetail/PaperServiceConfirmModal.jsx @@ -20,7 +20,7 @@ export const PaperServiceConfirmModal = connect( confirmLabel="Print Now" title="Paper service is required for the following document:" onCancelSequence="clearModalSequence" - onConfirmSequence="navigateToPrintPreviewSequence" + onConfirmSequence="navigateToPrintPaperServiceSequence" >

The following document will be served on all parties:

diff --git a/web-client/src/views/CaseDetail/PetitionerInformation.jsx b/web-client/src/views/CaseDetail/PetitionerInformation.jsx index c2174df2a03..eabb351157b 100644 --- a/web-client/src/views/CaseDetail/PetitionerInformation.jsx +++ b/web-client/src/views/CaseDetail/PetitionerInformation.jsx @@ -118,8 +118,8 @@ const PetitionerInformation = connect( constants, { nameOverride: - caseDetailHelper.showCaseNameForPrimary && - formattedCaseDetail.caseName, + formattedCaseDetail.showCaseTitleForPrimary && + formattedCaseDetail.caseTitle, }, )} diff --git a/web-client/src/views/CaseDetail/SealCaseModal.jsx b/web-client/src/views/CaseDetail/SealCaseModal.jsx index 26916db6a73..418a30cbeef 100644 --- a/web-client/src/views/CaseDetail/SealCaseModal.jsx +++ b/web-client/src/views/CaseDetail/SealCaseModal.jsx @@ -24,7 +24,7 @@ export const SealCaseModal = connect( >
{formattedCaseDetail.docketNumberWithSuffix}{' '} - {formattedCaseDetail.caseName} + {formattedCaseDetail.caseTitle}
); diff --git a/web-client/src/views/CaseDetail/UnconsolidateCasesModal.jsx b/web-client/src/views/CaseDetail/UnconsolidateCasesModal.jsx index a53b0535210..32aa0efba2b 100644 --- a/web-client/src/views/CaseDetail/UnconsolidateCasesModal.jsx +++ b/web-client/src/views/CaseDetail/UnconsolidateCasesModal.jsx @@ -57,7 +57,7 @@ export const UnconsolidateCasesModal = connect(
{consolidatedCase.docketNumberWithSuffix}
- {consolidatedCase.caseName} + {consolidatedCase.caseTitle} ), diff --git a/web-client/src/views/CaseDetailEdit/CaseInfo.jsx b/web-client/src/views/CaseDetailEdit/CaseInfo.jsx index 7bf2b403689..201ec28ccf2 100644 --- a/web-client/src/views/CaseDetailEdit/CaseInfo.jsx +++ b/web-client/src/views/CaseDetailEdit/CaseInfo.jsx @@ -160,10 +160,10 @@ export const CaseInfo = connect(
{ updateFormValueSequence({ @@ -174,7 +174,7 @@ export const CaseInfo = connect( /> diff --git a/web-client/src/views/CaseDetailEdit/IRSNotice.jsx b/web-client/src/views/CaseDetailEdit/IRSNotice.jsx index 68e0e1f0d31..92abbb058bc 100644 --- a/web-client/src/views/CaseDetailEdit/IRSNotice.jsx +++ b/web-client/src/views/CaseDetailEdit/IRSNotice.jsx @@ -27,7 +27,7 @@ export const IRSNotice = connect( return (
- Notice attached to petition? + Notice attached to petition?!
)} diff --git a/web-client/src/views/CaseDetailEdit/ReviewSavedPetition.jsx b/web-client/src/views/CaseDetailEdit/ReviewSavedPetition.jsx index a483665a63e..0a5800fb069 100644 --- a/web-client/src/views/CaseDetailEdit/ReviewSavedPetition.jsx +++ b/web-client/src/views/CaseDetailEdit/ReviewSavedPetition.jsx @@ -6,6 +6,7 @@ import { ConfirmModal } from '../../ustc-ui/Modal/ConfirmModal'; import { FileUploadErrorModal } from '../FileUploadErrorModal'; import { FileUploadStatusModal } from '../FileUploadStatusModal'; import { Focus } from '../../ustc-ui/Focus/Focus'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FormCancelModalDialog } from '../FormCancelModalDialog'; import { OrdersNeededSummary } from '../StartCaseInternal/OrdersNeededSummary'; import { PDFPreviewButton } from '../PDFPreviewButton'; @@ -30,8 +31,6 @@ export const ReviewSavedPetition = connect( documentId: state.documentId, form: state.form, formCancelToggleCancelSequence: sequences.formCancelToggleCancelSequence, - navigateToEditSavedPetitionSequence: - sequences.navigateToEditSavedPetitionSequence, openConfirmServeToIrsModalSequence: sequences.openConfirmServeToIrsModalSequence, reviewSavedPetitionHelper: state.reviewSavedPetitionHelper, @@ -42,10 +41,9 @@ export const ReviewSavedPetition = connect( }, function ReviewSavedPetition({ constants, - documentId, + // documentId, form, formCancelToggleCancelSequence, - navigateToEditSavedPetitionSequence, openConfirmServeToIrsModalSequence, reviewSavedPetitionHelper, saveCaseAndServeToIrsSequence, @@ -53,7 +51,7 @@ export const ReviewSavedPetition = connect( showModal, startCaseHelper, }) { - const { caseId } = form; + // const { caseId } = form; return ( <> @@ -77,7 +75,7 @@ export const ReviewSavedPetition = connect(
-

+

Parties