From 7ab04aa39093c9314ab8eb577a3eb938689f5ddc Mon Sep 17 00:00:00 2001 From: "Jay R. Newlin (PromptWorks)" Date: Fri, 13 Dec 2019 16:59:25 -0500 Subject: [PATCH 001/114] Removed file rendered unnecessary by change in test strategy --- .../New_Portfolio_-_No_optional_fields.html | 179 ------------------ 1 file changed, 179 deletions(-) delete mode 100644 uitests/New_Portfolio_-_No_optional_fields.html diff --git a/uitests/New_Portfolio_-_No_optional_fields.html b/uitests/New_Portfolio_-_No_optional_fields.html deleted file mode 100644 index 269f96df..00000000 --- a/uitests/New_Portfolio_-_No_optional_fields.html +++ /dev/null @@ -1,179 +0,0 @@ - - - - - - -New Portfolio - No optional fields - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
New Portfolio - No optional fields
waitForPageToLoad
open/login-dev
waitForPageToLoad
waitForElementPresentcss=.about-cloud > h1
assertTextcss=.about-cloud > h1About Cloud Services
waitForPageToLoad
waitForElementPresentcss=a[href="/portfolios/new"]
clickcss=a[href="/portfolios/new"]
waitForPageToLoad
waitForElementPresentcss=main.usa-section > h1
assertTextcss=main.usa-section > h1*New Portfolio Form*
waitForPageToLoad
waitForElementPresentcss=#name
typecss=#nameTatooine Energy Maintenance Systems
waitForPageToLoad
waitForElementPresentcss=#defense_component
typecss=#defense_componentDefense Logistics Agency
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
assertTextcss=input[type="submit"]Save
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.portfolio-header__name > h1
assertTextcss=.portfolio-header__name > h1*Tatooine Energy Maintenance Systems*
waitForPageToLoad
waitForElementPresentcss=.empty-state h3
assertTextcss=.empty-state h3*You don't have any Applications yet*
- - \ No newline at end of file From d3bced5b5dbd0d56374a9141aa6f2198b9ef8878 Mon Sep 17 00:00:00 2001 From: Rob Gil Date: Sun, 15 Dec 2019 13:02:52 -0500 Subject: [PATCH 002/114] Adds CODEOWNERS file and configures terraform with an owner for approvals --- .github/CODEOWNERS | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..d38680ce --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +terraform/* @dandds From 3457f51d99595028c2d8f13f57c0d2ecbc835ab6 Mon Sep 17 00:00:00 2001 From: dandds Date: Mon, 16 Dec 2019 10:47:22 -0500 Subject: [PATCH 003/114] CI script should fail hard. Right now, unit test failures in script/cibuild are not being emitted correctly. Instead, we'll just `set -e` at the top of the CI script so that failures are fast and obvious. --- script/cibuild | 1 + 1 file changed, 1 insertion(+) diff --git a/script/cibuild b/script/cibuild index 55bc7857..f0011051 100755 --- a/script/cibuild +++ b/script/cibuild @@ -1,4 +1,5 @@ #!/bin/bash +set -e # script/cibuild: Run CI related checks and tests From 22dd5d7b85105afceceeb0a4566ab7dc83ae79db Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Fri, 13 Dec 2019 14:49:39 -0500 Subject: [PATCH 004/114] Add migration for enforcing uniqueness of an application name within a portfolio and update create/update Applicaiton domain methods. --- .secrets.baseline | 4 +-- ..._add_application_name_and_portfolio_id_.py | 28 +++++++++++++++++++ atst/domain/applications.py | 17 +++++++++-- atst/models/application.py | 7 ++++- tests/domain/test_applications.py | 21 +++++++++++++- tests/domain/test_portfolios.py | 5 ++-- tests/test_access.py | 23 ++++++++------- 7 files changed, 87 insertions(+), 18 deletions(-) create mode 100644 alembic/versions/c487d91f1a26_add_application_name_and_portfolio_id_.py diff --git a/.secrets.baseline b/.secrets.baseline index 05921baa..24361804 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "^.secrets.baseline$|^.*pgsslrootcert.yml$", "lines": null }, - "generated_at": "2019-12-06T21:22:07Z", + "generated_at": "2019-12-13T20:38:57Z", "plugins_used": [ { "base64_limit": 4.5, @@ -170,7 +170,7 @@ "hashed_secret": "e4f14805dfd1e6af030359090c535e149e6b4207", "is_secret": false, "is_verified": false, - "line_number": 656, + "line_number": 659, "type": "Hex High Entropy String" } ] diff --git a/alembic/versions/c487d91f1a26_add_application_name_and_portfolio_id_.py b/alembic/versions/c487d91f1a26_add_application_name_and_portfolio_id_.py new file mode 100644 index 00000000..a0c32c2c --- /dev/null +++ b/alembic/versions/c487d91f1a26_add_application_name_and_portfolio_id_.py @@ -0,0 +1,28 @@ +"""add application name and portfolio_id unique constraint + +Revision ID: c487d91f1a26 +Revises: 3bd8552f1c57 +Create Date: 2019-12-13 14:33:23.952450 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'c487d91f1a26' # pragma: allowlist secret +down_revision = '3bd8552f1c57' # pragma: allowlist secret +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_unique_constraint('name_portfolio_id_unique_constraint', 'applications', ['name', 'portfolio_id']) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_constraint('name_portfolio_id_unique_constraint', 'applications', type_='unique') + # ### end Alembic commands ### diff --git a/atst/domain/applications.py b/atst/domain/applications.py index 21e8782b..39cf7251 100644 --- a/atst/domain/applications.py +++ b/atst/domain/applications.py @@ -1,4 +1,7 @@ +from sqlalchemy.exc import IntegrityError + from . import BaseDomainClass +from .exceptions import AlreadyExistsError from flask import g from atst.database import db from atst.domain.application_roles import ApplicationRoles @@ -28,7 +31,12 @@ class Applications(BaseDomainClass): if environment_names: Environments.create_many(user, application, environment_names) - db.session.commit() + try: + db.session.commit() + except IntegrityError: + db.session.rollback() + raise AlreadyExistsError("application") + return application @classmethod @@ -54,7 +62,12 @@ class Applications(BaseDomainClass): g.current_user, application, new_data["environment_names"] ) db.session.add(application) - db.session.commit() + + try: + db.session.commit() + except IntegrityError: + db.session.rollback() + raise AlreadyExistsError("application") return application diff --git a/atst/models/application.py b/atst/models/application.py index b6cff6bd..415e5694 100644 --- a/atst/models/application.py +++ b/atst/models/application.py @@ -1,4 +1,4 @@ -from sqlalchemy import and_, Column, ForeignKey, String +from sqlalchemy import and_, Column, ForeignKey, String, UniqueConstraint from sqlalchemy.orm import relationship, synonym from atst.models.base import Base @@ -34,6 +34,11 @@ class Application( ), ) members = synonym("roles") + __table_args__ = ( + UniqueConstraint( + "name", "portfolio_id", name="name_portfolio_id_unique_constraint" + ), + ) @property def users(self): diff --git a/tests/domain/test_applications.py b/tests/domain/test_applications.py index 66f4ee01..50ae8038 100644 --- a/tests/domain/test_applications.py +++ b/tests/domain/test_applications.py @@ -5,7 +5,7 @@ from atst.models import CSPRole, ApplicationRoleStatus from atst.domain.application_roles import ApplicationRoles from atst.domain.applications import Applications from atst.domain.environment_roles import EnvironmentRoles -from atst.domain.exceptions import NotFoundError +from atst.domain.exceptions import AlreadyExistsError, NotFoundError from atst.domain.permission_sets import PermissionSets from tests.factories import ( @@ -177,3 +177,22 @@ def test_invite_to_nonexistent_environment(): {"environment_id": uuid4(), "role": CSPRole.BASIC_ACCESS.value}, ], ) + + +def test_create_does_not_duplicate_names_within_portfolio(): + portfolio = PortfolioFactory.create() + name = "An Awesome Application" + + assert Applications.create(portfolio.owner, portfolio, name, "") + with pytest.raises(AlreadyExistsError): + Applications.create(portfolio.owner, portfolio, name, "") + + +def test_update_does_not_duplicate_names_within_portfolio(): + portfolio = PortfolioFactory.create() + name = "An Awesome Application" + application = ApplicationFactory.create(portfolio=portfolio, name=name) + dupe_application = ApplicationFactory.create(portfolio=portfolio) + + with pytest.raises(AlreadyExistsError): + Applications.update(dupe_application, {"name": name}) diff --git a/tests/domain/test_portfolios.py b/tests/domain/test_portfolios.py index 41e3fc81..0390f69f 100644 --- a/tests/domain/test_portfolios.py +++ b/tests/domain/test_portfolios.py @@ -1,4 +1,5 @@ import pytest +import random from uuid import uuid4 from atst.domain.exceptions import NotFoundError, UnauthorizedError @@ -97,7 +98,7 @@ def test_scoped_portfolio_returns_all_applications_for_portfolio_admin( Applications.create( portfolio.owner, portfolio, - "My Application", + "My Application %s" % (random.randrange(1, 1000)), "My application", ["dev", "staging", "prod"], ) @@ -120,7 +121,7 @@ def test_scoped_portfolio_returns_all_applications_for_portfolio_owner( Applications.create( portfolio.owner, portfolio, - "My Application", + "My Application %s" % (random.randrange(1, 1000)), "My application", ["dev", "staging", "prod"], ) diff --git a/tests/test_access.py b/tests/test_access.py index 19aaf749..ad4bd5be 100644 --- a/tests/test_access.py +++ b/tests/test_access.py @@ -1,6 +1,7 @@ from unittest.mock import Mock import pytest +import random from flask import url_for, Response @@ -264,26 +265,28 @@ def test_applications_post_application_step_1(post_url_assert_status): rando = user_with() portfolio = PortfolioFactory.create(owner=owner) application = ApplicationFactory.create(portfolio=portfolio) - step_1_form_data = { - "name": "Test Application", - "description": "This is only a test", - } + + def _form_data(): + return { + "name": "Test Application %s" % (random.randrange(1, 1000)), + "description": "This is only a test", + } url = url_for( "applications.create_new_application_step_1", portfolio_id=portfolio.id ) - post_url_assert_status(ccpo, url, 302, data=step_1_form_data) - post_url_assert_status(owner, url, 302, data=step_1_form_data) - post_url_assert_status(rando, url, 404, data=step_1_form_data) + post_url_assert_status(ccpo, url, 302, data=_form_data()) + post_url_assert_status(owner, url, 302, data=_form_data()) + post_url_assert_status(rando, url, 404, data=_form_data()) url = url_for( "applications.update_new_application_step_1", portfolio_id=portfolio.id, application_id=application.id, ) - post_url_assert_status(ccpo, url, 302, data=step_1_form_data) - post_url_assert_status(owner, url, 302, data=step_1_form_data) - post_url_assert_status(rando, url, 404, data=step_1_form_data) + post_url_assert_status(ccpo, url, 302, data=_form_data()) + post_url_assert_status(owner, url, 302, data=_form_data()) + post_url_assert_status(rando, url, 404, data=_form_data()) # applications.view_new_application_step_2 From ffbf6122903db0ee6e3a47db136b8b1be57c129e Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Fri, 13 Dec 2019 16:08:22 -0500 Subject: [PATCH 005/114] Update route to catch error when app name uniqueness is violated and display a error message --- atst/routes/applications/new.py | 38 ++++++++++++++++++++------- atst/utils/flash.py | 5 ++++ tests/routes/applications/test_new.py | 18 +++++++++++++ translations.yaml | 2 ++ 4 files changed, 53 insertions(+), 10 deletions(-) diff --git a/atst/routes/applications/new.py b/atst/routes/applications/new.py index a1a1a54c..e9238775 100644 --- a/atst/routes/applications/new.py +++ b/atst/routes/applications/new.py @@ -2,6 +2,7 @@ from flask import redirect, render_template, request as http_request, url_for, g from .blueprint import applications_bp from atst.domain.applications import Applications +from atst.domain.exceptions import AlreadyExistsError from atst.domain.portfolios import Portfolios from atst.forms.application import NameAndDescriptionForm, EnvironmentsForm from atst.domain.authz.decorator import user_can_access_decorator as user_can @@ -37,6 +38,31 @@ def render_new_application_form( return render_template(template, **render_args) +def update_application(form, application_id=None, portfolio_id=None): + if form.validate(): + application = None + try: + if application_id: + application = Applications.get(application_id) + application = Applications.update(application, form.data) + flash("application_updated", application_name=application.name) + else: + portfolio = Portfolios.get_for_update(portfolio_id) + application = Applications.create( + g.current_user, portfolio, **form.data + ) + flash("application_created", application_name=application.name) + + return application + + except AlreadyExistsError: + flash("application_name_error", name=form.data["name"]) + return False + + else: + return False + + @applications_bp.route("/portfolios//applications/new") @applications_bp.route("/applications//new/step_1") @user_can(Permissions.CREATE_APPLICATION, message="view create new application form") @@ -64,17 +90,9 @@ def create_or_update_new_application_step_1(portfolio_id=None, application_id=No form = get_new_application_form( {**http_request.form}, NameAndDescriptionForm, application_id ) + application = update_application(form, application_id, portfolio_id) - if form.validate(): - application = None - if application_id: - application = Applications.get(application_id) - application = Applications.update(application, form.data) - flash("application_updated", application_name=application.name) - else: - portfolio = Portfolios.get_for_update(portfolio_id) - application = Applications.create(g.current_user, portfolio, **form.data) - flash("application_created", application_name=application.name) + if application: return redirect( url_for( "applications.update_new_application_step_2", diff --git a/atst/utils/flash.py b/atst/utils/flash.py index fabba4d2..0de143bb 100644 --- a/atst/utils/flash.py +++ b/atst/utils/flash.py @@ -64,6 +64,11 @@ MESSAGES = { "message_template": "You have successfully updated the permissions for {{ user_name }}", "category": "success", }, + "application_name_error": { + "title_template": "", + "message_template": """{{ 'flash.application.name_error.message' | translate({ 'name': name }) }}""", + "category": "error", + }, "ccpo_user_added": { "title_template": translate("flash.success"), "message_template": "You have successfully given {{ user_name }} CCPO permissions.", diff --git a/tests/routes/applications/test_new.py b/tests/routes/applications/test_new.py index c4fb83ed..045ac19e 100644 --- a/tests/routes/applications/test_new.py +++ b/tests/routes/applications/test_new.py @@ -70,6 +70,24 @@ def test_post_name_and_description_for_update(client, session, user_session): assert application.description == "This is only a test" +def test_post_name_and_description_enforces_unique_name(client, user_session, session): + portfolio = PortfolioFactory.create() + name = "Test Application" + application = ApplicationFactory.create(portfolio=portfolio, name=name) + user_session(portfolio.owner) + + session.begin_nested() + response = client.post( + url_for( + "applications.create_new_application_step_1", portfolio_id=portfolio.id + ), + data={"name": name, "description": "This is only a test"}, + ) + session.rollback() + + assert response.status_code == 400 + + def test_get_environments(client, user_session): application = ApplicationFactory.create() user_session(application.portfolio.owner) diff --git a/translations.yaml b/translations.yaml index 1d876e97..6a678f48 100644 --- a/translations.yaml +++ b/translations.yaml @@ -114,6 +114,8 @@ flash: message: '{application_name} has been successfully created. You may continue on to provision environments and assign team members now, or come back and complete these tasks at a later time.' updated: 'You have successfully updated the {application_name} application.' deleted: 'You have successfully deleted the {application_name} application. To view the retained activity log, visit the portfolio administration page.' + name_error: + message: 'The application name {name} has already been used in this portfolio. Please enter a unique name.' delete_member_success: 'You have successfully deleted {member_name} from the portfolio.' deleted_member: Portfolio member deleted environment_added: 'The environment "{env_name}" has been added to the application.' From afad5362a1e74bc1985c6d6912ecfe0961e2c962 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Mon, 16 Dec 2019 10:21:45 -0500 Subject: [PATCH 006/114] Update name of UniqueContraint to include the table name --- .../c487d91f1a26_add_application_name_and_portfolio_id_.py | 4 ++-- atst/models/application.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/alembic/versions/c487d91f1a26_add_application_name_and_portfolio_id_.py b/alembic/versions/c487d91f1a26_add_application_name_and_portfolio_id_.py index a0c32c2c..f3cdc433 100644 --- a/alembic/versions/c487d91f1a26_add_application_name_and_portfolio_id_.py +++ b/alembic/versions/c487d91f1a26_add_application_name_and_portfolio_id_.py @@ -18,11 +18,11 @@ depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.create_unique_constraint('name_portfolio_id_unique_constraint', 'applications', ['name', 'portfolio_id']) + op.create_unique_constraint('applications_name_portfolio_id_key', 'applications', ['name', 'portfolio_id']) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.drop_constraint('name_portfolio_id_unique_constraint', 'applications', type_='unique') + op.drop_constraint('applications_name_portfolio_id_key', 'applications', type_='unique') # ### end Alembic commands ### diff --git a/atst/models/application.py b/atst/models/application.py index 415e5694..a7bdadba 100644 --- a/atst/models/application.py +++ b/atst/models/application.py @@ -36,7 +36,7 @@ class Application( members = synonym("roles") __table_args__ = ( UniqueConstraint( - "name", "portfolio_id", name="name_portfolio_id_unique_constraint" + "name", "portfolio_id", name="applications_name_portfolio_id_key" ), ) From b927ef1b0ec06d9f9a58a1a6cd436b3bf504c9be Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Mon, 16 Dec 2019 10:39:47 -0500 Subject: [PATCH 007/114] Create utility function for the pattern of committing to the database or raising AlreadyExistsError --- atst/domain/applications.py | 21 ++++----------------- atst/domain/task_orders.py | 19 +++---------------- atst/utils/__init__.py | 13 +++++++++++++ 3 files changed, 20 insertions(+), 33 deletions(-) diff --git a/atst/domain/applications.py b/atst/domain/applications.py index 39cf7251..c2321194 100644 --- a/atst/domain/applications.py +++ b/atst/domain/applications.py @@ -1,7 +1,4 @@ -from sqlalchemy.exc import IntegrityError - from . import BaseDomainClass -from .exceptions import AlreadyExistsError from flask import g from atst.database import db from atst.domain.application_roles import ApplicationRoles @@ -14,7 +11,7 @@ from atst.models import ( ApplicationRoleStatus, EnvironmentRole, ) -from atst.utils import first_or_none +from atst.utils import first_or_none, update_or_raise_already_exists_error class Applications(BaseDomainClass): @@ -31,12 +28,7 @@ class Applications(BaseDomainClass): if environment_names: Environments.create_many(user, application, environment_names) - try: - db.session.commit() - except IntegrityError: - db.session.rollback() - raise AlreadyExistsError("application") - + update_or_raise_already_exists_error(message="application") return application @classmethod @@ -61,14 +53,9 @@ class Applications(BaseDomainClass): Environments.create_many( g.current_user, application, new_data["environment_names"] ) + db.session.add(application) - - try: - db.session.commit() - except IntegrityError: - db.session.rollback() - raise AlreadyExistsError("application") - + update_or_raise_already_exists_error(message="application") return application @classmethod diff --git a/atst/domain/task_orders.py b/atst/domain/task_orders.py index 835590c9..8ad8b0f4 100644 --- a/atst/domain/task_orders.py +++ b/atst/domain/task_orders.py @@ -1,11 +1,10 @@ import datetime -from sqlalchemy.exc import IntegrityError from atst.database import db from atst.models.clin import CLIN from atst.models.task_order import TaskOrder, SORT_ORDERING from . import BaseDomainClass -from .exceptions import AlreadyExistsError +from atst.utils import update_or_raise_already_exists_error class TaskOrders(BaseDomainClass): @@ -16,15 +15,8 @@ class TaskOrders(BaseDomainClass): def create(cls, portfolio_id, number, clins, pdf): task_order = TaskOrder(portfolio_id=portfolio_id, number=number, pdf=pdf) db.session.add(task_order) - - try: - db.session.commit() - except IntegrityError: - db.session.rollback() - raise AlreadyExistsError("task_order") - + update_or_raise_already_exists_error(message="task_order") TaskOrders.create_clins(task_order.id, clins) - return task_order @classmethod @@ -42,12 +34,7 @@ class TaskOrders(BaseDomainClass): task_order.number = number db.session.add(task_order) - try: - db.session.commit() - except IntegrityError: - db.session.rollback() - raise AlreadyExistsError("task_order") - + update_or_raise_already_exists_error(message="task_order") return task_order @classmethod diff --git a/atst/utils/__init__.py b/atst/utils/__init__.py index 01988e10..9772af67 100644 --- a/atst/utils/__init__.py +++ b/atst/utils/__init__.py @@ -1,5 +1,10 @@ import re +from sqlalchemy.exc import IntegrityError + +from atst.database import db +from atst.domain.exceptions import AlreadyExistsError + def first_or_none(predicate, lst): return next((x for x in lst if predicate(x)), None) @@ -23,3 +28,11 @@ def camel_to_snake(camel_cased): def pick(keys, dct): _keys = set(keys) return {k: v for (k, v) in dct.items() if k in _keys} + + +def update_or_raise_already_exists_error(message): + try: + db.session.commit() + except IntegrityError: + db.session.rollback() + raise AlreadyExistsError(message) From 5f267e9cfaf7d9858da82518d71254b9e4972516 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Mon, 16 Dec 2019 14:40:17 -0500 Subject: [PATCH 008/114] Remove unused import --- .../c487d91f1a26_add_application_name_and_portfolio_id_.py | 1 - 1 file changed, 1 deletion(-) diff --git a/alembic/versions/c487d91f1a26_add_application_name_and_portfolio_id_.py b/alembic/versions/c487d91f1a26_add_application_name_and_portfolio_id_.py index f3cdc433..b70b4fde 100644 --- a/alembic/versions/c487d91f1a26_add_application_name_and_portfolio_id_.py +++ b/alembic/versions/c487d91f1a26_add_application_name_and_portfolio_id_.py @@ -6,7 +6,6 @@ Create Date: 2019-12-13 14:33:23.952450 """ from alembic import op -import sqlalchemy as sa # revision identifiers, used by Alembic. From 2f10900df1b64a231d0ac3485666eb30e348a9ed Mon Sep 17 00:00:00 2001 From: "Jay R. Newlin (PromptWorks)" Date: Mon, 16 Dec 2019 16:28:57 -0500 Subject: [PATCH 009/114] Renamed test --- uitests/Report_Basics.html | 1333 ------------------------------------ 1 file changed, 1333 deletions(-) delete mode 100644 uitests/Report_Basics.html diff --git a/uitests/Report_Basics.html b/uitests/Report_Basics.html deleted file mode 100644 index 129b17e9..00000000 --- a/uitests/Report_Basics.html +++ /dev/null @@ -1,1333 +0,0 @@ - - - - - - -Report Basics - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Report Basics
waitForPageToLoad
open/login-dev
waitForPageToLoad
waitForElementPresentcss=.about-cloud > h1
assertTextcss=.about-cloud > h1About Cloud Services
waitForPageToLoad
waitForElementPresentcss=a[href="/portfolios/new"]
clickcss=a[href="/portfolios/new"]
waitForPageToLoad
waitForElementPresentcss=main.usa-section > h1
assertTextcss=main.usa-section > h1*New Portfolio Form*
waitForPageToLoad
waitForElementPresentcss=#name
typecss=#nameTatooine Energy Maintenance Systems
waitForPageToLoad
waitForElementPresentcss=#defense_component
typecss=#defense_componentDefense Logistics Agency
waitForPageToLoad
waitForElementPresentcss=#description
typecss=#descriptionMaintenance and monitoring of the energy grid
waitForPageToLoad
waitForElementPresentcss=#app_migration > li:nth-of-type(3) > label
clickcss=#app_migration > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#native_apps > li:nth-of-type(1) > label
clickcss=#native_apps > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#team_experience > li:nth-of-type(5) > label
clickcss=#team_experience > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
assertTextcss=input[type="submit"]Save
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.portfolio-header__name > h1
assertTextcss=.portfolio-header__name > h1*Tatooine Energy Maintenance Systems*
waitForPageToLoad
waitForElementPresentcss=.empty-state h3
assertTextcss=.empty-state h3*You don't have any Applications yet*
waitForPageToLoad
waitForElementPresentcss=.icon--funding
clickcss=.icon--funding
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text h3
assertTextcss=.sticky-cta-text h3*Task Orders*
waitForPageToLoad
waitForElementPresentcss=.usa-button.usa-button-primary
clickcss=.usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Add Task Order (step 1 of 5)*
waitForPageToLoad
waitForElementPresentcss=.upload-button
clickcss=.upload-button
waitForPageToLoad
waitForElementPresentcss=#pdf
typecss=#pdfhttps://ghostinspector-prod.s3.amazonaws.com/uploads/726e1c95-2d16-4793-85d8-b4d3ae9cd35d.pdf
waitForPageToLoad
assertElementNotPresentcss=input[type="submit"][disabled="disabled"]
waitForPageToLoad
waitForElementPresentcss=a[href="#"].uploaded-file__remove
assertTextcss=a[href="#"].uploaded-file__remove*Remove*
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Add Task Order (step 2 of 5)*
waitForPageToLoad
waitForElementPresentcss=#number
typecss=#number${timestamp}
waitForPageToLoad
waitForElementPresentcss=svg.svg-inline--fa.fa-check-circle > path
assertElementPresentcss=svg.svg-inline--fa.fa-check-circle > path
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Add Task Order (step 3 of 5)*
waitForPageToLoad
waitForElementPresentcss=#clins-0-number
typecss=#clins-0-number0002
waitForPageToLoad
waitForElementPresentcss=.card__title > .h4
assertTextcss=.card__title > .h4*CLIN 0002*
waitForPageToLoad
waitForElementPresentcss=#clins-0-jedi_clin_type
typecss=#clins-0-jedi_clin_typeJEDI_CLIN_2
waitForPageToLoad
waitForElementPresentcss=#percent-obligated
assertTextcss=#percent-obligated*0%*
waitForPageToLoad
waitForElementPresentcss=#clins-0-total_amount
typecss=#clins-0-total_amount$800,000
waitForPageToLoad
waitForElementPresentcss=#clins-0-obligated_amount
typecss=#clins-0-obligated_amount$100,000
waitForPageToLoad
waitForElementPresentcss=#percent-obligated
assertTextcss=#percent-obligated*13%*
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
clickcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]10
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]01
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]2019
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]06
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]30
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]2020
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
clickcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > div:nth-of-type(4) > .usa-form-group-date-ok > .icon.icon--ok.icon--green > svg.svg-inline--fa.fa-check-circle.fa-w-16
assertElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > div:nth-of-type(4) > .usa-form-group-date-ok > .icon.icon--ok.icon--green > svg.svg-inline--fa.fa-check-circle.fa-w-16
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Add Task Order (step 4 of 5)*
waitForPageToLoad
waitForElementPresentcss=.totals-box > .h3:nth-of-type(2)
assertTextcss=.totals-box > .h3:nth-of-type(2)*$100,000.00*
waitForPageToLoad
waitForElementPresentcss=.totals-box > .h3:nth-of-type(4)
assertTextcss=.totals-box > .h3:nth-of-type(4)*$800,000.00*
waitForPageToLoad
waitForElementPresentcss=.col.task-order__details > div:nth-of-type(2)
assertElementPresentcss=.col.task-order__details > div:nth-of-type(2)
waitForPageToLoad
waitForElementPresentcss=table.fixed-table-wrapper > thead > tr > th.task-order__amount:nth-of-type(6)
assertTextcss=table.fixed-table-wrapper > thead > tr > th.task-order__amount:nth-of-type(6)*Amount Obligated*
waitForPageToLoad
waitForElementPresentcss=a.usa-button.usa-button-primary
clickcss=a.usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=.h2
assertTextcss=.h2*Confirm Signature*
waitForPageToLoad
waitForElementPresentcss=fieldset.usa-input__choices > legend > label
clickcss=fieldset.usa-input__choices > legend > label
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=h3.usa-alert-heading
assertTextcss=h3.usa-alert-heading*Your Task Order has been uploaded successfully.*
waitForPageToLoad
waitForElementPresentcss=.usa-alert-text
assertTextcss=.usa-alert-text*Your task order form for Tatooine Energy Maintenance Systems has been submitted.*
waitForPageToLoad
waitForElementPresentcss=.portfolio-funding
assertElementPresentcss=.portfolio-funding
waitForPageToLoad
waitForElementPresentcss=.action-group
assertElementPresentcss=.action-group
waitForPageToLoad
waitForElementPresentcss=.icon.icon--chart-pie > svg
clickcss=.icon.icon--chart-pie > svg
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Reports*
waitForPageToLoad
waitForElementPresentcss=.row > .col.col--grow.reporting-summary-item:nth-of-type(1) > .reporting-summary-item__value
assertTextcss=.row > .col.col--grow.reporting-summary-item:nth-of-type(1) > .reporting-summary-item__value*$100,000.00*
waitForPageToLoad
waitForElementPresentcss=.row > .col.col--grow.reporting-summary-item:nth-of-type(2) > .reporting-summary-item__value
assertTextcss=.row > .col.col--grow.reporting-summary-item:nth-of-type(2) > .reporting-summary-item__value*October 01, 2019 - - - June 30, 2020*
waitForPageToLoad
waitForElementPresentcss=.row > .col.col--grow.reporting-summary-item:nth-of-type(3) > h5.reporting-summary-item__header > .reporting-summary-item__header-text
assertTextcss=.row > .col.col--grow.reporting-summary-item:nth-of-type(3) > h5.reporting-summary-item__header > .reporting-summary-item__header-text*Days Remaining*
- - \ No newline at end of file From dbe24fdf91db622fdfb8edbc9e7a09555cc82e7e Mon Sep 17 00:00:00 2001 From: Rob Gil Date: Mon, 16 Dec 2019 10:46:47 -0500 Subject: [PATCH 010/114] 169163334 - Adds initial terraform documentation --- terraform/README.md | 84 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 terraform/README.md diff --git a/terraform/README.md b/terraform/README.md new file mode 100644 index 00000000..1f40fadc --- /dev/null +++ b/terraform/README.md @@ -0,0 +1,84 @@ +# ATAT Terraform +Welcome! You've found the ATAT IaC configurations. + +ATAT is configured using terraform and a wrapper script called `secrets-tool`. With `terraform` we can configure infrastructure in a programatic way and ensure consistency across environments. + +## Directory Structure + +**modules/** - Terraform modules. These are modules that can be re-used for multiple environments. + +**providers/** - Specific environment configurations. (dev,production, etc) + +# Setup +Install the following requirements. + +I highly recommend [tfenv](https://github.com/tfutils/tfenv) which will help you manage versions of TF and install new ones as needed. It gives you the ability to switch back and forth between versions as necessary, especially when doing upgrades and managing multiple environments. Think of it like `pyenv`. + +Python is required for the `secrets-tool`. It is used to wrap terraform and pass secrets in to terraform from Azure KeyVault. This approach avoids leaving secrets on the filesystem in any way and allow for restricting access to secrets to specific operators. + +Azure CLI is necessary for creating some intial resources, but is also used by the Python Azure SDK to make calls in some cases. + +Requirements: +- [tfenv](https://github.com/tfutils/tfenv) +- Python 3.7 +- Python pip +- Python virtualenv # FIXME: Switch to `pipenv` +- [azure cli](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest) + +# tfenv +`tfenv` will allow you to install TF versions. For example. + +``` +tfenv install 0.12.18 +``` +_0.12.18 at time of writing_ + + +To select a version to use +``` +tfenv use 0.12.18 +``` + +# Running Terraform +First, you'll need to log in to Azure. With the Azure CLI installed, you can run the following. + +``` +az login +``` + +Next, you'll need to initialize the environment. This process pulls down the terraform provider module from github as well as pulls in the modules that will be used by this provider/environment setup. + +``` +cd providers/dev/ +terraform init +``` + +Once initialized, you can run a plan. A `plan` compares the terraform definitions you have configured in the provider directory (Ex. `providers/dev`) with what is in the shared state file in the Azure Object Storage (which all providers are currently configured for). This then also compares it to the state of the services which are running in Azure. + +If nothing has been applied, you'll see all the resources defined in terraform as all new with a `+` next to the resource name. If the resource exists, but has changed, you'll see a `~` next to the resource and the delta of the change to be applied. + +If you're plan looks good, you can run the apply. +``` +terraform apply +``` + +Check the output for errors. Sometimes the syntax is valid, but some of the configuration may be wrong and only rejected by the Azure API at run time. If this is the case, fix your mistake, and re-run. + +# Shutting down and environment +To shutdown and remove an environment completely as to not incur any costs you would need to run a `terraform destroy`. + +``` +terraform destroy +``` + +**This will destroy all resources defined in the provider so use with caution!! This will include things like KeyVault, Postgres, and so on. You may lose data!!** + +# Advanced Terraform +## Targeted Apply +Sometimes you're writing a new module and don't want to make changes to anything else. In this case you can limit what TF changes. + +``` +terraform plan -target=module.vpc +``` + +In the above example, this will only run a plan (plan/apply/destroy) on the specific module. This can be a module, or resource. You can get a list of module and resources by running `terraform show`. From 9d282ee82aa65762d393c2c45c9fc6b2744099f1 Mon Sep 17 00:00:00 2001 From: dandds Date: Thu, 12 Dec 2019 11:27:41 -0500 Subject: [PATCH 011/114] K8s cronjob for resetting the database on staging. This K8s CronJob will run the script for resetting the database. It will only be applied to the staging site. --- Dockerfile | 3 +- deploy/overlays/staging/kustomization.yaml | 1 + deploy/overlays/staging/reset-cron-job.yml | 46 ++++++++++++++++++++++ 3 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 deploy/overlays/staging/reset-cron-job.yml diff --git a/Dockerfile b/Dockerfile index 744c9739..1785b5d8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -84,8 +84,7 @@ COPY --from=builder /install/celery_worker.py ./celery_worker.py COPY --from=builder /install/config/ ./config/ COPY --from=builder /install/templates/ ./templates/ COPY --from=builder /install/translations.yaml . -COPY --from=builder /install/script/seed_roles.py ./script/seed_roles.py -COPY --from=builder /install/script/sync-crls ./script/sync-crls +COPY --from=builder /install/script/ ./script/ COPY --from=builder /install/static/ ./static/ COPY --from=builder /install/fixtures/ ./fixtures COPY --from=builder /install/uwsgi.ini . diff --git a/deploy/overlays/staging/kustomization.yaml b/deploy/overlays/staging/kustomization.yaml index 38251002..ee6f3a0c 100644 --- a/deploy/overlays/staging/kustomization.yaml +++ b/deploy/overlays/staging/kustomization.yaml @@ -3,6 +3,7 @@ bases: - ../../azure/ resources: - namespace.yml + - reset-cron-job.yml patchesStrategicMerge: - replica_count.yml - ports.yml diff --git a/deploy/overlays/staging/reset-cron-job.yml b/deploy/overlays/staging/reset-cron-job.yml new file mode 100644 index 00000000..b4792e5d --- /dev/null +++ b/deploy/overlays/staging/reset-cron-job.yml @@ -0,0 +1,46 @@ +apiVersion: batch/v1beta1 +kind: CronJob +metadata: + name: reset-db + namespace: atat +spec: + schedule: "0 4 * * *" + concurrencyPolicy: Replace + successfulJobsHistoryLimit: 1 + jobTemplate: + spec: + template: + metadata: + labels: + app: atst + role: reset-db + aadpodidbinding: atat-kv-id-binding + spec: + restartPolicy: OnFailure + containers: + - name: reset + image: $CONTAINER_IMAGE + command: [ + "/bin/sh", "-c" + ] + args: [ + "/opt/atat/atst/.venv/bin/python", + "/opt/atat/atst/script/reset_database.py" + ] + envFrom: + - configMapRef: + name: atst-worker-envvars + volumeMounts: + - name: flask-secret + mountPath: "/config" + volumes: + - name: flask-secret + flexVolume: + driver: "azure/kv" + options: + usepodidentity: "true" + keyvaultname: "atat-vault-test" + keyvaultobjectnames: "staging-AZURE-STORAGE-KEY;staging-MAIL-PASSWORD;staging-PGPASSWORD;staging-REDIS-PASSWORD;staging-SECRET-KEY" + keyvaultobjectaliases: "AZURE_STORAGE_KEY;MAIL_PASSWORD;PGPASSWORD;REDIS_PASSWORD;SECRET_KEY" + keyvaultobjecttypes: "secret;secret;secret;secret;key" + tenantid: $TENANT_ID From 5c32879efb714d5005c8bc39e014d81abce3af31 Mon Sep 17 00:00:00 2001 From: "Jay R. Newlin (PromptWorks)" Date: Tue, 17 Dec 2019 14:16:20 -0500 Subject: [PATCH 012/114] Superseded by "Create New Application" --- uitests/Application_Settings.html | 1123 ----------------------------- 1 file changed, 1123 deletions(-) delete mode 100644 uitests/Application_Settings.html diff --git a/uitests/Application_Settings.html b/uitests/Application_Settings.html deleted file mode 100644 index 76557d2d..00000000 --- a/uitests/Application_Settings.html +++ /dev/null @@ -1,1123 +0,0 @@ - - - - - - -Application Settings - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Application Settings
waitForPageToLoad
open/login-dev?username=brandon
waitForPageToLoad
waitForElementPresentcss=a[href="/user"] > .topbar__link-label
assertTextcss=a[href="/user"] > .topbar__link-label*Brandon Buchannan*
waitForPageToLoad
waitForElementPresentcss=a[href="/logout"] > .topbar__link-label
clickcss=a[href="/logout"] > .topbar__link-label
waitForPageToLoad
waitForElementPresentcss=.col > .usa-alert.usa-alert-info:nth-of-type(2) > .usa-alert-body > h3.usa-alert-heading
assertTextcss=.col > .usa-alert.usa-alert-info:nth-of-type(2) > .usa-alert-body > h3.usa-alert-heading*Logged out*
waitForPageToLoad
open/login-dev
waitForPageToLoad
waitForElementPresentcss=.about-cloud > h1
assertTextcss=.about-cloud > h1About Cloud Services
waitForPageToLoad
waitForElementPresentcss=a[href="/portfolios/new"]
clickcss=a[href="/portfolios/new"]
waitForPageToLoad
waitForElementPresentcss=main.usa-section > h1
assertTextcss=main.usa-section > h1*New Portfolio Form*
waitForPageToLoad
waitForElementPresentcss=#name
typecss=#nameTatooine Energy Maintenance Systems
waitForPageToLoad
waitForElementPresentcss=#defense_component
typecss=#defense_componentDefense Logistics Agency
waitForPageToLoad
waitForElementPresentcss=#description
typecss=#descriptionMaintenance and monitoring of the energy grid
waitForPageToLoad
waitForElementPresentcss=#app_migration > li:nth-of-type(3) > label
clickcss=#app_migration > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#native_apps > li:nth-of-type(1) > label
clickcss=#native_apps > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#team_experience > li:nth-of-type(5) > label
clickcss=#team_experience > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
assertTextcss=input[type="submit"]Save
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.portfolio-header__name > h1
assertTextcss=.portfolio-header__name > h1*Tatooine Energy Maintenance Systems*
waitForPageToLoad
waitForElementPresentcss=.empty-state h3
assertTextcss=.empty-state h3*You don't have any Applications yet*
waitForPageToLoad
waitForElementPresentcss=a.usa-button.usa-button-primary
clickcss=a.usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Name and Describe New Application*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-context
assertTextcss=.sticky-cta-context*Step 1 of 3*
waitForPageToLoad
waitForElementPresentcss=#name
typecss=#nameStarter Application
waitForPageToLoad
waitForElementPresentcss=#description
typecss=#descriptionAny basic application
waitForPageToLoad
waitForElementPresentcss=button[type="submit"]
clickcss=button[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Add Environments to Starter Application*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-context
assertTextcss=.sticky-cta-context*Step 2 of 3*
waitForPageToLoad
waitForElementPresentcss=h3.usa-alert-heading
assertTextcss=h3.usa-alert-heading*Application Saved*
waitForPageToLoad
waitForElementPresentcss=button[type="submit"]
clickcss=button[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Add Members to Starter Application*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-context
assertTextcss=.sticky-cta-context*Step 3 of 3*
waitForPageToLoad
waitForElementPresentcss=h3.usa-alert-heading
assertTextcss=h3.usa-alert-heading*Application environments updated*
waitForPageToLoad
waitForElementPresentcss=.empty-state__message
assertTextcss=.empty-state__message*This Application has no members*
waitForPageToLoad
waitForElementPresentcss=a.usa-button.usa-button-secondary.add-new-button
clickcss=a.usa-button.usa-button-secondary.add-new-button
waitForPageToLoad
waitForElementPresentcss=#add-app-mem > div > div:nth-of-type(1) > h1
assertElementPresentcss=#add-app-mem > div > div:nth-of-type(1) > h1
waitForPageToLoad
waitForElementPresentcss=#user_data-first_name
typecss=#user_data-first_nameBrandon
waitForPageToLoad
waitForElementPresentcss=#user_data-last_name
typecss=#user_data-last_nameBuchannan
waitForPageToLoad
waitForElementPresentcss=#user_data-email
typecss=#user_data-emailbrandon@example.com
waitForPageToLoad
waitForElementPresentcss=#user_data-phone_number
typecss=#user_data-phone_number(206) 555-2342
waitForPageToLoad
waitForElementPresentcss=#user_data-dod_id
typecss=#user_data-dod_id3456789012
waitForPageToLoad
waitForElementPresentcss=#add-app-mem > div > div:nth-of-type(1) > .action-group > input[type="button"].action-group__action.usa-button
clickcss=#add-app-mem > div > div:nth-of-type(1) > .action-group > input[type="button"].action-group__action.usa-button
waitForPageToLoad
waitForElementPresentcss=#add-app-mem > div > div:nth-of-type(2) > h2
assertElementPresentcss=#add-app-mem > div > div:nth-of-type(2) > h2
waitForPageToLoad
waitForElementPresentcss=.application-perms > div:nth-of-type(1) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
clickcss=.application-perms > div:nth-of-type(1) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
waitForPageToLoad
waitForElementPresentcss=.application-perms > div:nth-of-type(2) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
clickcss=.application-perms > div:nth-of-type(2) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
waitForPageToLoad
waitForElementPresentcss=.application-perms > div:nth-of-type(3) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
clickcss=.application-perms > div:nth-of-type(3) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
waitForPageToLoad
waitForElementPresentcss=[name=environment_roles-0-role]
typecss=[name=environment_roles-0-role]Basic Access
waitForPageToLoad
waitForElementPresentcss=[name=environment_roles-1-role]
typecss=[name=environment_roles-1-role]Network Admin
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=table.atat-table > tbody > tr > td:nth-of-type(1) > strong
assertTextcss=table.atat-table > tbody > tr > td:nth-of-type(1) > strong*Brandon Buchannan*
waitForPageToLoad
waitForElementPresentcss=.label
assertTextcss=.label*INVITE PENDING*
waitForPageToLoad
waitForElementPresentcss=section.member-list.application-list
assertElementPresentcss=section.member-list.application-list
waitForPageToLoad
waitForElementPresentcss=h3.usa-alert-heading
assertTextcss=h3.usa-alert-heading*Brandon's invitation has been sent*
waitForPageToLoad
waitForElementPresentcss=span.action-group-footer > a.usa-button
clickcss=span.action-group-footer > a.usa-button
waitForPageToLoad
waitForElementPresentcss=.usa-input.usa-input--validation--anything > input[id="name"][type="text"]
assertTextcss=.usa-input.usa-input--validation--anything > input[id="name"][type="text"]*Starter Application*
waitForPageToLoad
waitForElementPresentcss=#description
assertTextcss=#description*Any basic application*
waitForPageToLoad
waitForElementPresentcss=.label
assertTextcss=.label*INVITE PENDING*
waitForPageToLoad
waitForElementPresentcss=.accordion-table__items > .accordion-table__item:nth-of-type(1) > .accordion-table__item-content > .environment-list__item > .label.label--below
assertElementPresentcss=.accordion-table__items > .accordion-table__item:nth-of-type(1) > .accordion-table__item-content > .environment-list__item > .label.label--below
waitForPageToLoad
waitForElementPresentcss=#delete-application
assertTextcss=#delete-application*Delete application*
- - \ No newline at end of file From dd09f386fede8075c66b686a6087130a8c8fd28a Mon Sep 17 00:00:00 2001 From: "Jay R. Newlin (PromptWorks)" Date: Tue, 17 Dec 2019 14:48:28 -0500 Subject: [PATCH 013/114] New test to support others; doesn't run standalone --- uitests/Create_TO_after_other_steps.html | 388 +++++++++++++++++++++++ 1 file changed, 388 insertions(+) create mode 100644 uitests/Create_TO_after_other_steps.html diff --git a/uitests/Create_TO_after_other_steps.html b/uitests/Create_TO_after_other_steps.html new file mode 100644 index 00000000..9583a99e --- /dev/null +++ b/uitests/Create_TO_after_other_steps.html @@ -0,0 +1,388 @@ + + + + + + +Create TO after other steps + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Create TO after other steps
waitForPageToLoad
waitForElementPresentcss=.icon--funding
clickcss=.icon--funding
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-buttons > .usa-button.usa-button-primary
clickcss=.sticky-cta-buttons > .usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=.upload-button
clickcss=.upload-button
waitForPageToLoad
waitForElementPresentcss=#pdf
typecss=#pdfhttps://ghostinspector-prod.s3.amazonaws.com/uploads/310638bb-42fd-4158-b14f-417826ae4f79.pdf
waitForPageToLoad
assertElementNotPresentcss=input[type="submit"][disabled="disabled"]
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=#number
typecss=#number${timestamp}
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=#clins-0-number
typecss=#clins-0-number0002
waitForPageToLoad
waitForElementPresentcss=#clins-0-jedi_clin_type
typecss=#clins-0-jedi_clin_typeJEDI_CLIN_2
waitForPageToLoad
waitForElementPresentcss=#clins-0-total_amount
typecss=#clins-0-total_amount$800,000
waitForPageToLoad
waitForElementPresentcss=#clins-0-obligated_amount
typecss=#clins-0-obligated_amount$100,000
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]10
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]1
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]2019
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]6
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]30
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]2020
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
clickcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=a.usa-button.usa-button-primary
clickcss=a.usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=fieldset.usa-input__choices > legend > label
clickcss=fieldset.usa-input__choices > legend > label
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=h3.usa-alert-heading
assertTextcss=h3.usa-alert-heading*Your Task Order has been uploaded successfully.*
+ + \ No newline at end of file From 301fcd3f78ea952b0aed39d4548bba72e5430e1d Mon Sep 17 00:00:00 2001 From: "Jay R. Newlin (PromptWorks)" Date: Tue, 17 Dec 2019 15:33:39 -0500 Subject: [PATCH 014/114] New test to support others; doesn't run standalone --- uitests/Add_expired_TO.html | 373 ++++++++++++++++++++++++++++++++++++ 1 file changed, 373 insertions(+) create mode 100644 uitests/Add_expired_TO.html diff --git a/uitests/Add_expired_TO.html b/uitests/Add_expired_TO.html new file mode 100644 index 00000000..71f6a617 --- /dev/null +++ b/uitests/Add_expired_TO.html @@ -0,0 +1,373 @@ + + + + + + +Add expired TO + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Add expired TO
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-buttons > .usa-button.usa-button-primary
clickcss=.sticky-cta-buttons > .usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=.upload-button
clickcss=.upload-button
waitForPageToLoad
waitForElementPresentcss=#pdf
typecss=#pdfhttps://ghostinspector-prod.s3.amazonaws.com/uploads/310638bb-42fd-4158-b14f-417826ae4f79.pdf
waitForPageToLoad
assertElementNotPresentcss=input[type="submit"][disabled="disabled"]
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=#number
typecss=#number${timestamp}
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=#clins-0-number
typecss=#clins-0-number0001
waitForPageToLoad
waitForElementPresentcss=#clins-0-jedi_clin_type
typecss=#clins-0-jedi_clin_typeJEDI_CLIN_1
waitForPageToLoad
waitForElementPresentcss=#clins-0-total_amount
typecss=#clins-0-total_amount$40,000
waitForPageToLoad
waitForElementPresentcss=#clins-0-obligated_amount
typecss=#clins-0-obligated_amount$8,000
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]10
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]1
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]2019
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]10
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]31
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]2019
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
clickcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=a.usa-button.usa-button-primary
clickcss=a.usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=fieldset.usa-input__choices > legend > label
clickcss=fieldset.usa-input__choices > legend > label
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=h3.usa-alert-heading
assertTextcss=h3.usa-alert-heading*Your Task Order has been uploaded successfully.*
+ + \ No newline at end of file From b270d0e4b0bcc25545d37fd50fa2678fc39911dd Mon Sep 17 00:00:00 2001 From: graham-dds Date: Tue, 17 Dec 2019 16:10:21 -0500 Subject: [PATCH 015/114] Update new portfolio layout - Move CTA buttons to floating footer - separated -> bordered --- styles/components/_forms.scss | 3 +- templates/portfolios/new/step_1.html | 54 ++++++++++++++-------------- 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/styles/components/_forms.scss b/styles/components/_forms.scss index a6e0709a..43c31c43 100644 --- a/styles/components/_forms.scss +++ b/styles/components/_forms.scss @@ -1,7 +1,8 @@ // Form Grid .form-row { margin: ($gap * 4) 0; - &--separated { + + &--bordered { border-bottom: $color-gray-lighter 1px solid; } diff --git a/templates/portfolios/new/step_1.html b/templates/portfolios/new/step_1.html index 4613b063..3383128b 100644 --- a/templates/portfolios/new/step_1.html +++ b/templates/portfolios/new/step_1.html @@ -16,36 +16,36 @@ {{ StickyCTA(text="Create New Portfolio") }} -
- {{ form.csrf_token }} -
-
- {{ TextInput(form.name, optional=False) }} - {{"forms.portfolio.name.help_text" | translate | safe }} +
+ + {{ form.csrf_token }} +
+
+ {{ TextInput(form.name, optional=False, classes="form-col") }} + {{"forms.portfolio.name.help_text" | translate | safe }} +
-
-
-
- {{ TextInput(form.description, paragraph=True) }} - {{"forms.portfolio.description.help_text" | translate | safe }} +
+
+ {{ TextInput(form.description, paragraph=True) }} + {{"forms.portfolio.description.help_text" | translate | safe }} +
-
-
-
- {{ MultiCheckboxInput(form.defense_component, optional=False) }} - {{ "forms.portfolio.defense_component.help_text" | translate | safe }} +
+
+ {{ MultiCheckboxInput(form.defense_component, optional=False) }} + {{ "forms.portfolio.defense_component.help_text" | translate | safe }} +
-
-
- {{ - SaveButton( - text=('common.save' | translate), - form="portfolio-create", - element="input", - ) - }} -
- + {% endblock %} From 4b5558be8d76bf183a941cac68ee02c502b33b00 Mon Sep 17 00:00:00 2001 From: "Jay R. Newlin (PromptWorks)" Date: Tue, 17 Dec 2019 17:06:04 -0500 Subject: [PATCH 016/114] New test to support others; doesn't run standalone --- uitests/Add_future_TO.html | 373 +++++++++++++++++++++++++++++++++++++ 1 file changed, 373 insertions(+) create mode 100644 uitests/Add_future_TO.html diff --git a/uitests/Add_future_TO.html b/uitests/Add_future_TO.html new file mode 100644 index 00000000..89b22c7a --- /dev/null +++ b/uitests/Add_future_TO.html @@ -0,0 +1,373 @@ + + + + + + +Add future TO + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Add future TO
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-buttons > .usa-button.usa-button-primary
clickcss=.sticky-cta-buttons > .usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=.upload-button
clickcss=.upload-button
waitForPageToLoad
waitForElementPresentcss=#pdf
typecss=#pdfhttps://ghostinspector-prod.s3.amazonaws.com/uploads/310638bb-42fd-4158-b14f-417826ae4f79.pdf
waitForPageToLoad
assertElementNotPresentcss=input[type="submit"][disabled="disabled"]
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=#number
typecss=#number${timestamp}
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=#clins-0-number
typecss=#clins-0-number0001
waitForPageToLoad
waitForElementPresentcss=#clins-0-jedi_clin_type
typecss=#clins-0-jedi_clin_typeJEDI_CLIN_1
waitForPageToLoad
waitForElementPresentcss=#clins-0-total_amount
typecss=#clins-0-total_amount$500,000
waitForPageToLoad
waitForElementPresentcss=#clins-0-obligated_amount
typecss=#clins-0-obligated_amount$5,000
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]7
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]1
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]2020
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]12
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]31
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]2020
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
clickcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=a.usa-button.usa-button-primary
clickcss=a.usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=fieldset.usa-input__choices > legend > label
clickcss=fieldset.usa-input__choices > legend > label
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=h3.usa-alert-heading
assertTextcss=h3.usa-alert-heading*Your Task Order has been uploaded successfully.*
+ + \ No newline at end of file From 812caf5d7d4fdc537b3e244cd5fea146feccb861 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Mon, 16 Dec 2019 11:02:18 -0500 Subject: [PATCH 017/114] Update schema and create/update Environments domain methods to enforce environment name uniqueness within an application context. --- ...dd_uniqueness_contraint_to_environment_.py | 28 +++++++++++++++++++ atst/domain/environments.py | 6 ++-- atst/models/environment.py | 8 +++++- tests/domain/test_environments.py | 23 ++++++++++++++- 4 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 alembic/versions/08f2a640e9c2_add_uniqueness_contraint_to_environment_.py diff --git a/alembic/versions/08f2a640e9c2_add_uniqueness_contraint_to_environment_.py b/alembic/versions/08f2a640e9c2_add_uniqueness_contraint_to_environment_.py new file mode 100644 index 00000000..56985f73 --- /dev/null +++ b/alembic/versions/08f2a640e9c2_add_uniqueness_contraint_to_environment_.py @@ -0,0 +1,28 @@ +"""add uniqueness contraint to environment within an application + +Revision ID: 08f2a640e9c2 +Revises: c487d91f1a26 +Create Date: 2019-12-16 10:43:12.331095 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision = '08f2a640e9c2' # pragma: allowlist secret +down_revision = 'c487d91f1a26' # pragma: allowlist secret +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_unique_constraint('environments_name_application_id_key', 'environments', ['name', 'application_id']) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_constraint('environments_name_application_id_key', 'environments', type_='unique') + # ### end Alembic commands ### diff --git a/atst/domain/environments.py b/atst/domain/environments.py index a1056623..fd5f3eb0 100644 --- a/atst/domain/environments.py +++ b/atst/domain/environments.py @@ -12,6 +12,7 @@ from atst.models import ( CLIN, ) from atst.domain.environment_roles import EnvironmentRoles +from atst.utils import update_or_raise_already_exists_error from .exceptions import NotFoundError, DisabledError @@ -21,7 +22,7 @@ class Environments(object): def create(cls, user, application, name): environment = Environment(application=application, name=name, creator=user) db.session.add(environment) - db.session.commit() + update_or_raise_already_exists_error(message="environment") return environment @classmethod @@ -39,7 +40,8 @@ class Environments(object): if name is not None: environment.name = name db.session.add(environment) - db.session.commit() + update_or_raise_already_exists_error(message="environment") + return environment @classmethod def get(cls, environment_id): diff --git a/atst/models/environment.py b/atst/models/environment.py index 5fc642e5..115f3ed7 100644 --- a/atst/models/environment.py +++ b/atst/models/environment.py @@ -1,4 +1,4 @@ -from sqlalchemy import Column, ForeignKey, String, TIMESTAMP +from sqlalchemy import Column, ForeignKey, String, TIMESTAMP, UniqueConstraint from sqlalchemy.orm import relationship from sqlalchemy.dialects.postgresql import JSONB from enum import Enum @@ -38,6 +38,12 @@ class Environment( primaryjoin="and_(EnvironmentRole.environment_id == Environment.id, EnvironmentRole.deleted == False)", ) + __table_args__ = ( + UniqueConstraint( + "name", "application_id", name="environments_name_application_id_key" + ), + ) + class ProvisioningStatus(Enum): PENDING = "pending" COMPLETED = "completed" diff --git a/tests/domain/test_environments.py b/tests/domain/test_environments.py index 3aa5f547..298f2675 100644 --- a/tests/domain/test_environments.py +++ b/tests/domain/test_environments.py @@ -4,7 +4,7 @@ from uuid import uuid4 from atst.domain.environments import Environments from atst.domain.environment_roles import EnvironmentRoles -from atst.domain.exceptions import NotFoundError, DisabledError +from atst.domain.exceptions import AlreadyExistsError, DisabledError, NotFoundError from atst.models.environment_role import CSPRole, EnvironmentRole from tests.factories import ( @@ -100,6 +100,27 @@ def test_update_environment(): assert environment.name == "name 2" +def test_create_does_not_duplicate_names_within_application(): + application = ApplicationFactory.create() + name = "Your Environment" + user = application.portfolio.owner + + assert Environments.create(user, application, name) + with pytest.raises(AlreadyExistsError): + Environments.create(user, application, name) + + +def test_update_does_not_duplicate_names_within_application(): + application = ApplicationFactory.create() + name = "Your Environment" + environment = EnvironmentFactory.create(application=application, name=name) + dupe_env = EnvironmentFactory.create(application=application) + user = application.portfolio.owner + + with pytest.raises(AlreadyExistsError): + Environments.update(dupe_env, name) + + class EnvQueryTest: @property def NOW(self): From 63a5d9274b86a24ffd3e44b15ab7296385ae6207 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Mon, 16 Dec 2019 14:38:46 -0500 Subject: [PATCH 018/114] Update route to handle error when env names are duplicated --- atst/routes/applications/settings.py | 69 +++++++++++++--------- atst/utils/flash.py | 5 ++ templates/applications/settings.html | 3 + tests/routes/applications/test_settings.py | 20 ++++++- translations.yaml | 6 +- 5 files changed, 70 insertions(+), 33 deletions(-) diff --git a/atst/routes/applications/settings.py b/atst/routes/applications/settings.py index f2d252a9..66131c15 100644 --- a/atst/routes/applications/settings.py +++ b/atst/routes/applications/settings.py @@ -1,4 +1,10 @@ -from flask import redirect, render_template, request as http_request, url_for, g +from flask import ( + redirect, + render_template, + request as http_request, + url_for, + g, +) from .blueprint import applications_bp from atst.domain.exceptions import AlreadyExistsError @@ -245,16 +251,36 @@ def handle_update_member(application_id, application_role_id, form_data): # TODO: flash error message +def handle_update_environment(form, application=None, environment=None): + if form.validate(): + try: + if environment: + environment = Environments.update( + environment=environment, name=form.name.data + ) + flash("application_environments_updated") + else: + environment = Environments.create( + g.current_user, application=application, name=form.name.data + ) + flash("environment_added", environment_name=form.name.data) + + return environment + + except AlreadyExistsError: + flash("application_environments_name_error", name=form.name.data) + return False + + else: + return False + + @applications_bp.route("/applications//settings") @user_can(Permissions.VIEW_APPLICATION, message="view application edit form") def settings(application_id): application = Applications.get(application_id) - return render_settings_page( - application=application, - active_toggler=http_request.args.get("active_toggler"), - active_toggler_section=http_request.args.get("active_toggler_section"), - ) + return render_settings_page(application=application,) @applications_bp.route("/environments//edit", methods=["POST"]) @@ -264,31 +290,21 @@ def update_environment(environment_id): application = environment.application env_form = EditEnvironmentForm(obj=environment, formdata=http_request.form) + updated_environment = handle_update_environment( + form=env_form, application=application, environment=environment + ) - if env_form.validate(): - Environments.update(environment=environment, name=env_form.name.data) - - flash("application_environments_updated") - + if updated_environment: return redirect( url_for( "applications.settings", application_id=application.id, fragment="application-environments", _anchor="application-environments", - active_toggler=environment.id, - active_toggler_section="edit", ) ) else: - return ( - render_settings_page( - application=application, - active_toggler=environment.id, - active_toggler_section="edit", - ), - 400, - ) + return (render_settings_page(application=application, show_flash=True), 400) @applications_bp.route( @@ -298,14 +314,9 @@ def update_environment(environment_id): def new_environment(application_id): application = Applications.get(application_id) env_form = EditEnvironmentForm(formdata=http_request.form) + environment = handle_update_environment(form=env_form, application=application) - if env_form.validate(): - Environments.create( - g.current_user, application=application, name=env_form.name.data - ) - - flash("environment_added", environment_name=env_form.data["name"]) - + if environment: return redirect( url_for( "applications.settings", @@ -315,7 +326,7 @@ def new_environment(application_id): ) ) else: - return (render_settings_page(application=application), 400) + return (render_settings_page(application=application, show_flash=True), 400) @applications_bp.route("/applications//edit", methods=["POST"]) diff --git a/atst/utils/flash.py b/atst/utils/flash.py index 0de143bb..f876330f 100644 --- a/atst/utils/flash.py +++ b/atst/utils/flash.py @@ -29,6 +29,11 @@ MESSAGES = { """, "category": "success", }, + "application_environments_name_error": { + "title_template": "", + "message_template": """{{ 'flash.application.env_name_error.message' | translate({ 'name': name }) }}""", + "category": "error", + }, "application_environments_updated": { "title_template": "Application environments updated", "message_template": "Application environments have been updated", diff --git a/templates/applications/settings.html b/templates/applications/settings.html index c8e41fcd..875f0232 100644 --- a/templates/applications/settings.html +++ b/templates/applications/settings.html @@ -13,6 +13,9 @@ {% block application_content %} + {% if show_flash -%} + {% include "fragments/flash.html" %} + {%- endif %}

{{ 'portfolios.applications.settings.name_description' | translate }}

{% if user_can(permissions.EDIT_APPLICATION) %} diff --git a/tests/routes/applications/test_settings.py b/tests/routes/applications/test_settings.py index 08c979ad..597664d1 100644 --- a/tests/routes/applications/test_settings.py +++ b/tests/routes/applications/test_settings.py @@ -52,8 +52,6 @@ def test_updating_application_environments_success(client, user_session): _external=True, fragment="application-environments", _anchor="application-environments", - active_toggler=environment.id, - active_toggler_section="edit", ) assert environment.name == "new name a" @@ -78,6 +76,24 @@ def test_update_environment_failure(client, user_session): assert environment.name == "original name" +def test_enforces_unique_env_name(client, user_session, session): + application = ApplicationFactory.create() + user = application.portfolio.owner + name = "New Environment" + environment = EnvironmentFactory.create(application=application, name=name) + form_data = {"name": name} + user_session(user) + + session.begin_nested() + response = client.post( + url_for("applications.new_environment", application_id=application.id), + data=form_data, + ) + session.rollback() + + assert response.status_code == 400 + + def test_application_settings(client, user_session): portfolio = PortfolioFactory.create() application = Applications.create( diff --git a/translations.yaml b/translations.yaml index 6a678f48..e0277fff 100644 --- a/translations.yaml +++ b/translations.yaml @@ -116,6 +116,8 @@ flash: deleted: 'You have successfully deleted the {application_name} application. To view the retained activity log, visit the portfolio administration page.' name_error: message: 'The application name {name} has already been used in this portfolio. Please enter a unique name.' + env_name_error: + message: 'The environment name {name} has already been used in this application. Please enter a unique name.' delete_member_success: 'You have successfully deleted {member_name} from the portfolio.' deleted_member: Portfolio member deleted environment_added: 'The environment "{env_name}" has been added to the application.' @@ -199,7 +201,7 @@ forms:

- defense_component: + defense_component: label: "Select DoD component(s) funding your Portfolio:" choices: air_force: Air Force @@ -211,7 +213,7 @@ forms: help_text: |

Select the DOD component(s) that will fund all Applications within this Portfolio. - In JEDI, multiple DoD organizations can fund the same Portfolio.
+ In JEDI, multiple DoD organizations can fund the same Portfolio.
Select all that apply.

attachment: From e82e0b482a5cd4c02924dacb127cce716d54d021 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Tue, 17 Dec 2019 15:49:48 -0500 Subject: [PATCH 019/114] remove unused imports --- .../08f2a640e9c2_add_uniqueness_contraint_to_environment_.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/alembic/versions/08f2a640e9c2_add_uniqueness_contraint_to_environment_.py b/alembic/versions/08f2a640e9c2_add_uniqueness_contraint_to_environment_.py index 56985f73..bfc5b894 100644 --- a/alembic/versions/08f2a640e9c2_add_uniqueness_contraint_to_environment_.py +++ b/alembic/versions/08f2a640e9c2_add_uniqueness_contraint_to_environment_.py @@ -6,8 +6,6 @@ Create Date: 2019-12-16 10:43:12.331095 """ from alembic import op -import sqlalchemy as sa -from sqlalchemy.dialects import postgresql # revision identifiers, used by Alembic. revision = '08f2a640e9c2' # pragma: allowlist secret From d300ccf31b74e8fd9cf8b304edaf4eb650957d47 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Wed, 18 Dec 2019 10:37:19 -0500 Subject: [PATCH 020/114] Catch error on update applications route when app name is duplicated within a portfolio --- .secrets.baseline | 4 +-- atst/routes/applications/new.py | 32 ++------------------ atst/routes/applications/settings.py | 34 +++++++++++++++++++--- tests/routes/applications/test_settings.py | 17 +++++++++++ tests/test_access.py | 12 ++++++-- 5 files changed, 61 insertions(+), 38 deletions(-) diff --git a/.secrets.baseline b/.secrets.baseline index 24361804..ffa18c6e 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "^.secrets.baseline$|^.*pgsslrootcert.yml$", "lines": null }, - "generated_at": "2019-12-13T20:38:57Z", + "generated_at": "2019-12-18T15:29:41Z", "plugins_used": [ { "base64_limit": 4.5, @@ -170,7 +170,7 @@ "hashed_secret": "e4f14805dfd1e6af030359090c535e149e6b4207", "is_secret": false, "is_verified": false, - "line_number": 659, + "line_number": 665, "type": "Hex High Entropy String" } ] diff --git a/atst/routes/applications/new.py b/atst/routes/applications/new.py index e9238775..9d673b04 100644 --- a/atst/routes/applications/new.py +++ b/atst/routes/applications/new.py @@ -1,9 +1,7 @@ -from flask import redirect, render_template, request as http_request, url_for, g +from flask import redirect, render_template, request as http_request, url_for from .blueprint import applications_bp from atst.domain.applications import Applications -from atst.domain.exceptions import AlreadyExistsError -from atst.domain.portfolios import Portfolios from atst.forms.application import NameAndDescriptionForm, EnvironmentsForm from atst.domain.authz.decorator import user_can_access_decorator as user_can from atst.models.permissions import Permissions @@ -13,6 +11,7 @@ from atst.routes.applications.settings import ( get_new_member_form, handle_create_member, handle_update_member, + handle_update_application, ) @@ -38,31 +37,6 @@ def render_new_application_form( return render_template(template, **render_args) -def update_application(form, application_id=None, portfolio_id=None): - if form.validate(): - application = None - try: - if application_id: - application = Applications.get(application_id) - application = Applications.update(application, form.data) - flash("application_updated", application_name=application.name) - else: - portfolio = Portfolios.get_for_update(portfolio_id) - application = Applications.create( - g.current_user, portfolio, **form.data - ) - flash("application_created", application_name=application.name) - - return application - - except AlreadyExistsError: - flash("application_name_error", name=form.data["name"]) - return False - - else: - return False - - @applications_bp.route("/portfolios//applications/new") @applications_bp.route("/applications//new/step_1") @user_can(Permissions.CREATE_APPLICATION, message="view create new application form") @@ -90,7 +64,7 @@ def create_or_update_new_application_step_1(portfolio_id=None, application_id=No form = get_new_application_form( {**http_request.form}, NameAndDescriptionForm, application_id ) - application = update_application(form, application_id, portfolio_id) + application = handle_update_application(form, application_id, portfolio_id) if application: return redirect( diff --git a/atst/routes/applications/settings.py b/atst/routes/applications/settings.py index 66131c15..fc95c615 100644 --- a/atst/routes/applications/settings.py +++ b/atst/routes/applications/settings.py @@ -16,6 +16,7 @@ from atst.domain.csp.cloud import GeneralCSPException from atst.domain.common import Paginator from atst.domain.environment_roles import EnvironmentRoles from atst.domain.invitations import ApplicationInvitations +from atst.domain.portfolios import Portfolios from atst.forms.application_member import NewForm as NewMemberForm, UpdateMemberForm from atst.forms.application import NameAndDescriptionForm, EditEnvironmentForm from atst.forms.data import ENV_ROLE_NO_ACCESS as NO_ACCESS @@ -275,6 +276,29 @@ def handle_update_environment(form, application=None, environment=None): return False +def handle_update_application(form, application_id=None, portfolio_id=None): + if form.validate(): + application = None + + try: + if application_id: + application = Applications.get(application_id) + application = Applications.update(application, form.data) + flash("application_updated", application_name=application.name) + else: + portfolio = Portfolios.get_for_update(portfolio_id) + application = Applications.create( + g.current_user, portfolio, **form.data + ) + flash("application_created", application_name=application.name) + + return application + + except AlreadyExistsError: + flash("application_name_error", name=form.data["name"]) + return False + + @applications_bp.route("/applications//settings") @user_can(Permissions.VIEW_APPLICATION, message="view application edit form") def settings(application_id): @@ -334,10 +358,9 @@ def new_environment(application_id): def update(application_id): application = Applications.get(application_id) form = NameAndDescriptionForm(http_request.form) - if form.validate(): - application_data = form.data - Applications.update(application, application_data) + updated_application = handle_update_application(form, application_id) + if updated_application: return redirect( url_for( "applications.portfolio_applications", @@ -345,7 +368,10 @@ def update(application_id): ) ) else: - return render_settings_page(application=application, application_form=form) + return ( + render_settings_page(application=application, show_flash=True), + 400, + ) @applications_bp.route("/applications//delete", methods=["POST"]) diff --git a/tests/routes/applications/test_settings.py b/tests/routes/applications/test_settings.py index 597664d1..e9117166 100644 --- a/tests/routes/applications/test_settings.py +++ b/tests/routes/applications/test_settings.py @@ -274,6 +274,23 @@ def test_user_without_permission_cannot_update_application(client, user_session) assert application.description == "Cool stuff happening here!" +def test_update_application_enforces_unique_name(client, user_session, session): + portfolio = PortfolioFactory.create() + name = "Test Application" + application = ApplicationFactory.create(portfolio=portfolio, name=name) + dupe_application = ApplicationFactory.create(portfolio=portfolio) + user_session(portfolio.owner) + + session.begin_nested() + response = client.post( + url_for("applications.update", application_id=dupe_application.id), + data={"name": name, "description": dupe_application.description}, + ) + session.rollback() + + assert response.status_code == 400 + + def test_user_can_only_access_apps_in_their_portfolio(client, user_session): portfolio = PortfolioFactory.create() other_portfolio = PortfolioFactory.create( diff --git a/tests/test_access.py b/tests/test_access.py index ad4bd5be..ccae69ba 100644 --- a/tests/test_access.py +++ b/tests/test_access.py @@ -538,10 +538,16 @@ def test_applications_update_access(post_url_assert_status): ) app = portfolio.applications[0] + def _form_data(): + return { + "name": "Test Application %s" % (random.randrange(1, 1000)), + "description": "This is only a test", + } + url = url_for("applications.update", application_id=app.id) - post_url_assert_status(dev, url, 200) - post_url_assert_status(ccpo, url, 200) - post_url_assert_status(rando, url, 404) + post_url_assert_status(dev, url, 302, data=_form_data()) + post_url_assert_status(ccpo, url, 302, data=_form_data()) + post_url_assert_status(rando, url, 404, data=_form_data()) # applications.update_environments From f543602076b6468eb7eddc8a2c833a5976bac0d6 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Wed, 18 Dec 2019 10:54:00 -0500 Subject: [PATCH 021/114] Update function name to better reflect what it does --- atst/domain/applications.py | 6 +++--- atst/domain/environments.py | 6 +++--- atst/domain/task_orders.py | 6 +++--- atst/utils/__init__.py | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/atst/domain/applications.py b/atst/domain/applications.py index c2321194..3dbb9953 100644 --- a/atst/domain/applications.py +++ b/atst/domain/applications.py @@ -11,7 +11,7 @@ from atst.models import ( ApplicationRoleStatus, EnvironmentRole, ) -from atst.utils import first_or_none, update_or_raise_already_exists_error +from atst.utils import first_or_none, commit_or_raise_already_exists_error class Applications(BaseDomainClass): @@ -28,7 +28,7 @@ class Applications(BaseDomainClass): if environment_names: Environments.create_many(user, application, environment_names) - update_or_raise_already_exists_error(message="application") + commit_or_raise_already_exists_error(message="application") return application @classmethod @@ -55,7 +55,7 @@ class Applications(BaseDomainClass): ) db.session.add(application) - update_or_raise_already_exists_error(message="application") + commit_or_raise_already_exists_error(message="application") return application @classmethod diff --git a/atst/domain/environments.py b/atst/domain/environments.py index fd5f3eb0..b8a59485 100644 --- a/atst/domain/environments.py +++ b/atst/domain/environments.py @@ -12,7 +12,7 @@ from atst.models import ( CLIN, ) from atst.domain.environment_roles import EnvironmentRoles -from atst.utils import update_or_raise_already_exists_error +from atst.utils import commit_or_raise_already_exists_error from .exceptions import NotFoundError, DisabledError @@ -22,7 +22,7 @@ class Environments(object): def create(cls, user, application, name): environment = Environment(application=application, name=name, creator=user) db.session.add(environment) - update_or_raise_already_exists_error(message="environment") + commit_or_raise_already_exists_error(message="environment") return environment @classmethod @@ -40,7 +40,7 @@ class Environments(object): if name is not None: environment.name = name db.session.add(environment) - update_or_raise_already_exists_error(message="environment") + commit_or_raise_already_exists_error(message="environment") return environment @classmethod diff --git a/atst/domain/task_orders.py b/atst/domain/task_orders.py index 8ad8b0f4..9ecf41e9 100644 --- a/atst/domain/task_orders.py +++ b/atst/domain/task_orders.py @@ -4,7 +4,7 @@ from atst.database import db from atst.models.clin import CLIN from atst.models.task_order import TaskOrder, SORT_ORDERING from . import BaseDomainClass -from atst.utils import update_or_raise_already_exists_error +from atst.utils import commit_or_raise_already_exists_error class TaskOrders(BaseDomainClass): @@ -15,7 +15,7 @@ class TaskOrders(BaseDomainClass): def create(cls, portfolio_id, number, clins, pdf): task_order = TaskOrder(portfolio_id=portfolio_id, number=number, pdf=pdf) db.session.add(task_order) - update_or_raise_already_exists_error(message="task_order") + commit_or_raise_already_exists_error(message="task_order") TaskOrders.create_clins(task_order.id, clins) return task_order @@ -34,7 +34,7 @@ class TaskOrders(BaseDomainClass): task_order.number = number db.session.add(task_order) - update_or_raise_already_exists_error(message="task_order") + commit_or_raise_already_exists_error(message="task_order") return task_order @classmethod diff --git a/atst/utils/__init__.py b/atst/utils/__init__.py index 9772af67..d3f284cc 100644 --- a/atst/utils/__init__.py +++ b/atst/utils/__init__.py @@ -30,7 +30,7 @@ def pick(keys, dct): return {k: v for (k, v) in dct.items() if k in _keys} -def update_or_raise_already_exists_error(message): +def commit_or_raise_already_exists_error(message): try: db.session.commit() except IntegrityError: From 096cff620ef945dc739e79fbac86c5d279488d5b Mon Sep 17 00:00:00 2001 From: "Jay R. Newlin (PromptWorks)" Date: Wed, 18 Dec 2019 11:08:07 -0500 Subject: [PATCH 022/114] New tests that serve as bases/steps in others --- uitests/Create_New_Application.html | 547 ++++++++++++++++++++++++++++ uitests/Create_New_TO.html | 529 +++++++++++++++++++++++++++ 2 files changed, 1076 insertions(+) create mode 100644 uitests/Create_New_Application.html create mode 100644 uitests/Create_New_TO.html diff --git a/uitests/Create_New_Application.html b/uitests/Create_New_Application.html new file mode 100644 index 00000000..0bac9367 --- /dev/null +++ b/uitests/Create_New_Application.html @@ -0,0 +1,547 @@ + + + + + + +Create New Application + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Create New Application
waitForPageToLoad
open/login-dev?username=brandon
waitForPageToLoad
waitForElementPresentcss=a[href="/user"] > .topbar__link-label
assertTextcss=a[href="/user"] > .topbar__link-label*Brandon Buchannan*
waitForPageToLoad
waitForElementPresentcss=a[href="/logout"] > .topbar__link-label
clickcss=a[href="/logout"] > .topbar__link-label
waitForPageToLoad
waitForElementPresentcss=.col > .usa-alert.usa-alert-info:nth-of-type(2) > .usa-alert-body > h3.usa-alert-heading
assertTextcss=.col > .usa-alert.usa-alert-info:nth-of-type(2) > .usa-alert-body > h3.usa-alert-heading*Logged out*
waitForPageToLoad
open/login-dev
waitForPageToLoad
waitForElementPresentcss=.about-cloud > h1
assertTextcss=.about-cloud > h1About Cloud Services
waitForPageToLoad
waitForElementPresentcss=a[href="/portfolios/new"]
clickcss=a[href="/portfolios/new"]
waitForPageToLoad
waitForElementPresentcss=.portfolio-header__name > h1
assertTextcss=.portfolio-header__name > h1*New Portfolio*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Create New Portfolio*
waitForPageToLoad
waitForElementPresentcss=#name
typecss=#nameTatooine Energy Maintenance Systems
waitForPageToLoad
waitForElementPresentcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.empty-state > h3
assertTextcss=.empty-state > h3*You don't have any Applications yet*
waitForPageToLoad
waitForElementPresentcss=.usa-button.usa-button-primary
clickcss=.usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=#name
typecss=#nameStarter Application
waitForPageToLoad
waitForElementPresentcss=button[type="submit"]
clickcss=button[type="submit"]
waitForPageToLoad
waitForElementPresentcss=button[type="submit"]
clickcss=button[type="submit"]
waitForPageToLoad
waitForElementPresentcss=a.usa-button.usa-button-secondary.add-new-button
clickcss=a.usa-button.usa-button-secondary.add-new-button
waitForPageToLoad
waitForElementPresentcss=#user_data-first_name
typecss=#user_data-first_nameBrandon
waitForPageToLoad
waitForElementPresentcss=#user_data-last_name
typecss=#user_data-last_nameBuchannan
waitForPageToLoad
waitForElementPresentcss=#user_data-email
typecss=#user_data-emailjay+brandon@promptworks.com
waitForPageToLoad
waitForElementPresentcss=#user_data-dod_id
typecss=#user_data-dod_id3456789012
waitForPageToLoad
waitForElementPresentcss=#add-app-mem > div > div:nth-of-type(1) > .action-group > input[type="button"].action-group__action.usa-button
clickcss=#add-app-mem > div > div:nth-of-type(1) > .action-group > input[type="button"].action-group__action.usa-button
waitForPageToLoad
waitForElementPresentcss=.application-perms > div:nth-of-type(1) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
clickcss=.application-perms > div:nth-of-type(1) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
waitForPageToLoad
waitForElementPresentcss=.application-perms > div:nth-of-type(2) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
clickcss=.application-perms > div:nth-of-type(2) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
waitForPageToLoad
waitForElementPresentcss=.application-perms > div:nth-of-type(3) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
clickcss=.application-perms > div:nth-of-type(3) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
waitForPageToLoad
waitForElementPresentcss=#environment_roles-0-role-None
typecss=#environment_roles-0-role-NoneBasic Access
waitForPageToLoad
waitForElementPresentcss=#environment_roles-1-role-None
typecss=#environment_roles-1-role-NoneNetwork Admin
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=span.action-group-footer > a.usa-button
clickcss=span.action-group-footer > a.usa-button
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Starter Application*
waitForPageToLoad
waitForElementPresentcss=.label
assertTextcss=.label*INVITE PENDING*
waitForPageToLoad
waitForElementPresentcss=.accordion-table__items > .accordion-table__item:nth-of-type(1) > .accordion-table__item-content > .environment-list__item > .label.label--below
assertElementPresentcss=.accordion-table__items > .accordion-table__item:nth-of-type(1) > .accordion-table__item-content > .environment-list__item > .label.label--below
waitForPageToLoad
waitForElementPresentcss=#delete-application
assertTextcss=#delete-application*Delete application*
+ + \ No newline at end of file diff --git a/uitests/Create_New_TO.html b/uitests/Create_New_TO.html new file mode 100644 index 00000000..1980dfc8 --- /dev/null +++ b/uitests/Create_New_TO.html @@ -0,0 +1,529 @@ + + + + + + +Create New TO + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Create New TO
waitForPageToLoad
open/login-dev
waitForPageToLoad
waitForElementPresentcss=.about-cloud > h1
assertTextcss=.about-cloud > h1About Cloud Services
waitForPageToLoad
waitForElementPresentcss=a[href="/portfolios/new"]
clickcss=a[href="/portfolios/new"]
waitForPageToLoad
waitForElementPresentcss=.portfolio-header__name > h1
assertTextcss=.portfolio-header__name > h1*New Portfolio*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Create New Portfolio*
waitForPageToLoad
waitForElementPresentcss=#name
typecss=#nameTatooine Energy Maintenance Systems
waitForPageToLoad
waitForElementPresentcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.empty-state > h3
assertTextcss=.empty-state > h3*You don't have any Applications yet*
waitForPageToLoad
waitForElementPresentcss=.icon--funding
clickcss=.icon--funding
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-buttons > .usa-button.usa-button-primary
clickcss=.sticky-cta-buttons > .usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=.upload-button
clickcss=.upload-button
waitForPageToLoad
waitForElementPresentcss=#pdf
typecss=#pdfhttps://ghostinspector-prod.s3.amazonaws.com/uploads/310638bb-42fd-4158-b14f-417826ae4f79.pdf
waitForPageToLoad
assertElementNotPresentcss=input[type="submit"][disabled="disabled"]
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=#number
typecss=#number${timestamp}
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=#clins-0-number
typecss=#clins-0-number0002
waitForPageToLoad
waitForElementPresentcss=#clins-0-jedi_clin_type
typecss=#clins-0-jedi_clin_typeJEDI_CLIN_2
waitForPageToLoad
waitForElementPresentcss=#clins-0-total_amount
typecss=#clins-0-total_amount$800,000
waitForPageToLoad
waitForElementPresentcss=#clins-0-obligated_amount
typecss=#clins-0-obligated_amount$100,000
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]10
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]1
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]2019
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]6
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]30
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]2020
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
clickcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=a.usa-button.usa-button-primary
clickcss=a.usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=fieldset.usa-input__choices > legend > label
clickcss=fieldset.usa-input__choices > legend > label
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=h3.usa-alert-heading
assertTextcss=h3.usa-alert-heading*Your Task Order has been uploaded successfully.*
+ + \ No newline at end of file From e585e8fcaac1fea24c49841a8346f94440eb6542 Mon Sep 17 00:00:00 2001 From: "Jay R. Newlin (PromptWorks)" Date: Wed, 18 Dec 2019 11:11:47 -0500 Subject: [PATCH 023/114] New tests for TO Index page --- ...TO_Index_(Landing)_Page_-_Empty_State.html | 258 ++++ uitests/TO_Index_with_Draft_TO.html | 849 +++++++++++ uitests/TO_Index_with_TO.html | 877 ++++++++++++ uitests/TO_Index_with_Unsigned_TO.html | 1027 +++++++++++++ uitests/TO_Index_with_expired_TO.html | 1151 +++++++++++++++ uitests/TO_Index_with_future_TO.html | 1273 +++++++++++++++++ 6 files changed, 5435 insertions(+) create mode 100644 uitests/TO_Index_(Landing)_Page_-_Empty_State.html create mode 100644 uitests/TO_Index_with_Draft_TO.html create mode 100644 uitests/TO_Index_with_TO.html create mode 100644 uitests/TO_Index_with_Unsigned_TO.html create mode 100644 uitests/TO_Index_with_expired_TO.html create mode 100644 uitests/TO_Index_with_future_TO.html diff --git a/uitests/TO_Index_(Landing)_Page_-_Empty_State.html b/uitests/TO_Index_(Landing)_Page_-_Empty_State.html new file mode 100644 index 00000000..70d615fc --- /dev/null +++ b/uitests/TO_Index_(Landing)_Page_-_Empty_State.html @@ -0,0 +1,258 @@ + + + + + + +TO Index (Landing) Page - Empty State + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TO Index (Landing) Page - Empty State
waitForPageToLoad
open/login-dev
waitForPageToLoad
waitForElementPresentcss=.about-cloud > h1
assertTextcss=.about-cloud > h1About Cloud Services
waitForPageToLoad
waitForElementPresentcss=a[href="/portfolios/new"]
clickcss=a[href="/portfolios/new"]
waitForPageToLoad
waitForElementPresentcss=.portfolio-header__name > h1
assertTextcss=.portfolio-header__name > h1*New Portfolio*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Create New Portfolio*
waitForPageToLoad
waitForElementPresentcss=#name
typecss=#nameTatooine Energy Maintenance Systems
waitForPageToLoad
waitForElementPresentcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.empty-state > h3
assertTextcss=.empty-state > h3*You don't have any Applications yet*
waitForPageToLoad
waitForElementPresentcss=.icon--funding
clickcss=.icon--funding
waitForPageToLoad
pause5000
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Task Orders*
waitForPageToLoad
waitForElementPresentcss=.empty-state > h3
assertTextcss=.empty-state > h3*Add approved task orders*
waitForPageToLoad
waitForElementPresentcss=.empty-state__footer > a.usa-button.usa-button-primary
assertElementPresentcss=.empty-state__footer > a.usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-buttons > a.usa-button.usa-button-primary
assertElementPresentcss=.sticky-cta-buttons > a.usa-button.usa-button-primary
+ + \ No newline at end of file diff --git a/uitests/TO_Index_with_Draft_TO.html b/uitests/TO_Index_with_Draft_TO.html new file mode 100644 index 00000000..1769434e --- /dev/null +++ b/uitests/TO_Index_with_Draft_TO.html @@ -0,0 +1,849 @@ + + + + + + +TO Index with Draft TO + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TO Index with Draft TO
waitForPageToLoad
open/login-dev
waitForPageToLoad
waitForElementPresentcss=.about-cloud > h1
assertTextcss=.about-cloud > h1About Cloud Services
waitForPageToLoad
waitForElementPresentcss=a[href="/portfolios/new"]
clickcss=a[href="/portfolios/new"]
waitForPageToLoad
waitForElementPresentcss=.portfolio-header__name > h1
assertTextcss=.portfolio-header__name > h1*New Portfolio*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Create New Portfolio*
waitForPageToLoad
waitForElementPresentcss=#name
typecss=#nameTatooine Energy Maintenance Systems
waitForPageToLoad
waitForElementPresentcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.empty-state > h3
assertTextcss=.empty-state > h3*You don't have any Applications yet*
waitForPageToLoad
waitForElementPresentcss=.icon--funding
clickcss=.icon--funding
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-buttons > .usa-button.usa-button-primary
clickcss=.sticky-cta-buttons > .usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=.upload-button
clickcss=.upload-button
waitForPageToLoad
waitForElementPresentcss=#pdf
typecss=#pdfhttps://ghostinspector-prod.s3.amazonaws.com/uploads/310638bb-42fd-4158-b14f-417826ae4f79.pdf
waitForPageToLoad
assertElementNotPresentcss=input[type="submit"][disabled="disabled"]
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=#number
typecss=#number${timestamp}
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=#clins-0-number
typecss=#clins-0-number0002
waitForPageToLoad
waitForElementPresentcss=#clins-0-jedi_clin_type
typecss=#clins-0-jedi_clin_typeJEDI_CLIN_2
waitForPageToLoad
waitForElementPresentcss=#clins-0-total_amount
typecss=#clins-0-total_amount$800,000
waitForPageToLoad
waitForElementPresentcss=#clins-0-obligated_amount
typecss=#clins-0-obligated_amount$100,000
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]10
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]1
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]2019
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]6
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]30
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]2020
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
clickcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=a.usa-button.usa-button-primary
clickcss=a.usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=fieldset.usa-input__choices > legend > label
clickcss=fieldset.usa-input__choices > legend > label
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=h3.usa-alert-heading
assertTextcss=h3.usa-alert-heading*Your Task Order has been uploaded successfully.*
waitForPageToLoad
waitForElementPresentcss=.usa-button.usa-button-primary
clickcss=.usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=.upload-button
clickcss=.upload-button
waitForPageToLoad
waitForElementPresentcss=#pdf
typecss=#pdfhttps://ghostinspector-prod.s3.amazonaws.com/uploads/0b480cc1-e73e-448e-837e-e624407d5dc4.pdf
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=#number
typecss=#number${timestamp}
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=a.action-group__action
clickcss=a.action-group__action
waitForPageToLoad
waitForElementPresentcss=.action-group > button[type="submit"].usa-button.usa-button-primary:nth-of-type(2)
clickcss=.action-group > button[type="submit"].usa-button.usa-button-primary:nth-of-type(2)
waitForPageToLoad
waitForElementPresentcss=.accordion-list > .accordion:nth-of-type(2) > div > h4.accordion__button > button.usa-accordion-button
clickcss=.accordion-list > .accordion:nth-of-type(2) > div > h4.accordion__button > button.usa-accordion-button
waitForPageToLoad
waitForElementPresentcss=.accordion-list > .accordion:nth-of-type(3) > div > h4.accordion__button > button.usa-accordion-button
clickcss=.accordion-list > .accordion:nth-of-type(3) > div > h4.accordion__button > button.usa-accordion-button
waitForPageToLoad
waitForElementPresentcss=#Draft > .accordion__content--list-item
assertElementPresentcss=#Draft > .accordion__content--list-item
waitForPageToLoad
waitForElementPresentcss=#Draft > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(1)
assertElementPresentcss=#Draft > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(1)
waitForPageToLoad
waitForElementPresentcss=#Draft > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(1) > p
assertTextcss=#Draft > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(1) > p*- + - + -*
waitForPageToLoad
waitForElementPresentcss=#Draft > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(2)
assertElementPresentcss=#Draft > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(2)
waitForPageToLoad
waitForElementPresentcss=#Draft > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(2) > p
assertTextcss=#Draft > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(2) > p*$0.00*
waitForPageToLoad
waitForElementPresentcss=#Draft > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(3)
assertElementPresentcss=#Draft > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(3)
waitForPageToLoad
waitForElementPresentcss=#Draft > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(3) > p
assertTextcss=#Draft > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(3) > p*$0.00*
waitForPageToLoad
waitForElementPresentcss=#Draft > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(4)
assertElementPresentcss=#Draft > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(4)
waitForPageToLoad
waitForElementPresentcss=#Draft > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(4) > p
assertTextcss=#Draft > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(4) > p*$0.00*
+ + \ No newline at end of file diff --git a/uitests/TO_Index_with_TO.html b/uitests/TO_Index_with_TO.html new file mode 100644 index 00000000..a96d033c --- /dev/null +++ b/uitests/TO_Index_with_TO.html @@ -0,0 +1,877 @@ + + + + + + +TO Index with TO + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TO Index with TO
waitForPageToLoad
open/login-dev
waitForPageToLoad
waitForElementPresentcss=.about-cloud > h1
assertTextcss=.about-cloud > h1About Cloud Services
waitForPageToLoad
waitForElementPresentcss=a[href="/portfolios/new"]
clickcss=a[href="/portfolios/new"]
waitForPageToLoad
waitForElementPresentcss=.portfolio-header__name > h1
assertTextcss=.portfolio-header__name > h1*New Portfolio*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Create New Portfolio*
waitForPageToLoad
waitForElementPresentcss=#name
typecss=#nameTatooine Energy Maintenance Systems
waitForPageToLoad
waitForElementPresentcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.empty-state > h3
assertTextcss=.empty-state > h3*You don't have any Applications yet*
waitForPageToLoad
waitForElementPresentcss=.icon--funding
clickcss=.icon--funding
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-buttons > .usa-button.usa-button-primary
clickcss=.sticky-cta-buttons > .usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=.upload-button
clickcss=.upload-button
waitForPageToLoad
waitForElementPresentcss=#pdf
typecss=#pdfhttps://ghostinspector-prod.s3.amazonaws.com/uploads/310638bb-42fd-4158-b14f-417826ae4f79.pdf
waitForPageToLoad
assertElementNotPresentcss=input[type="submit"][disabled="disabled"]
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=#number
typecss=#number${timestamp}
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=#clins-0-number
typecss=#clins-0-number0002
waitForPageToLoad
waitForElementPresentcss=#clins-0-jedi_clin_type
typecss=#clins-0-jedi_clin_typeJEDI_CLIN_2
waitForPageToLoad
waitForElementPresentcss=#clins-0-total_amount
typecss=#clins-0-total_amount$800,000
waitForPageToLoad
waitForElementPresentcss=#clins-0-obligated_amount
typecss=#clins-0-obligated_amount$100,000
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]10
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]1
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]2019
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]6
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]30
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]2020
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
clickcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=a.usa-button.usa-button-primary
clickcss=a.usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=fieldset.usa-input__choices > legend > label
clickcss=fieldset.usa-input__choices > legend > label
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=h3.usa-alert-heading
assertTextcss=h3.usa-alert-heading*Your Task Order has been uploaded successfully.*
waitForPageToLoad
waitForElementPresentcss=.accordion-list > .accordion:nth-of-type(2) > div > h4.accordion__button > button.usa-accordion-button
clickcss=.accordion-list > .accordion:nth-of-type(2) > div > h4.accordion__button > button.usa-accordion-button
waitForPageToLoad
waitForElementPresentcss=.accordion__content--list-item > .row > .col.col--grow:nth-of-type(1)
assertElementPresentcss=.accordion__content--list-item > .row > .col.col--grow:nth-of-type(1)
waitForPageToLoad
waitForElementPresentcss=.row > .col.col--grow:nth-of-type(2)
assertElementPresentcss=.row > .col.col--grow:nth-of-type(2)
waitForPageToLoad
waitForElementPresentcss=.row > .col.col--grow:nth-of-type(3)
assertElementPresentcss=.row > .col.col--grow:nth-of-type(3)
waitForPageToLoad
waitForElementPresentcss=.row > .col.col--grow:nth-of-type(4)
assertElementPresentcss=.row > .col.col--grow:nth-of-type(4)
waitForPageToLoad
waitForElementPresentcss=.accordion-list > .accordion:nth-of-type(3) > div > h4.accordion__button > button.usa-accordion-button
clickcss=.accordion-list > .accordion:nth-of-type(3) > div > h4.accordion__button > button.usa-accordion-button
waitForPageToLoad
waitForElementPresentcss=#Draft > .accordion__content--empty
assertTextcss=#Draft > .accordion__content--empty*This Portfolio has no Draft Task Orders.*
waitForPageToLoad
waitForElementPresentcss=.accordion-list > .accordion:nth-of-type(4) > div > h4.accordion__button > button.usa-accordion-button
clickcss=.accordion-list > .accordion:nth-of-type(4) > div > h4.accordion__button > button.usa-accordion-button
waitForPageToLoad
waitForElementPresentcss=#Upcoming > .accordion__content--empty
assertTextcss=#Upcoming > .accordion__content--empty*This Portfolio has no Upcoming Task Orders.*
waitForPageToLoad
waitForElementPresentcss=.accordion-list > .accordion:nth-of-type(5) > div > h4.accordion__button > button.usa-accordion-button
clickcss=.accordion-list > .accordion:nth-of-type(5) > div > h4.accordion__button > button.usa-accordion-button
waitForPageToLoad
waitForElementPresentcss=#Expired > .accordion__content--empty
assertTextcss=#Expired > .accordion__content--empty*This Portfolio has no Expired Task Orders.*
waitForPageToLoad
waitForElementPresentcss=.accordion-list > .accordion:nth-of-type(6) > div > h4.accordion__button > button.usa-accordion-button
clickcss=.accordion-list > .accordion:nth-of-type(6) > div > h4.accordion__button > button.usa-accordion-button
waitForPageToLoad
waitForElementPresentcss=#Unsigned > .accordion__content--empty
assertTextcss=#Unsigned > .accordion__content--empty*This Portfolio has no Unsigned Task Orders.*
waitForPageToLoad
waitForElementPresentcss=.accordion-list > .accordion:nth-of-type(6) > div > h4.accordion__button > button.usa-accordion-button
clickcss=.accordion-list > .accordion:nth-of-type(6) > div > h4.accordion__button > button.usa-accordion-button
waitForPageToLoad
waitForElementPresentcss=.accordion-list > .accordion:nth-of-type(5) > div > h4.accordion__button > button.usa-accordion-button
clickcss=.accordion-list > .accordion:nth-of-type(5) > div > h4.accordion__button > button.usa-accordion-button
waitForPageToLoad
waitForElementPresentcss=.accordion-list > .accordion:nth-of-type(4) > div > h4.accordion__button > button.usa-accordion-button
clickcss=.accordion-list > .accordion:nth-of-type(4) > div > h4.accordion__button > button.usa-accordion-button
waitForPageToLoad
waitForElementPresentcss=.accordion-list > .accordion:nth-of-type(3) > div > h4.accordion__button > button.usa-accordion-button
clickcss=.accordion-list > .accordion:nth-of-type(3) > div > h4.accordion__button > button.usa-accordion-button
waitForPageToLoad
waitForElementPresentcss=.accordion-list > .accordion:nth-of-type(2) > div > h4.accordion__button > button.usa-accordion-button
clickcss=.accordion-list > .accordion:nth-of-type(2) > div > h4.accordion__button > button.usa-accordion-button
waitForPageToLoad
waitForElementPresentcss=.accordion-list > .accordion:nth-of-type(2) > div > h4.accordion__button > button.usa-accordion-button
clickcss=.accordion-list > .accordion:nth-of-type(2) > div > h4.accordion__button > button.usa-accordion-button
waitForPageToLoad
waitForElementPresentcss=.accordion-list > .accordion:nth-of-type(5) > div > h4.accordion__button > button.usa-accordion-button
clickcss=.accordion-list > .accordion:nth-of-type(5) > div > h4.accordion__button > button.usa-accordion-button
waitForPageToLoad
waitForElementPresentcss=a.accordion-list__collapse
clickcss=a.accordion-list__collapse
+ + \ No newline at end of file diff --git a/uitests/TO_Index_with_Unsigned_TO.html b/uitests/TO_Index_with_Unsigned_TO.html new file mode 100644 index 00000000..86897b35 --- /dev/null +++ b/uitests/TO_Index_with_Unsigned_TO.html @@ -0,0 +1,1027 @@ + + + + + + +TO Index with Unsigned TO + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TO Index with Unsigned TO
waitForPageToLoad
open/login-dev
waitForPageToLoad
waitForElementPresentcss=.about-cloud > h1
assertTextcss=.about-cloud > h1About Cloud Services
waitForPageToLoad
waitForElementPresentcss=a[href="/portfolios/new"]
clickcss=a[href="/portfolios/new"]
waitForPageToLoad
waitForElementPresentcss=.portfolio-header__name > h1
assertTextcss=.portfolio-header__name > h1*New Portfolio*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Create New Portfolio*
waitForPageToLoad
waitForElementPresentcss=#name
typecss=#nameTatooine Energy Maintenance Systems
waitForPageToLoad
waitForElementPresentcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.empty-state > h3
assertTextcss=.empty-state > h3*You don't have any Applications yet*
waitForPageToLoad
waitForElementPresentcss=.icon--funding
clickcss=.icon--funding
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-buttons > .usa-button.usa-button-primary
clickcss=.sticky-cta-buttons > .usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=.upload-button
clickcss=.upload-button
waitForPageToLoad
waitForElementPresentcss=#pdf
typecss=#pdfhttps://ghostinspector-prod.s3.amazonaws.com/uploads/310638bb-42fd-4158-b14f-417826ae4f79.pdf
waitForPageToLoad
assertElementNotPresentcss=input[type="submit"][disabled="disabled"]
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=#number
typecss=#number${timestamp}
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=#clins-0-number
typecss=#clins-0-number0002
waitForPageToLoad
waitForElementPresentcss=#clins-0-jedi_clin_type
typecss=#clins-0-jedi_clin_typeJEDI_CLIN_2
waitForPageToLoad
waitForElementPresentcss=#clins-0-total_amount
typecss=#clins-0-total_amount$800,000
waitForPageToLoad
waitForElementPresentcss=#clins-0-obligated_amount
typecss=#clins-0-obligated_amount$100,000
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]10
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]1
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]2019
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]6
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]30
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]2020
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
clickcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=a.usa-button.usa-button-primary
clickcss=a.usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=fieldset.usa-input__choices > legend > label
clickcss=fieldset.usa-input__choices > legend > label
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=h3.usa-alert-heading
assertTextcss=h3.usa-alert-heading*Your Task Order has been uploaded successfully.*
waitForPageToLoad
waitForElementPresentcss=.usa-button.usa-button-primary
clickcss=.usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=.upload-button
clickcss=.upload-button
waitForPageToLoad
waitForElementPresentcss=#pdf
typecss=#pdfhttps://ghostinspector-prod.s3.amazonaws.com/uploads/0b480cc1-e73e-448e-837e-e624407d5dc4.pdf
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=#number
typecss=#number${timestamp}
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=#clins-0-number
typecss=#clins-0-number0001
waitForPageToLoad
waitForElementPresentcss=#clins-0-total_amount
typecss=#clins-0-total_amount$40,000
waitForPageToLoad
waitForElementPresentcss=#clins-0-obligated_amount
typecss=#clins-0-obligated_amount$10,000
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]10
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]1
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]2019
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]4
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]30
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]2020
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
clickcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=a.action-group__action
clickcss=a.action-group__action
waitForPageToLoad
waitForElementPresentcss=.action-group > button[type="submit"].usa-button.usa-button-primary:nth-of-type(2)
clickcss=.action-group > button[type="submit"].usa-button.usa-button-primary:nth-of-type(2)
waitForPageToLoad
waitForElementPresentcss=.accordion-list > .accordion:nth-of-type(2) > div > h4.accordion__button > button.usa-accordion-button
clickcss=.accordion-list > .accordion:nth-of-type(2) > div > h4.accordion__button > button.usa-accordion-button
waitForPageToLoad
waitForElementPresentcss=.accordion-list > .accordion:nth-of-type(6) > div > h4.accordion__button > button.usa-accordion-button
clickcss=.accordion-list > .accordion:nth-of-type(6) > div > h4.accordion__button > button.usa-accordion-button
waitForPageToLoad
waitForElementPresentcss=#Active > .accordion__content--list-item
assertElementPresentcss=#Active > .accordion__content--list-item
waitForPageToLoad
waitForElementPresentcss=#Unsigned > .accordion__content--list-item
assertElementPresentcss=#Unsigned > .accordion__content--list-item
waitForPageToLoad
waitForElementPresentcss=#Unsigned > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(1)
assertElementPresentcss=#Unsigned > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(1)
waitForPageToLoad
waitForElementPresentcss=#Unsigned > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(2)
assertElementPresentcss=#Unsigned > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(2)
waitForPageToLoad
waitForElementPresentcss=#Unsigned > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(3)
assertElementPresentcss=#Unsigned > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(3)
waitForPageToLoad
waitForElementPresentcss=#Unsigned > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(4)
assertElementPresentcss=#Unsigned > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(4)
waitForPageToLoad
waitForElementPresentcss=#Active > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(4)
assertElementPresentcss=#Active > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(4)
waitForPageToLoad
waitForElementPresentcss=#Active > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(3)
assertElementPresentcss=#Active > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(3)
waitForPageToLoad
waitForElementPresentcss=#Active > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(2)
assertElementPresentcss=#Active > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(2)
waitForPageToLoad
waitForElementPresentcss=#Active > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(1)
assertElementPresentcss=#Active > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(1)
+ + \ No newline at end of file diff --git a/uitests/TO_Index_with_expired_TO.html b/uitests/TO_Index_with_expired_TO.html new file mode 100644 index 00000000..401645e6 --- /dev/null +++ b/uitests/TO_Index_with_expired_TO.html @@ -0,0 +1,1151 @@ + + + + + + +TO Index with expired TO + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TO Index with expired TO
waitForPageToLoad
open/login-dev
waitForPageToLoad
waitForElementPresentcss=.about-cloud > h1
assertTextcss=.about-cloud > h1About Cloud Services
waitForPageToLoad
waitForElementPresentcss=a[href="/portfolios/new"]
clickcss=a[href="/portfolios/new"]
waitForPageToLoad
waitForElementPresentcss=.portfolio-header__name > h1
assertTextcss=.portfolio-header__name > h1*New Portfolio*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Create New Portfolio*
waitForPageToLoad
waitForElementPresentcss=#name
typecss=#nameTatooine Energy Maintenance Systems
waitForPageToLoad
waitForElementPresentcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.empty-state > h3
assertTextcss=.empty-state > h3*You don't have any Applications yet*
waitForPageToLoad
waitForElementPresentcss=.icon--funding
clickcss=.icon--funding
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-buttons > .usa-button.usa-button-primary
clickcss=.sticky-cta-buttons > .usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=.upload-button
clickcss=.upload-button
waitForPageToLoad
waitForElementPresentcss=#pdf
typecss=#pdfhttps://ghostinspector-prod.s3.amazonaws.com/uploads/310638bb-42fd-4158-b14f-417826ae4f79.pdf
waitForPageToLoad
assertElementNotPresentcss=input[type="submit"][disabled="disabled"]
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=#number
typecss=#number${timestamp}
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=#clins-0-number
typecss=#clins-0-number0002
waitForPageToLoad
waitForElementPresentcss=#clins-0-jedi_clin_type
typecss=#clins-0-jedi_clin_typeJEDI_CLIN_2
waitForPageToLoad
waitForElementPresentcss=#clins-0-total_amount
typecss=#clins-0-total_amount$800,000
waitForPageToLoad
waitForElementPresentcss=#clins-0-obligated_amount
typecss=#clins-0-obligated_amount$100,000
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]10
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]1
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]2019
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]6
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]30
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]2020
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
clickcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=a.usa-button.usa-button-primary
clickcss=a.usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=fieldset.usa-input__choices > legend > label
clickcss=fieldset.usa-input__choices > legend > label
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=h3.usa-alert-heading
assertTextcss=h3.usa-alert-heading*Your Task Order has been uploaded successfully.*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-buttons > .usa-button.usa-button-primary
clickcss=.sticky-cta-buttons > .usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=.upload-button
clickcss=.upload-button
waitForPageToLoad
waitForElementPresentcss=#pdf
typecss=#pdfhttps://ghostinspector-prod.s3.amazonaws.com/uploads/310638bb-42fd-4158-b14f-417826ae4f79.pdf
waitForPageToLoad
assertElementNotPresentcss=input[type="submit"][disabled="disabled"]
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=#number
typecss=#number${timestamp}
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=#clins-0-number
typecss=#clins-0-number0001
waitForPageToLoad
waitForElementPresentcss=#clins-0-jedi_clin_type
typecss=#clins-0-jedi_clin_typeJEDI_CLIN_1
waitForPageToLoad
waitForElementPresentcss=#clins-0-total_amount
typecss=#clins-0-total_amount$40,000
waitForPageToLoad
waitForElementPresentcss=#clins-0-obligated_amount
typecss=#clins-0-obligated_amount$8,000
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]10
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]1
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]2019
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]10
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]31
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]2019
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
clickcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=a.usa-button.usa-button-primary
clickcss=a.usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=fieldset.usa-input__choices > legend > label
clickcss=fieldset.usa-input__choices > legend > label
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=h3.usa-alert-heading
assertTextcss=h3.usa-alert-heading*Your Task Order has been uploaded successfully.*
waitForPageToLoad
waitForElementPresentcss=.accordion-list > .accordion:nth-of-type(2) > div > h4.accordion__button > button.usa-accordion-button
clickcss=.accordion-list > .accordion:nth-of-type(2) > div > h4.accordion__button > button.usa-accordion-button
waitForPageToLoad
waitForElementPresentcss=.accordion__content--list-item > .row > .col.col--grow:nth-of-type(1)
assertElementPresentcss=.accordion__content--list-item > .row > .col.col--grow:nth-of-type(1)
waitForPageToLoad
waitForElementPresentcss=.row > .col.col--grow:nth-of-type(2)
assertElementPresentcss=.row > .col.col--grow:nth-of-type(2)
waitForPageToLoad
waitForElementPresentcss=.row > .col.col--grow:nth-of-type(3)
assertElementPresentcss=.row > .col.col--grow:nth-of-type(3)
waitForPageToLoad
waitForElementPresentcss=.row > .col.col--grow:nth-of-type(4)
assertElementPresentcss=.row > .col.col--grow:nth-of-type(4)
waitForPageToLoad
waitForElementPresentcss=.accordion-list > .accordion:nth-of-type(3) > div > h4.accordion__button > button.usa-accordion-button
clickcss=.accordion-list > .accordion:nth-of-type(3) > div > h4.accordion__button > button.usa-accordion-button
waitForPageToLoad
waitForElementPresentcss=#Draft > .accordion__content--empty
assertTextcss=#Draft > .accordion__content--empty*This Portfolio has no Draft Task Orders.*
waitForPageToLoad
waitForElementPresentcss=.accordion-list > .accordion:nth-of-type(4) > div > h4.accordion__button > button.usa-accordion-button
clickcss=.accordion-list > .accordion:nth-of-type(4) > div > h4.accordion__button > button.usa-accordion-button
waitForPageToLoad
waitForElementPresentcss=#Upcoming > .accordion__content--empty
assertTextcss=#Upcoming > .accordion__content--empty*This Portfolio has no Upcoming Task Orders.*
waitForPageToLoad
waitForElementPresentcss=.accordion-list > .accordion:nth-of-type(6) > div > h4.accordion__button > button.usa-accordion-button
clickcss=.accordion-list > .accordion:nth-of-type(6) > div > h4.accordion__button > button.usa-accordion-button
waitForPageToLoad
waitForElementPresentcss=#Unsigned > .accordion__content--empty
assertTextcss=#Unsigned > .accordion__content--empty*This Portfolio has no Unsigned Task Orders.*
waitForPageToLoad
waitForElementPresentcss=a.accordion-list__collapse
clickcss=a.accordion-list__collapse
waitForPageToLoad
waitForElementPresentcss=.accordion-list > .accordion:nth-of-type(2) > div > h4.accordion__button > button.usa-accordion-button
clickcss=.accordion-list > .accordion:nth-of-type(2) > div > h4.accordion__button > button.usa-accordion-button
waitForPageToLoad
waitForElementPresentcss=.accordion-list > .accordion:nth-of-type(5) > div > h4.accordion__button > button.usa-accordion-button
clickcss=.accordion-list > .accordion:nth-of-type(5) > div > h4.accordion__button > button.usa-accordion-button
waitForPageToLoad
waitForElementPresentcss=#Expired.usa-accordion-content.accordion__content
assertElementPresentcss=#Expired.usa-accordion-content.accordion__content
+ + \ No newline at end of file diff --git a/uitests/TO_Index_with_future_TO.html b/uitests/TO_Index_with_future_TO.html new file mode 100644 index 00000000..ff3ddb1a --- /dev/null +++ b/uitests/TO_Index_with_future_TO.html @@ -0,0 +1,1273 @@ + + + + + + +TO Index with future TO + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TO Index with future TO
waitForPageToLoad
open/login-dev
waitForPageToLoad
waitForElementPresentcss=.about-cloud > h1
assertTextcss=.about-cloud > h1About Cloud Services
waitForPageToLoad
waitForElementPresentcss=a[href="/portfolios/new"]
clickcss=a[href="/portfolios/new"]
waitForPageToLoad
waitForElementPresentcss=.portfolio-header__name > h1
assertTextcss=.portfolio-header__name > h1*New Portfolio*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Create New Portfolio*
waitForPageToLoad
waitForElementPresentcss=#name
typecss=#nameTatooine Energy Maintenance Systems
waitForPageToLoad
waitForElementPresentcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.empty-state > h3
assertTextcss=.empty-state > h3*You don't have any Applications yet*
waitForPageToLoad
waitForElementPresentcss=.icon--funding
clickcss=.icon--funding
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-buttons > .usa-button.usa-button-primary
clickcss=.sticky-cta-buttons > .usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=.upload-button
clickcss=.upload-button
waitForPageToLoad
waitForElementPresentcss=#pdf
typecss=#pdfhttps://ghostinspector-prod.s3.amazonaws.com/uploads/310638bb-42fd-4158-b14f-417826ae4f79.pdf
waitForPageToLoad
assertElementNotPresentcss=input[type="submit"][disabled="disabled"]
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=#number
typecss=#number${timestamp}
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=#clins-0-number
typecss=#clins-0-number0002
waitForPageToLoad
waitForElementPresentcss=#clins-0-jedi_clin_type
typecss=#clins-0-jedi_clin_typeJEDI_CLIN_2
waitForPageToLoad
waitForElementPresentcss=#clins-0-total_amount
typecss=#clins-0-total_amount$800,000
waitForPageToLoad
waitForElementPresentcss=#clins-0-obligated_amount
typecss=#clins-0-obligated_amount$100,000
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]10
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]1
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]2019
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]6
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]30
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]2020
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
clickcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=a.usa-button.usa-button-primary
clickcss=a.usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=fieldset.usa-input__choices > legend > label
clickcss=fieldset.usa-input__choices > legend > label
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=h3.usa-alert-heading
assertTextcss=h3.usa-alert-heading*Your Task Order has been uploaded successfully.*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-buttons > .usa-button.usa-button-primary
clickcss=.sticky-cta-buttons > .usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=.upload-button
clickcss=.upload-button
waitForPageToLoad
waitForElementPresentcss=#pdf
typecss=#pdfhttps://ghostinspector-prod.s3.amazonaws.com/uploads/310638bb-42fd-4158-b14f-417826ae4f79.pdf
waitForPageToLoad
assertElementNotPresentcss=input[type="submit"][disabled="disabled"]
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=#number
typecss=#number${timestamp}
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=#clins-0-number
typecss=#clins-0-number0001
waitForPageToLoad
waitForElementPresentcss=#clins-0-jedi_clin_type
typecss=#clins-0-jedi_clin_typeJEDI_CLIN_1
waitForPageToLoad
waitForElementPresentcss=#clins-0-total_amount
typecss=#clins-0-total_amount$500,000
waitForPageToLoad
waitForElementPresentcss=#clins-0-obligated_amount
typecss=#clins-0-obligated_amount$5,000
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]7
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]1
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]2020
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]12
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]31
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]2020
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
clickcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=a.usa-button.usa-button-primary
clickcss=a.usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=fieldset.usa-input__choices > legend > label
clickcss=fieldset.usa-input__choices > legend > label
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=h3.usa-alert-heading
assertTextcss=h3.usa-alert-heading*Your Task Order has been uploaded successfully.*
waitForPageToLoad
waitForElementPresentcss=.accordion-list > .accordion:nth-of-type(2) > div > h4.accordion__button > button.usa-accordion-button
clickcss=.accordion-list > .accordion:nth-of-type(2) > div > h4.accordion__button > button.usa-accordion-button
waitForPageToLoad
waitForElementPresentcss=.accordion__content--list-item > .row > .col.col--grow:nth-of-type(1)
assertElementPresentcss=.accordion__content--list-item > .row > .col.col--grow:nth-of-type(1)
waitForPageToLoad
waitForElementPresentcss=.row > .col.col--grow:nth-of-type(2)
assertElementPresentcss=.row > .col.col--grow:nth-of-type(2)
waitForPageToLoad
waitForElementPresentcss=.row > .col.col--grow:nth-of-type(3)
assertElementPresentcss=.row > .col.col--grow:nth-of-type(3)
waitForPageToLoad
waitForElementPresentcss=.row > .col.col--grow:nth-of-type(4)
assertElementPresentcss=.row > .col.col--grow:nth-of-type(4)
waitForPageToLoad
waitForElementPresentcss=.accordion-list > .accordion:nth-of-type(3) > div > h4.accordion__button > button.usa-accordion-button
clickcss=.accordion-list > .accordion:nth-of-type(3) > div > h4.accordion__button > button.usa-accordion-button
waitForPageToLoad
waitForElementPresentcss=#Draft > .accordion__content--empty
assertTextcss=#Draft > .accordion__content--empty*This Portfolio has no Draft Task Orders.*
waitForPageToLoad
waitForElementPresentcss=.accordion-list > .accordion:nth-of-type(5) > div > h4.accordion__button > button.usa-accordion-button
clickcss=.accordion-list > .accordion:nth-of-type(5) > div > h4.accordion__button > button.usa-accordion-button
waitForPageToLoad
waitForElementPresentcss=#Expired > .accordion__content--empty
assertTextcss=#Expired > .accordion__content--empty*This Portfolio has no Expired Task Orders.*
waitForPageToLoad
waitForElementPresentcss=.accordion-list > .accordion:nth-of-type(6) > div > h4.accordion__button > button.usa-accordion-button
clickcss=.accordion-list > .accordion:nth-of-type(6) > div > h4.accordion__button > button.usa-accordion-button
waitForPageToLoad
waitForElementPresentcss=#Unsigned > .accordion__content--empty
assertTextcss=#Unsigned > .accordion__content--empty*This Portfolio has no Unsigned Task Orders.*
waitForPageToLoad
waitForElementPresentcss=a.accordion-list__collapse
clickcss=a.accordion-list__collapse
waitForPageToLoad
waitForElementPresentcss=.accordion-list > .accordion:nth-of-type(2) > div > h4.accordion__button > button.usa-accordion-button
clickcss=.accordion-list > .accordion:nth-of-type(2) > div > h4.accordion__button > button.usa-accordion-button
waitForPageToLoad
waitForElementPresentcss=#Expired.usa-accordion-content.accordion__content
assertElementPresentcss=#Expired.usa-accordion-content.accordion__content
waitForPageToLoad
waitForElementPresentcss=.accordion-list > .accordion:nth-of-type(4) > div > h4.accordion__button > button.usa-accordion-button
clickcss=.accordion-list > .accordion:nth-of-type(4) > div > h4.accordion__button > button.usa-accordion-button
waitForPageToLoad
waitForElementPresentcss=#Upcoming > .accordion__content--list-item
assertElementPresentcss=#Upcoming > .accordion__content--list-item
waitForPageToLoad
waitForElementPresentcss=#Upcoming > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(1)
assertElementPresentcss=#Upcoming > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(1)
waitForPageToLoad
waitForElementPresentcss=#Upcoming > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(1) > p
assertTextcss=#Upcoming > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(1) > p*Jul 01, 2020 + - + Dec 31, 2020*
waitForPageToLoad
waitForElementPresentcss=#Upcoming > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(2)
assertElementPresentcss=#Upcoming > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(2)
waitForPageToLoad
waitForElementPresentcss=#Upcoming > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(2) > p
assertTextcss=#Upcoming > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(2) > p*$500,000.00*
waitForPageToLoad
waitForElementPresentcss=#Upcoming > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(3)
assertElementPresentcss=#Upcoming > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(3)
waitForPageToLoad
waitForElementPresentcss=#Upcoming > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(3) > p
assertTextcss=#Upcoming > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(3) > p*$5,000.00*
waitForPageToLoad
waitForElementPresentcss=#Upcoming > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(4)
assertElementPresentcss=#Upcoming > .accordion__content--list-item > .row > .col.col--grow:nth-of-type(4)
+ + \ No newline at end of file From d621781c3bfbddf3f821876288b19f93eb202a25 Mon Sep 17 00:00:00 2001 From: Rob Gil Date: Wed, 18 Dec 2019 11:12:14 -0500 Subject: [PATCH 024/114] 170339063 - Adds network diagrams Network diagrams are created with plantuml Ex. java -jar ~/plantuml.jar ./useast.txt java -jar ~/plantuml.jar ./uswest.txt Running this will create .png diagrams. PNG is the default but can be changed to SVG, PDF, etc --- .../diagram/USEAST Development Network.png | Bin 0 -> 86931 bytes .../diagram/USWEST Development Network.png | Bin 0 -> 72551 bytes terraform/providers/dev/diagram/useast.txt | 50 ++++++++++++++++++ terraform/providers/dev/diagram/uswest.txt | 40 ++++++++++++++ 4 files changed, 90 insertions(+) create mode 100644 terraform/providers/dev/diagram/USEAST Development Network.png create mode 100644 terraform/providers/dev/diagram/USWEST Development Network.png create mode 100644 terraform/providers/dev/diagram/useast.txt create mode 100644 terraform/providers/dev/diagram/uswest.txt diff --git a/terraform/providers/dev/diagram/USEAST Development Network.png b/terraform/providers/dev/diagram/USEAST Development Network.png new file mode 100644 index 0000000000000000000000000000000000000000..a32c05db125f6db4f815ff3b907929cd4bda3530 GIT binary patch literal 86931 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 literal 0 HcmV?d00001 diff --git a/terraform/providers/dev/diagram/USWEST Development Network.png b/terraform/providers/dev/diagram/USWEST Development Network.png new file mode 100644 index 0000000000000000000000000000000000000000..ba04343de458324b2311872dfbd6cf078e7dad40 GIT binary patch literal 72551 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%0D}U|OIEGoFMP3Yk%MlNl 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 F{0Fn6iQfPK literal 0 HcmV?d00001 diff --git a/terraform/providers/dev/diagram/useast.txt b/terraform/providers/dev/diagram/useast.txt new file mode 100644 index 00000000..48ee5c45 --- /dev/null +++ b/terraform/providers/dev/diagram/useast.txt @@ -0,0 +1,50 @@ +@startuml USEAST Development Network + +title USEAST Development Network + +cloud Internet + +cloud Azure { + [Azure Storage] as storage + [Azure CDN] as cdn + cdn --> storage : "HTTPS/443" + note as cdn_note + CDN and Azure storage are + managed by Azure and configured + for geographic failover + end note +} +frame "USEAST Virtual Network" as vnet { + frame "Public Route Table" as public_rt{ + frame "Public Subnet" as public_subnet { + [ALB] + [Internet] --> ALB + note as public_useast + 10.1.1.0/24 + end note + } + } + frame "Private Route Table" as private_rt{ + frame "Private Subnet" as private_subnet { + [AKS] + [Redis] + [Postgres] + [AzurePrivateStorage] + AKS --> Redis : "TLS:6379" + AKS --> Postgres : "TLS:5432" + AKS --> AzurePrivateStorage : "HTTPS/443" + [ALB] --> AKS : "HTTPS:443" + note as private_useast + 10.1.2.0/24 + end note + } + } +} + +frame "US West Backup Region" as backupregion { + component "Backup Postgres" as pgbackup + [Postgres] --> pgbackup : "Private Peering / TLS:5432" +} + +note right of [ALB] : Azure Load Balancer restricted to AKS only +@enduml diff --git a/terraform/providers/dev/diagram/uswest.txt b/terraform/providers/dev/diagram/uswest.txt new file mode 100644 index 00000000..1b2338f8 --- /dev/null +++ b/terraform/providers/dev/diagram/uswest.txt @@ -0,0 +1,40 @@ +@startuml USWEST Development Network + +title USWEST Development Network + +cloud Internet + +frame "USEAST Virtual Network" as vnet { + frame "Public Route Table" as public_rt{ + frame "Public Subnet" as public_subnet { + [ALB] + [Internet] --> ALB + note as public_useast + 10.2.1.0/24 + end note + } + } + frame "Private Route Table" as private_rt{ + frame "Private Subnet" as private_subnet { + [AKS] + [Redis] + [Postgres] + [AzurePrivateStorage] + AKS --> Redis : "TLS:6379" + AKS --> Postgres : "TLS:5432" + AKS --> AzurePrivateStorage : "HTTPS/443" + [ALB] --> AKS : "HTTPS:443" + note as private_useast + 10.2.2.0/24 + end note + } + } +} + +frame "USEAST Primary Region " as primary_region{ + component "Postgres" as pgbackup + [Postgres] --> pgbackup : "Private Peering / TLS:5432" +} + +note right of [ALB] : Azure Load Balancer restricted to AKS only +@enduml From d4641714616e947e3842b896023dfe13ba327d9a Mon Sep 17 00:00:00 2001 From: "Jay R. Newlin (PromptWorks)" Date: Wed, 18 Dec 2019 11:12:30 -0500 Subject: [PATCH 025/114] New test for Application Index page --- uitests/Application_Index_with_App.html | 761 ++++++++++++++++++++++++ 1 file changed, 761 insertions(+) create mode 100644 uitests/Application_Index_with_App.html diff --git a/uitests/Application_Index_with_App.html b/uitests/Application_Index_with_App.html new file mode 100644 index 00000000..67f34a53 --- /dev/null +++ b/uitests/Application_Index_with_App.html @@ -0,0 +1,761 @@ + + + + + + +Application Index with App + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Application Index with App
waitForPageToLoad
open/login-dev?username=brandon
waitForPageToLoad
waitForElementPresentcss=a[href="/user"] > .topbar__link-label
assertTextcss=a[href="/user"] > .topbar__link-label*Brandon Buchannan*
waitForPageToLoad
waitForElementPresentcss=a[href="/logout"] > .topbar__link-label
clickcss=a[href="/logout"] > .topbar__link-label
waitForPageToLoad
waitForElementPresentcss=.col > .usa-alert.usa-alert-info:nth-of-type(2) > .usa-alert-body > h3.usa-alert-heading
assertTextcss=.col > .usa-alert.usa-alert-info:nth-of-type(2) > .usa-alert-body > h3.usa-alert-heading*Logged out*
waitForPageToLoad
open/login-dev
waitForPageToLoad
waitForElementPresentcss=.about-cloud > h1
assertTextcss=.about-cloud > h1About Cloud Services
waitForPageToLoad
waitForElementPresentcss=a[href="/portfolios/new"]
clickcss=a[href="/portfolios/new"]
waitForPageToLoad
waitForElementPresentcss=.portfolio-header__name > h1
assertTextcss=.portfolio-header__name > h1*New Portfolio*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Create New Portfolio*
waitForPageToLoad
waitForElementPresentcss=#name
typecss=#nameTatooine Energy Maintenance Systems
waitForPageToLoad
waitForElementPresentcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.empty-state > h3
assertTextcss=.empty-state > h3*You don't have any Applications yet*
waitForPageToLoad
waitForElementPresentcss=.usa-button.usa-button-primary
clickcss=.usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=#name
typecss=#nameStarter Application
waitForPageToLoad
waitForElementPresentcss=button[type="submit"]
clickcss=button[type="submit"]
waitForPageToLoad
waitForElementPresentcss=button[type="submit"]
clickcss=button[type="submit"]
waitForPageToLoad
waitForElementPresentcss=a.usa-button.usa-button-secondary.add-new-button
clickcss=a.usa-button.usa-button-secondary.add-new-button
waitForPageToLoad
waitForElementPresentcss=#user_data-first_name
typecss=#user_data-first_nameBrandon
waitForPageToLoad
waitForElementPresentcss=#user_data-last_name
typecss=#user_data-last_nameBuchannan
waitForPageToLoad
waitForElementPresentcss=#user_data-email
typecss=#user_data-emailjay+brandon@promptworks.com
waitForPageToLoad
waitForElementPresentcss=#user_data-dod_id
typecss=#user_data-dod_id3456789012
waitForPageToLoad
waitForElementPresentcss=#add-app-mem > div > div:nth-of-type(1) > .action-group > input[type="button"].action-group__action.usa-button
clickcss=#add-app-mem > div > div:nth-of-type(1) > .action-group > input[type="button"].action-group__action.usa-button
waitForPageToLoad
waitForElementPresentcss=.application-perms > div:nth-of-type(1) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
clickcss=.application-perms > div:nth-of-type(1) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
waitForPageToLoad
waitForElementPresentcss=.application-perms > div:nth-of-type(2) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
clickcss=.application-perms > div:nth-of-type(2) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
waitForPageToLoad
waitForElementPresentcss=.application-perms > div:nth-of-type(3) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
clickcss=.application-perms > div:nth-of-type(3) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
waitForPageToLoad
waitForElementPresentcss=#environment_roles-0-role-None
typecss=#environment_roles-0-role-NoneBasic Access
waitForPageToLoad
waitForElementPresentcss=#environment_roles-1-role-None
typecss=#environment_roles-1-role-NoneNetwork Admin
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=span.action-group-footer > a.usa-button
clickcss=span.action-group-footer > a.usa-button
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Starter Application*
waitForPageToLoad
waitForElementPresentcss=.label
assertTextcss=.label*INVITE PENDING*
waitForPageToLoad
waitForElementPresentcss=.accordion-table__items > .accordion-table__item:nth-of-type(1) > .accordion-table__item-content > .environment-list__item > .label.label--below
assertElementPresentcss=.accordion-table__items > .accordion-table__item:nth-of-type(1) > .accordion-table__item-content > .environment-list__item > .label.label--below
waitForPageToLoad
waitForElementPresentcss=#delete-application
assertTextcss=#delete-application*Delete application*
waitForPageToLoad
waitForElementPresentcss=.icon--applications
clickcss=.icon--applications
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Applications*
waitForPageToLoad
waitForElementPresentcss=.accordion-list
assertElementPresentcss=.accordion-list
waitForPageToLoad
waitForElementPresentcss=button.usa-accordion-button
clickcss=button.usa-accordion-button
waitForPageToLoad
waitForElementPresentcss=.usa-accordion-content > .accordion__content--list-item:nth-of-type(1) > .row > .col.col--grow
assertTextcss=.usa-accordion-content > .accordion__content--list-item:nth-of-type(1) > .row > .col.col--grow*Development*
waitForPageToLoad
waitForElementPresentcss=.usa-accordion-content > .accordion__content--list-item:nth-of-type(2) > .row > .col.col--grow
assertTextcss=.usa-accordion-content > .accordion__content--list-item:nth-of-type(2) > .row > .col.col--grow*Production*
waitForPageToLoad
waitForElementPresentcss=.usa-accordion-content > .accordion__content--list-item:nth-of-type(3) > .row > .col.col--grow
assertTextcss=.usa-accordion-content > .accordion__content--list-item:nth-of-type(3) > .row > .col.col--grow*Staging*
waitForPageToLoad
waitForElementPresentcss=.usa-accordion-content > .accordion__content--list-item:nth-of-type(4) > .row > .col.col--grow
assertTextcss=.usa-accordion-content > .accordion__content--list-item:nth-of-type(4) > .row > .col.col--grow*Testing*
waitForPageToLoad
waitForElementPresentcss=button.usa-accordion-button
clickcss=button.usa-accordion-button
waitForPageToLoad
waitForElementPresentcss=button.usa-accordion-button
clickcss=button.usa-accordion-button
waitForPageToLoad
waitForElementPresentcss=a.accordion-list__collapse
clickcss=a.accordion-list__collapse
waitForPageToLoad
waitForElementPresentcss=button.usa-accordion-button
clickcss=button.usa-accordion-button
+ + \ No newline at end of file From 2690416707824775724892a9f2064170161aebd4 Mon Sep 17 00:00:00 2001 From: "Jay R. Newlin (PromptWorks)" Date: Wed, 18 Dec 2019 11:13:35 -0500 Subject: [PATCH 026/114] Test renamed and adjusted for new functionality --- uitests/Reports_-_Basics.html | 744 ++++++++++++++++++++++++++++++++++ 1 file changed, 744 insertions(+) create mode 100644 uitests/Reports_-_Basics.html diff --git a/uitests/Reports_-_Basics.html b/uitests/Reports_-_Basics.html new file mode 100644 index 00000000..5f1d9eda --- /dev/null +++ b/uitests/Reports_-_Basics.html @@ -0,0 +1,744 @@ + + + + + + +Reports - Basics + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Reports - Basics
waitForPageToLoad
open/login-dev
waitForPageToLoad
waitForElementPresentcss=.about-cloud > h1
assertTextcss=.about-cloud > h1About Cloud Services
waitForPageToLoad
waitForElementPresentcss=a[href="/portfolios/new"]
clickcss=a[href="/portfolios/new"]
waitForPageToLoad
waitForElementPresentcss=.portfolio-header__name > h1
assertTextcss=.portfolio-header__name > h1*New Portfolio*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Create New Portfolio*
waitForPageToLoad
waitForElementPresentcss=#name
typecss=#nameTatooine Energy Maintenance Systems
waitForPageToLoad
waitForElementPresentcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.empty-state > h3
assertTextcss=.empty-state > h3*You don't have any Applications yet*
waitForPageToLoad
waitForElementPresentcss=.icon--funding
clickcss=.icon--funding
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-buttons > .usa-button.usa-button-primary
clickcss=.sticky-cta-buttons > .usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=.upload-button
clickcss=.upload-button
waitForPageToLoad
waitForElementPresentcss=#pdf
typecss=#pdfhttps://ghostinspector-prod.s3.amazonaws.com/uploads/310638bb-42fd-4158-b14f-417826ae4f79.pdf
waitForPageToLoad
assertElementNotPresentcss=input[type="submit"][disabled="disabled"]
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=#number
typecss=#number${timestamp}
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=#clins-0-number
typecss=#clins-0-number0002
waitForPageToLoad
waitForElementPresentcss=#clins-0-jedi_clin_type
typecss=#clins-0-jedi_clin_typeJEDI_CLIN_2
waitForPageToLoad
waitForElementPresentcss=#clins-0-total_amount
typecss=#clins-0-total_amount$800,000
waitForPageToLoad
waitForElementPresentcss=#clins-0-obligated_amount
typecss=#clins-0-obligated_amount$100,000
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]10
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]1
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]2019
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]6
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]30
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]2020
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
clickcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=a.usa-button.usa-button-primary
clickcss=a.usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=fieldset.usa-input__choices > legend > label
clickcss=fieldset.usa-input__choices > legend > label
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=h3.usa-alert-heading
assertTextcss=h3.usa-alert-heading*Your Task Order has been uploaded successfully.*
waitForPageToLoad
waitForElementPresentcss=.icon.icon--chart-pie
clickcss=.icon.icon--chart-pie
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Reports*
waitForPageToLoad
waitForElementPresentcss=.row > .col.col--grow.reporting-summary-item:nth-of-type(1) > .reporting-summary-item__value
assertTextcss=.row > .col.col--grow.reporting-summary-item:nth-of-type(1) > .reporting-summary-item__value*$100,000.00*
waitForPageToLoad
waitForElementPresentcss=.row > .col.col--grow.reporting-summary-item:nth-of-type(2) > .reporting-summary-item__value
assertTextcss=.row > .col.col--grow.reporting-summary-item:nth-of-type(2) > .reporting-summary-item__value*October 01, 2019 + - + June 30, 2020*
waitForPageToLoad
waitForElementPresentcss=.row > .col.col--grow.reporting-summary-item:nth-of-type(3) > h5.reporting-summary-item__header > .reporting-summary-item__header-text
assertTextcss=.row > .col.col--grow.reporting-summary-item:nth-of-type(3) > h5.reporting-summary-item__header > .reporting-summary-item__header-text*Days Remaining*
waitForPageToLoad
waitForElementPresentcss=h3.h5
assertTextcss=h3.h5*IDIQ CLIN 0002 Classified IaaS/PaaS*
waitForPageToLoad
waitForElementPresentcss=.jedi-clin-funding__subheader
assertTextcss=.jedi-clin-funding__subheader*Total obligated amount: $100,000.00*
waitForPageToLoad
waitForElementPresentcss=.jedi-clin-funding__graph-values
assertElementPresentcss=.jedi-clin-funding__graph-values
waitForPageToLoad
waitForElementPresentcss=.jedi-clin-funding__graph-values > .jedi-clin-funding__meta:nth-of-type(3) > .h3.jedi-clin-funding__meta-value
assertTextcss=.jedi-clin-funding__graph-values > .jedi-clin-funding__meta:nth-of-type(3) > .h3.jedi-clin-funding__meta-value*$100,000.00*
waitForPageToLoad
waitForElementPresentcss=h3.h4
assertTextcss=h3.h4*Active Task Orders*
waitForPageToLoad
waitForElementPresentcss=.jedi-clin-funding__active-task-orders
assertElementPresentcss=.jedi-clin-funding__active-task-orders
waitForPageToLoad
waitForElementPresentcss=button.usa-accordion-button
clickcss=button.usa-accordion-button
+ + \ No newline at end of file From 0698bacc126ef0c3d526e838538dbcdd922d56d3 Mon Sep 17 00:00:00 2001 From: "Jay R. Newlin (PromptWorks)" Date: Wed, 18 Dec 2019 11:15:03 -0500 Subject: [PATCH 027/114] New tests for added Reporting functionality --- uitests/Reports_-_Empty_State.html | 248 +++ ...orts_-_with_TO,_App,_and_Environments.html | 1006 ++++++++++ uitests/Reports_-_with_expired_TO.html | 1614 +++++++++++++++++ 3 files changed, 2868 insertions(+) create mode 100644 uitests/Reports_-_Empty_State.html create mode 100644 uitests/Reports_-_with_TO,_App,_and_Environments.html create mode 100644 uitests/Reports_-_with_expired_TO.html diff --git a/uitests/Reports_-_Empty_State.html b/uitests/Reports_-_Empty_State.html new file mode 100644 index 00000000..602407d8 --- /dev/null +++ b/uitests/Reports_-_Empty_State.html @@ -0,0 +1,248 @@ + + + + + + +Reports - Empty State + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Reports - Empty State
waitForPageToLoad
open/login-dev
waitForPageToLoad
waitForElementPresentcss=.about-cloud > h1
assertTextcss=.about-cloud > h1About Cloud Services
waitForPageToLoad
waitForElementPresentcss=a[href="/portfolios/new"]
clickcss=a[href="/portfolios/new"]
waitForPageToLoad
waitForElementPresentcss=.portfolio-header__name > h1
assertTextcss=.portfolio-header__name > h1*New Portfolio*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Create New Portfolio*
waitForPageToLoad
waitForElementPresentcss=#name
typecss=#nameTatooine Energy Maintenance Systems
waitForPageToLoad
waitForElementPresentcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.empty-state > h3
assertTextcss=.empty-state > h3*You don't have any Applications yet*
waitForPageToLoad
waitForElementPresentcss=.icon--chart-pie
clickcss=.icon--chart-pie
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Reports*
waitForPageToLoad
waitForElementPresentcss=button.usa-accordion-button
clickcss=button.usa-accordion-button
waitForPageToLoad
waitForElementPresentcss=.row > .col.col--grow.reporting-summary-item:nth-of-type(1) > .reporting-summary-item__value
assertTextcss=.row > .col.col--grow.reporting-summary-item:nth-of-type(1) > .reporting-summary-item__value*$0.00*
waitForPageToLoad
waitForElementPresentcss=.row > .col.col--grow.reporting-summary-item:nth-of-type(3) > .reporting-summary-item__value
assertTextcss=.row > .col.col--grow.reporting-summary-item:nth-of-type(3) > .reporting-summary-item__value*0 days*
+ + \ No newline at end of file diff --git a/uitests/Reports_-_with_TO,_App,_and_Environments.html b/uitests/Reports_-_with_TO,_App,_and_Environments.html new file mode 100644 index 00000000..5fa2f879 --- /dev/null +++ b/uitests/Reports_-_with_TO,_App,_and_Environments.html @@ -0,0 +1,1006 @@ + + + + + + +Reports - with TO, App, and Environments + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Reports - with TO, App, and Environments
waitForPageToLoad
open/login-dev?username=brandon
waitForPageToLoad
waitForElementPresentcss=a[href="/user"] > .topbar__link-label
assertTextcss=a[href="/user"] > .topbar__link-label*Brandon Buchannan*
waitForPageToLoad
waitForElementPresentcss=a[href="/logout"] > .topbar__link-label
clickcss=a[href="/logout"] > .topbar__link-label
waitForPageToLoad
waitForElementPresentcss=.col > .usa-alert.usa-alert-info:nth-of-type(2) > .usa-alert-body > h3.usa-alert-heading
assertTextcss=.col > .usa-alert.usa-alert-info:nth-of-type(2) > .usa-alert-body > h3.usa-alert-heading*Logged out*
waitForPageToLoad
open/login-dev
waitForPageToLoad
waitForElementPresentcss=.about-cloud > h1
assertTextcss=.about-cloud > h1About Cloud Services
waitForPageToLoad
waitForElementPresentcss=a[href="/portfolios/new"]
clickcss=a[href="/portfolios/new"]
waitForPageToLoad
waitForElementPresentcss=.portfolio-header__name > h1
assertTextcss=.portfolio-header__name > h1*New Portfolio*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Create New Portfolio*
waitForPageToLoad
waitForElementPresentcss=#name
typecss=#nameTatooine Energy Maintenance Systems
waitForPageToLoad
waitForElementPresentcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.empty-state > h3
assertTextcss=.empty-state > h3*You don't have any Applications yet*
waitForPageToLoad
waitForElementPresentcss=.usa-button.usa-button-primary
clickcss=.usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=#name
typecss=#nameStarter Application
waitForPageToLoad
waitForElementPresentcss=button[type="submit"]
clickcss=button[type="submit"]
waitForPageToLoad
waitForElementPresentcss=button[type="submit"]
clickcss=button[type="submit"]
waitForPageToLoad
waitForElementPresentcss=a.usa-button.usa-button-secondary.add-new-button
clickcss=a.usa-button.usa-button-secondary.add-new-button
waitForPageToLoad
waitForElementPresentcss=#user_data-first_name
typecss=#user_data-first_nameBrandon
waitForPageToLoad
waitForElementPresentcss=#user_data-last_name
typecss=#user_data-last_nameBuchannan
waitForPageToLoad
waitForElementPresentcss=#user_data-email
typecss=#user_data-emailjay+brandon@promptworks.com
waitForPageToLoad
waitForElementPresentcss=#user_data-dod_id
typecss=#user_data-dod_id3456789012
waitForPageToLoad
waitForElementPresentcss=#add-app-mem > div > div:nth-of-type(1) > .action-group > input[type="button"].action-group__action.usa-button
clickcss=#add-app-mem > div > div:nth-of-type(1) > .action-group > input[type="button"].action-group__action.usa-button
waitForPageToLoad
waitForElementPresentcss=.application-perms > div:nth-of-type(1) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
clickcss=.application-perms > div:nth-of-type(1) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
waitForPageToLoad
waitForElementPresentcss=.application-perms > div:nth-of-type(2) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
clickcss=.application-perms > div:nth-of-type(2) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
waitForPageToLoad
waitForElementPresentcss=.application-perms > div:nth-of-type(3) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
clickcss=.application-perms > div:nth-of-type(3) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
waitForPageToLoad
waitForElementPresentcss=#environment_roles-0-role-None
typecss=#environment_roles-0-role-NoneBasic Access
waitForPageToLoad
waitForElementPresentcss=#environment_roles-1-role-None
typecss=#environment_roles-1-role-NoneNetwork Admin
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=span.action-group-footer > a.usa-button
clickcss=span.action-group-footer > a.usa-button
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Starter Application*
waitForPageToLoad
waitForElementPresentcss=.label
assertTextcss=.label*INVITE PENDING*
waitForPageToLoad
waitForElementPresentcss=.accordion-table__items > .accordion-table__item:nth-of-type(1) > .accordion-table__item-content > .environment-list__item > .label.label--below
assertElementPresentcss=.accordion-table__items > .accordion-table__item:nth-of-type(1) > .accordion-table__item-content > .environment-list__item > .label.label--below
waitForPageToLoad
waitForElementPresentcss=#delete-application
assertTextcss=#delete-application*Delete application*
waitForPageToLoad
waitForElementPresentcss=.icon--funding
clickcss=.icon--funding
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-buttons > .usa-button.usa-button-primary
clickcss=.sticky-cta-buttons > .usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=.upload-button
clickcss=.upload-button
waitForPageToLoad
waitForElementPresentcss=#pdf
typecss=#pdfhttps://ghostinspector-prod.s3.amazonaws.com/uploads/310638bb-42fd-4158-b14f-417826ae4f79.pdf
waitForPageToLoad
assertElementNotPresentcss=input[type="submit"][disabled="disabled"]
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=#number
typecss=#number${timestamp}
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=#clins-0-number
typecss=#clins-0-number0002
waitForPageToLoad
waitForElementPresentcss=#clins-0-jedi_clin_type
typecss=#clins-0-jedi_clin_typeJEDI_CLIN_2
waitForPageToLoad
waitForElementPresentcss=#clins-0-total_amount
typecss=#clins-0-total_amount$800,000
waitForPageToLoad
waitForElementPresentcss=#clins-0-obligated_amount
typecss=#clins-0-obligated_amount$100,000
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]10
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]1
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]2019
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]6
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]30
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]2020
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
clickcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=a.usa-button.usa-button-primary
clickcss=a.usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=fieldset.usa-input__choices > legend > label
clickcss=fieldset.usa-input__choices > legend > label
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=h3.usa-alert-heading
assertTextcss=h3.usa-alert-heading*Your Task Order has been uploaded successfully.*
waitForPageToLoad
waitForElementPresentcss=.icon.icon--chart-pie
clickcss=.icon.icon--chart-pie
waitForPageToLoad
waitForElementPresentcss=button.usa-accordion-button
clickcss=button.usa-accordion-button
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Reports*
+ + \ No newline at end of file diff --git a/uitests/Reports_-_with_expired_TO.html b/uitests/Reports_-_with_expired_TO.html new file mode 100644 index 00000000..34eff04b --- /dev/null +++ b/uitests/Reports_-_with_expired_TO.html @@ -0,0 +1,1614 @@ + + + + + + +Reports - with expired TO + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Reports - with expired TO
waitForPageToLoad
open/login-dev?username=brandon
waitForPageToLoad
waitForElementPresentcss=a[href="/user"] > .topbar__link-label
assertTextcss=a[href="/user"] > .topbar__link-label*Brandon Buchannan*
waitForPageToLoad
waitForElementPresentcss=a[href="/logout"] > .topbar__link-label
clickcss=a[href="/logout"] > .topbar__link-label
waitForPageToLoad
waitForElementPresentcss=.col > .usa-alert.usa-alert-info:nth-of-type(2) > .usa-alert-body > h3.usa-alert-heading
assertTextcss=.col > .usa-alert.usa-alert-info:nth-of-type(2) > .usa-alert-body > h3.usa-alert-heading*Logged out*
waitForPageToLoad
open/login-dev
waitForPageToLoad
waitForElementPresentcss=.about-cloud > h1
assertTextcss=.about-cloud > h1About Cloud Services
waitForPageToLoad
waitForElementPresentcss=a[href="/portfolios/new"]
clickcss=a[href="/portfolios/new"]
waitForPageToLoad
waitForElementPresentcss=.portfolio-header__name > h1
assertTextcss=.portfolio-header__name > h1*New Portfolio*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Create New Portfolio*
waitForPageToLoad
waitForElementPresentcss=#name
typecss=#nameTatooine Energy Maintenance Systems
waitForPageToLoad
waitForElementPresentcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.empty-state > h3
assertTextcss=.empty-state > h3*You don't have any Applications yet*
waitForPageToLoad
waitForElementPresentcss=.usa-button.usa-button-primary
clickcss=.usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=#name
typecss=#nameStarter Application
waitForPageToLoad
waitForElementPresentcss=button[type="submit"]
clickcss=button[type="submit"]
waitForPageToLoad
waitForElementPresentcss=button[type="submit"]
clickcss=button[type="submit"]
waitForPageToLoad
waitForElementPresentcss=a.usa-button.usa-button-secondary.add-new-button
clickcss=a.usa-button.usa-button-secondary.add-new-button
waitForPageToLoad
waitForElementPresentcss=#user_data-first_name
typecss=#user_data-first_nameBrandon
waitForPageToLoad
waitForElementPresentcss=#user_data-last_name
typecss=#user_data-last_nameBuchannan
waitForPageToLoad
waitForElementPresentcss=#user_data-email
typecss=#user_data-emailjay+brandon@promptworks.com
waitForPageToLoad
waitForElementPresentcss=#user_data-dod_id
typecss=#user_data-dod_id3456789012
waitForPageToLoad
waitForElementPresentcss=#add-app-mem > div > div:nth-of-type(1) > .action-group > input[type="button"].action-group__action.usa-button
clickcss=#add-app-mem > div > div:nth-of-type(1) > .action-group > input[type="button"].action-group__action.usa-button
waitForPageToLoad
waitForElementPresentcss=.application-perms > div:nth-of-type(1) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
clickcss=.application-perms > div:nth-of-type(1) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
waitForPageToLoad
waitForElementPresentcss=.application-perms > div:nth-of-type(2) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
clickcss=.application-perms > div:nth-of-type(2) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
waitForPageToLoad
waitForElementPresentcss=.application-perms > div:nth-of-type(3) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
clickcss=.application-perms > div:nth-of-type(3) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
waitForPageToLoad
waitForElementPresentcss=#environment_roles-0-role-None
typecss=#environment_roles-0-role-NoneBasic Access
waitForPageToLoad
waitForElementPresentcss=#environment_roles-1-role-None
typecss=#environment_roles-1-role-NoneNetwork Admin
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=span.action-group-footer > a.usa-button
clickcss=span.action-group-footer > a.usa-button
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Starter Application*
waitForPageToLoad
waitForElementPresentcss=.label
assertTextcss=.label*INVITE PENDING*
waitForPageToLoad
waitForElementPresentcss=.accordion-table__items > .accordion-table__item:nth-of-type(1) > .accordion-table__item-content > .environment-list__item > .label.label--below
assertElementPresentcss=.accordion-table__items > .accordion-table__item:nth-of-type(1) > .accordion-table__item-content > .environment-list__item > .label.label--below
waitForPageToLoad
waitForElementPresentcss=#delete-application
assertTextcss=#delete-application*Delete application*
waitForPageToLoad
waitForElementPresentcss=.icon--funding
clickcss=.icon--funding
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-buttons > .usa-button.usa-button-primary
clickcss=.sticky-cta-buttons > .usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=.upload-button
clickcss=.upload-button
waitForPageToLoad
waitForElementPresentcss=#pdf
typecss=#pdfhttps://ghostinspector-prod.s3.amazonaws.com/uploads/310638bb-42fd-4158-b14f-417826ae4f79.pdf
waitForPageToLoad
assertElementNotPresentcss=input[type="submit"][disabled="disabled"]
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=#number
typecss=#number${timestamp}
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=#clins-0-number
typecss=#clins-0-number0002
waitForPageToLoad
waitForElementPresentcss=#clins-0-jedi_clin_type
typecss=#clins-0-jedi_clin_typeJEDI_CLIN_2
waitForPageToLoad
waitForElementPresentcss=#clins-0-total_amount
typecss=#clins-0-total_amount$800,000
waitForPageToLoad
waitForElementPresentcss=#clins-0-obligated_amount
typecss=#clins-0-obligated_amount$100,000
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]10
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]1
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]2019
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]6
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]30
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]2020
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
clickcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=a.usa-button.usa-button-primary
clickcss=a.usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=fieldset.usa-input__choices > legend > label
clickcss=fieldset.usa-input__choices > legend > label
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=h3.usa-alert-heading
assertTextcss=h3.usa-alert-heading*Your Task Order has been uploaded successfully.*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-buttons > .usa-button.usa-button-primary
clickcss=.sticky-cta-buttons > .usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=.upload-button
clickcss=.upload-button
waitForPageToLoad
waitForElementPresentcss=#pdf
typecss=#pdfhttps://ghostinspector-prod.s3.amazonaws.com/uploads/310638bb-42fd-4158-b14f-417826ae4f79.pdf
waitForPageToLoad
assertElementNotPresentcss=input[type="submit"][disabled="disabled"]
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=#number
typecss=#number${timestamp}
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=#clins-0-number
typecss=#clins-0-number0001
waitForPageToLoad
waitForElementPresentcss=#clins-0-jedi_clin_type
typecss=#clins-0-jedi_clin_typeJEDI_CLIN_1
waitForPageToLoad
waitForElementPresentcss=#clins-0-total_amount
typecss=#clins-0-total_amount$40,000
waitForPageToLoad
waitForElementPresentcss=#clins-0-obligated_amount
typecss=#clins-0-obligated_amount$8,000
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]10
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]1
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]
typecss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]2019
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]10
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]31
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]
typecss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]2019
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
clickcss=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=a.usa-button.usa-button-primary
clickcss=a.usa-button.usa-button-primary
waitForPageToLoad
waitForElementPresentcss=fieldset.usa-input__choices > legend > label
clickcss=fieldset.usa-input__choices > legend > label
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=h3.usa-alert-heading
assertTextcss=h3.usa-alert-heading*Your Task Order has been uploaded successfully.*
waitForPageToLoad
waitForElementPresentcss=.icon.icon--chart-pie
clickcss=.icon.icon--chart-pie
waitForPageToLoad
waitForElementPresentcss=button.usa-accordion-button
clickcss=button.usa-accordion-button
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Reports*
waitForPageToLoad
waitForElementPresentcss=.row > .col.col--grow.reporting-summary-item:nth-of-type(1) > .reporting-summary-item__value
assertTextcss=.row > .col.col--grow.reporting-summary-item:nth-of-type(1) > .reporting-summary-item__value*$100,000.00*
waitForPageToLoad
waitForElementPresentcss=.row > .col.col--grow.reporting-summary-item:nth-of-type(2) > .reporting-summary-item__value
assertTextcss=.row > .col.col--grow.reporting-summary-item:nth-of-type(2) > .reporting-summary-item__value*October 01, 2019 + - + June 30, 2020*
waitForPageToLoad
waitForElementPresentcss=h3.h5
assertTextcss=h3.h5*IDIQ CLIN 0002 Classified IaaS/PaaS*
waitForPageToLoad
waitForElementPresentcss=.jedi-clin-funding__subheader
assertTextcss=.jedi-clin-funding__subheader*Total obligated amount: $100,000.00*
waitForPageToLoad
waitForElementPresentcss=.jedi-clin-funding__graph-values > .jedi-clin-funding__meta:nth-of-type(3) > .h3.jedi-clin-funding__meta-value
assertTextcss=.jedi-clin-funding__graph-values > .jedi-clin-funding__meta:nth-of-type(3) > .h3.jedi-clin-funding__meta-value*$100,000.00*
waitForPageToLoad
waitForElementPresentcss=#expired_funding > tbody > tr:nth-of-type(1) > td
assertElementPresentcss=#expired_funding > tbody > tr:nth-of-type(1) > td
waitForPageToLoad
waitForElementPresentcss=#expired_funding > tbody > tr:nth-of-type(2) > td:nth-of-type(1)
assertElementPresentcss=#expired_funding > tbody > tr:nth-of-type(2) > td:nth-of-type(1)
waitForPageToLoad
waitForElementPresentcss=#expired_funding > tbody > tr:nth-of-type(2) > td:nth-of-type(2)
assertElementPresentcss=#expired_funding > tbody > tr:nth-of-type(2) > td:nth-of-type(2)
waitForPageToLoad
waitForElementPresentcss=#expired_funding > tbody > tr:nth-of-type(2) > td:nth-of-type(2)
assertTextcss=#expired_funding > tbody > tr:nth-of-type(2) > td:nth-of-type(2)*Oct 01, 2019 + - + Oct 31, 2019*
waitForPageToLoad
waitForElementPresentcss=#expired_funding > tbody > tr:nth-of-type(2) > td:nth-of-type(3)
assertElementPresentcss=#expired_funding > tbody > tr:nth-of-type(2) > td:nth-of-type(3)
waitForPageToLoad
waitForElementPresentcss=#expired_funding > tbody > tr:nth-of-type(2) > td:nth-of-type(3)
assertTextcss=#expired_funding > tbody > tr:nth-of-type(2) > td:nth-of-type(3)*$40,000.00*
waitForPageToLoad
waitForElementPresentcss=#expired_funding > tbody > tr:nth-of-type(2) > td:nth-of-type(4)
assertElementPresentcss=#expired_funding > tbody > tr:nth-of-type(2) > td:nth-of-type(4)
waitForPageToLoad
waitForElementPresentcss=#expired_funding > tbody > tr:nth-of-type(2) > td:nth-of-type(4)
assertTextcss=#expired_funding > tbody > tr:nth-of-type(2) > td:nth-of-type(4)*$8,000.00*
waitForPageToLoad
waitForElementPresentcss=#expired_funding > tbody > tr:nth-of-type(2) > td:nth-of-type(5)
assertElementPresentcss=#expired_funding > tbody > tr:nth-of-type(2) > td:nth-of-type(5)
waitForPageToLoad
waitForElementPresentcss=#expired_funding > tbody > tr:nth-of-type(2) > td:nth-of-type(1) > .h4.reporting-expended-funding__header
assertTextcss=#expired_funding > tbody > tr:nth-of-type(2) > td:nth-of-type(1) > .h4.reporting-expended-funding__header*0001*
waitForPageToLoad
waitForElementPresentcss=#expired_funding > tbody > tr:nth-of-type(2) > td:nth-of-type(1) > div:nth-of-type(2)
assertTextcss=#expired_funding > tbody > tr:nth-of-type(2) > td:nth-of-type(1) > div:nth-of-type(2)*Unclassified IaaS/PaaS*
+ + \ No newline at end of file From fac58391d1b58e921036f9cf2c37c7e61d39f0d0 Mon Sep 17 00:00:00 2001 From: "Jay R. Newlin (PromptWorks)" Date: Wed, 18 Dec 2019 11:17:44 -0500 Subject: [PATCH 028/114] Tests updated to account for new designs --- uitests/New_Portfolio.html | 258 ++++----------------- uitests/TO_Step_1.html | 280 ++++------------------- uitests/TO_Step_2.html | 302 ++++--------------------- uitests/TO_Step_3.html | 324 +++++--------------------- uitests/TO_Step_3_-_Add_CLIN.html | 340 +++++----------------------- uitests/TO_Step_4.html | 346 +++++----------------------- uitests/TO_Step_5.html | 362 +++++------------------------- 7 files changed, 362 insertions(+), 1850 deletions(-) diff --git a/uitests/New_Portfolio.html b/uitests/New_Portfolio.html index 356cb2b3..5495828f 100644 --- a/uitests/New_Portfolio.html +++ b/uitests/New_Portfolio.html @@ -16,7 +16,7 @@ - + @@ -63,7 +63,7 @@ - + @@ -75,13 +75,28 @@ - + - - + + + + + + + + + + + + + + + + + @@ -105,177 +120,12 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -289,53 +139,23 @@ + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/uitests/TO_Step_1.html b/uitests/TO_Step_1.html index f8536744..217798ca 100644 --- a/uitests/TO_Step_1.html +++ b/uitests/TO_Step_1.html @@ -16,7 +16,7 @@ - +
css=a[href="/portfolios/new"]
click css=a[href="/portfolios/new"]
waitForElementPresentcss=main.usa-section > h1css=.portfolio-header__name > h1
assertTextcss=main.usa-section > h1*New Portfolio Form*css=.portfolio-header__name > h1*New Portfolio*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Create New Portfolio*
waitForPageToLoad
waitForElementPresentcss=#defense_componentcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
typecss=#defense_componentDefense Logistics Agency
waitForPageToLoad
waitForElementPresentcss=#description
typecss=#descriptionMaintenance and monitoring of the energy grid
waitForPageToLoad
waitForElementPresentcss=#app_migration > li:nth-of-type(3) > label
clickcss=#app_migration > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#native_apps > li:nth-of-type(1) > label
clickcss=#native_apps > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#team_experience > li:nth-of-type(5) > label
clickcss=#team_experience > li:nth-of-type(5) > labelcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.empty-state > h3
assertTextcss=input[type="submit"]Save
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.portfolio-header__name > h1
assertTextcss=.portfolio-header__name > h1*Tatooine Energy Maintenance Systems*
waitForPageToLoad
waitForElementPresentcss=.empty-state h3
assertTextcss=.empty-state h3css=.empty-state > h3 *You don't have any Applications yet*
@@ -66,7 +66,7 @@ Imported from: AT-AT CI - login--> - + @@ -79,13 +79,29 @@ Imported from: AT-AT CI - login--> - + - - + + + + + + + + + + + + + + + + + + @@ -111,188 +127,12 @@ Imported from: AT-AT CI - login--> - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -307,56 +147,24 @@ Imported from: AT-AT CI - login--> + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -411,13 +219,13 @@ Imported from: AT-AT CI - login--> - + - - + + diff --git a/uitests/TO_Step_2.html b/uitests/TO_Step_2.html index 4dd7f908..980b2628 100644 --- a/uitests/TO_Step_2.html +++ b/uitests/TO_Step_2.html @@ -16,7 +16,7 @@ - +
css=a[href="/portfolios/new"]
click css=a[href="/portfolios/new"]
waitForElementPresentcss=main.usa-section > h1css=.portfolio-header__name > h1
assertTextcss=main.usa-section > h1*New Portfolio Form*css=.portfolio-header__name > h1*New Portfolio*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Create New Portfolio*
waitForPageToLoad
waitForElementPresentcss=#defense_componentcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
typecss=#defense_componentDefense Logistics Agency
waitForPageToLoad
waitForElementPresentcss=#description
typecss=#descriptionMaintenance and monitoring of the energy grid
waitForPageToLoad
waitForElementPresentcss=#app_migration > li:nth-of-type(3) > label
clickcss=#app_migration > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#native_apps > li:nth-of-type(1) > label
clickcss=#native_apps > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#team_experience > li:nth-of-type(5) > label
clickcss=#team_experience > li:nth-of-type(5) > labelcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.empty-state > h3
assertTextcss=input[type="submit"]Save
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.portfolio-header__name > h1
assertTextcss=.portfolio-header__name > h1*Tatooine Energy Maintenance Systems*
waitForPageToLoad
waitForElementPresentcss=.empty-state h3
assertTextcss=.empty-state h3css=.empty-state > h3 *You don't have any Applications yet*
waitForElementPresentcss=.sticky-cta-text > h3css=.sticky-cta-context
assertTextcss=.sticky-cta-text > h3*Add Task Order (step 1 of 5)*css=.sticky-cta-context*Step 1 of 5*
waitForPageToLoad
@@ -69,7 +69,7 @@ Imported from: AT-AT CI - New Portfolio--> - + @@ -83,13 +83,30 @@ Imported from: AT-AT CI - New Portfolio--> Imported from: AT-AT CI - New Portfolio--> - + - - + + + + + + + + + + + + + + + + + + @@ -117,199 +134,12 @@ Imported from: AT-AT CI - New Portfolio--> Imported from: AT-AT CI - New Portfolio--> - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -325,59 +155,25 @@ Imported from: AT-AT CI - New Portfolio--> + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -436,13 +232,13 @@ Imported from: AT-AT CI - New Portfolio--> - + - - + + @@ -526,13 +322,13 @@ This is Ghost Inspector flow control. The test will wait until the file is uploa - + - - + + diff --git a/uitests/TO_Step_3.html b/uitests/TO_Step_3.html index 08a12033..6467b614 100644 --- a/uitests/TO_Step_3.html +++ b/uitests/TO_Step_3.html @@ -16,7 +16,7 @@ - +
css=a[href="/portfolios/new"]
click css=a[href="/portfolios/new"]
waitForElementPresentcss=main.usa-section > h1css=.portfolio-header__name > h1
assertTextcss=main.usa-section > h1*New Portfolio Form*css=.portfolio-header__name > h1*New Portfolio*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Create New Portfolio*
waitForPageToLoad
waitForElementPresentcss=#defense_componentcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
typecss=#defense_componentDefense Logistics Agency
waitForPageToLoad
waitForElementPresentcss=#description
typecss=#descriptionMaintenance and monitoring of the energy grid
waitForPageToLoad
waitForElementPresentcss=#app_migration > li:nth-of-type(3) > label
clickcss=#app_migration > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#native_apps > li:nth-of-type(1) > label
clickcss=#native_apps > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#team_experience > li:nth-of-type(5) > label
clickcss=#team_experience > li:nth-of-type(5) > labelcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.empty-state > h3
assertTextcss=input[type="submit"]Save
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.portfolio-header__name > h1
assertTextcss=.portfolio-header__name > h1*Tatooine Energy Maintenance Systems*
waitForPageToLoad
waitForElementPresentcss=.empty-state h3
assertTextcss=.empty-state h3css=.empty-state > h3 *You don't have any Applications yet*
waitForElementPresentcss=.sticky-cta-text > h3css=.sticky-cta-context
assertTextcss=.sticky-cta-text > h3*Add Task Order (step 1 of 5)*css=.sticky-cta-context*Step 1 of 5*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3css=.sticky-cta-context
assertTextcss=.sticky-cta-text > h3*Add Task Order (step 2 of 5)*css=.sticky-cta-context*Step 2 of 5*
waitForPageToLoad
@@ -72,7 +72,7 @@ Imported from: AT-AT CI - New Portfolio--> - + @@ -87,13 +87,31 @@ Imported from: AT-AT CI - TO Step 1 Imported from: AT-AT CI - New Portfolio--> - + - - + + + + + + + + + + + + + + + + + + @@ -123,210 +141,12 @@ Imported from: AT-AT CI - TO Step 1 Imported from: AT-AT CI - New Portfolio--> - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -343,62 +163,26 @@ Imported from: AT-AT CI - New Portfolio--> + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -461,13 +245,13 @@ Imported from: AT-AT CI - TO Step 1--> Imported from: AT-AT CI - TO Step 1--> - + - - + + @@ -557,13 +341,13 @@ Imported from: AT-AT CI - TO Step 1--> - + - - + + @@ -619,13 +403,13 @@ Imported from: AT-AT CI - TO Step 1--> - + - - + + diff --git a/uitests/TO_Step_3_-_Add_CLIN.html b/uitests/TO_Step_3_-_Add_CLIN.html index c9230826..e385a3a8 100644 --- a/uitests/TO_Step_3_-_Add_CLIN.html +++ b/uitests/TO_Step_3_-_Add_CLIN.html @@ -16,7 +16,7 @@ - +
css=a[href="/portfolios/new"]
click css=a[href="/portfolios/new"]
waitForElementPresentcss=main.usa-section > h1css=.portfolio-header__name > h1
assertTextcss=main.usa-section > h1*New Portfolio Form*css=.portfolio-header__name > h1*New Portfolio*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Create New Portfolio*
waitForPageToLoad
waitForElementPresentcss=#defense_componentcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
typecss=#defense_componentDefense Logistics Agency
waitForPageToLoad
waitForElementPresentcss=#description
typecss=#descriptionMaintenance and monitoring of the energy grid
waitForPageToLoad
waitForElementPresentcss=#app_migration > li:nth-of-type(3) > label
clickcss=#app_migration > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#native_apps > li:nth-of-type(1) > label
clickcss=#native_apps > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#team_experience > li:nth-of-type(5) > label
clickcss=#team_experience > li:nth-of-type(5) > labelcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.empty-state > h3
assertTextcss=input[type="submit"]Save
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.portfolio-header__name > h1
assertTextcss=.portfolio-header__name > h1*Tatooine Energy Maintenance Systems*
waitForPageToLoad
waitForElementPresentcss=.empty-state h3
assertTextcss=.empty-state h3css=.empty-state > h3 *You don't have any Applications yet*
waitForElementPresentcss=.sticky-cta-text > h3css=.sticky-cta-context
assertTextcss=.sticky-cta-text > h3*Add Task Order (step 1 of 5)*css=.sticky-cta-context*Step 1 of 5*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3css=.sticky-cta-context
assertTextcss=.sticky-cta-text > h3*Add Task Order (step 2 of 5)*css=.sticky-cta-context*Step 2 of 5*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3css=.sticky-cta-context
assertTextcss=.sticky-cta-text > h3*Add Task Order (step 3 of 5)*css=.sticky-cta-context*Step 3 of 5*
waitForPageToLoad
@@ -75,7 +75,7 @@ Imported from: AT-AT CI - New Portfolio--> - + @@ -91,13 +91,32 @@ Imported from: AT-AT CI - TO Step 1 Imported from: AT-AT CI - New Portfolio--> - + - - + + + + + + + + + + + + + + + + + + @@ -129,221 +148,12 @@ Imported from: AT-AT CI - TO Step 1 Imported from: AT-AT CI - New Portfolio--> - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -361,65 +171,27 @@ Imported from: AT-AT CI - New Portfolio--> + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -486,13 +258,13 @@ Imported from: AT-AT CI - TO Step 2 Imported from: AT-AT CI - TO Step 1--> - + - - + + @@ -588,13 +360,13 @@ Imported from: AT-AT CI - TO Step 2--> Imported from: AT-AT CI - TO Step 2--> - + - - + + @@ -654,13 +426,13 @@ Imported from: AT-AT CI - TO Step 2--> - + - - + + diff --git a/uitests/TO_Step_4.html b/uitests/TO_Step_4.html index bd2e0450..bf7ecb81 100644 --- a/uitests/TO_Step_4.html +++ b/uitests/TO_Step_4.html @@ -16,7 +16,7 @@ - +
css=a[href="/portfolios/new"]
click css=a[href="/portfolios/new"]
waitForElementPresentcss=main.usa-section > h1css=.portfolio-header__name > h1
assertTextcss=main.usa-section > h1*New Portfolio Form*css=.portfolio-header__name > h1*New Portfolio*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Create New Portfolio*
waitForPageToLoad
waitForElementPresentcss=#defense_componentcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
typecss=#defense_componentDefense Logistics Agency
waitForPageToLoad
waitForElementPresentcss=#description
typecss=#descriptionMaintenance and monitoring of the energy grid
waitForPageToLoad
waitForElementPresentcss=#app_migration > li:nth-of-type(3) > label
clickcss=#app_migration > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#native_apps > li:nth-of-type(1) > label
clickcss=#native_apps > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#team_experience > li:nth-of-type(5) > label
clickcss=#team_experience > li:nth-of-type(5) > labelcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.empty-state > h3
assertTextcss=input[type="submit"]Save
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.portfolio-header__name > h1
assertTextcss=.portfolio-header__name > h1*Tatooine Energy Maintenance Systems*
waitForPageToLoad
waitForElementPresentcss=.empty-state h3
assertTextcss=.empty-state h3css=.empty-state > h3 *You don't have any Applications yet*
waitForElementPresentcss=.sticky-cta-text > h3css=.sticky-cta-context
assertTextcss=.sticky-cta-text > h3*Add Task Order (step 1 of 5)*css=.sticky-cta-context*Step 1 of 5*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3css=.sticky-cta-context
assertTextcss=.sticky-cta-text > h3*Add Task Order (step 2 of 5)*css=.sticky-cta-context*Step 2 of 5*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3css=.sticky-cta-context
assertTextcss=.sticky-cta-text > h3*Add Task Order (step 3 of 5)*css=.sticky-cta-context*Step 3 of 5*
waitForPageToLoad
@@ -75,7 +75,7 @@ Imported from: AT-AT CI - New Portfolio--> - + @@ -91,13 +91,32 @@ Imported from: AT-AT CI - TO Step 1 Imported from: AT-AT CI - New Portfolio--> - + - - + + + + + + + + + + + + + + + + + + @@ -129,221 +148,12 @@ Imported from: AT-AT CI - TO Step 1 Imported from: AT-AT CI - New Portfolio--> - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -361,65 +171,27 @@ Imported from: AT-AT CI - New Portfolio--> + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -486,13 +258,13 @@ Imported from: AT-AT CI - TO Step 2 Imported from: AT-AT CI - TO Step 1--> - + - - + + @@ -588,13 +360,13 @@ Imported from: AT-AT CI - TO Step 2--> Imported from: AT-AT CI - TO Step 2--> - + - - + + @@ -654,13 +426,13 @@ Imported from: AT-AT CI - TO Step 2--> - + - - + + @@ -940,13 +712,13 @@ Imported from: AT-AT CI - TO Step 2--> - + - - + + diff --git a/uitests/TO_Step_5.html b/uitests/TO_Step_5.html index 4e932c50..7f56ad80 100644 --- a/uitests/TO_Step_5.html +++ b/uitests/TO_Step_5.html @@ -16,7 +16,7 @@ - +
css=a[href="/portfolios/new"]
click css=a[href="/portfolios/new"]
waitForElementPresentcss=main.usa-section > h1css=.portfolio-header__name > h1
assertTextcss=main.usa-section > h1*New Portfolio Form*css=.portfolio-header__name > h1*New Portfolio*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Create New Portfolio*
waitForPageToLoad
waitForElementPresentcss=#defense_componentcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
typecss=#defense_componentDefense Logistics Agency
waitForPageToLoad
waitForElementPresentcss=#description
typecss=#descriptionMaintenance and monitoring of the energy grid
waitForPageToLoad
waitForElementPresentcss=#app_migration > li:nth-of-type(3) > label
clickcss=#app_migration > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#native_apps > li:nth-of-type(1) > label
clickcss=#native_apps > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#team_experience > li:nth-of-type(5) > label
clickcss=#team_experience > li:nth-of-type(5) > labelcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.empty-state > h3
assertTextcss=input[type="submit"]Save
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.portfolio-header__name > h1
assertTextcss=.portfolio-header__name > h1*Tatooine Energy Maintenance Systems*
waitForPageToLoad
waitForElementPresentcss=.empty-state h3
assertTextcss=.empty-state h3css=.empty-state > h3 *You don't have any Applications yet*
waitForElementPresentcss=.sticky-cta-text > h3css=.sticky-cta-context
assertTextcss=.sticky-cta-text > h3*Add Task Order (step 1 of 5)*css=.sticky-cta-context*Step 1 of 5*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3css=.sticky-cta-context
assertTextcss=.sticky-cta-text > h3*Add Task Order (step 2 of 5)*css=.sticky-cta-context*Step 2 of 5*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3css=.sticky-cta-context
assertTextcss=.sticky-cta-text > h3*Add Task Order (step 3 of 5)*css=.sticky-cta-context*Step 3 of 5*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3css=.sticky-cta-context
assertTextcss=.sticky-cta-text > h3*Add Task Order (step 4 of 5)*css=.sticky-cta-context*Step 4 of 5*
waitForPageToLoad
@@ -78,7 +78,7 @@ Imported from: AT-AT CI - New Portfolio--> - + @@ -95,13 +95,33 @@ Imported from: AT-AT CI - TO Step 1 Imported from: AT-AT CI - New Portfolio--> - + - - + + + + + + + + + + + + + + + + + + @@ -135,232 +155,12 @@ Imported from: AT-AT CI - TO Step 1 Imported from: AT-AT CI - New Portfolio--> - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -379,68 +179,28 @@ Imported from: AT-AT CI - New Portfolio--> + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -511,13 +271,13 @@ Imported from: AT-AT CI - TO Step 2 Imported from: AT-AT CI - TO Step 1--> - + - - + + @@ -619,13 +379,13 @@ Imported from: AT-AT CI - TO Step 3 Imported from: AT-AT CI - TO Step 2--> - + - - + + @@ -689,13 +449,13 @@ Imported from: AT-AT CI - TO Step 3--> Imported from: AT-AT CI - TO Step 3--> - + - - + + @@ -993,13 +753,13 @@ Imported from: AT-AT CI - TO Step 3--> - + - - + + From 5c84b7486ea0d1698ed3d42cfa49c86873893174 Mon Sep 17 00:00:00 2001 From: "Jay R. Newlin (PromptWorks)" Date: Wed, 18 Dec 2019 11:20:04 -0500 Subject: [PATCH 029/114] Test adjustments for efficiency --- uitests/Edit_App_Member.html | 790 +++---------------------- uitests/Resend_App_Member_Invite.html | 790 +++---------------------- uitests/Revoke_App_Member_Invite.html | 790 +++---------------------- uitests/Revoke_Environment_Access.html | 790 +++---------------------- 4 files changed, 368 insertions(+), 2792 deletions(-) diff --git a/uitests/Edit_App_Member.html b/uitests/Edit_App_Member.html index 276dcf34..5fa57810 100644 --- a/uitests/Edit_App_Member.html +++ b/uitests/Edit_App_Member.html @@ -16,7 +16,7 @@ - +
css=a[href="/portfolios/new"]
click css=a[href="/portfolios/new"]
waitForElementPresentcss=main.usa-section > h1css=.portfolio-header__name > h1
assertTextcss=main.usa-section > h1*New Portfolio Form*css=.portfolio-header__name > h1*New Portfolio*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Create New Portfolio*
waitForPageToLoad
waitForElementPresentcss=#defense_componentcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
typecss=#defense_componentDefense Logistics Agency
waitForPageToLoad
waitForElementPresentcss=#description
typecss=#descriptionMaintenance and monitoring of the energy grid
waitForPageToLoad
waitForElementPresentcss=#app_migration > li:nth-of-type(3) > label
clickcss=#app_migration > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#native_apps > li:nth-of-type(1) > label
clickcss=#native_apps > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#team_experience > li:nth-of-type(5) > label
clickcss=#team_experience > li:nth-of-type(5) > labelcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.empty-state > h3
assertTextcss=input[type="submit"]Save
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.portfolio-header__name > h1
assertTextcss=.portfolio-header__name > h1*Tatooine Energy Maintenance Systems*
waitForPageToLoad
waitForElementPresentcss=.empty-state h3
assertTextcss=.empty-state h3css=.empty-state > h3 *You don't have any Applications yet*
waitForElementPresentcss=.sticky-cta-text > h3css=.sticky-cta-context
assertTextcss=.sticky-cta-text > h3*Add Task Order (step 1 of 5)*css=.sticky-cta-context*Step 1 of 5*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3css=.sticky-cta-context
assertTextcss=.sticky-cta-text > h3*Add Task Order (step 2 of 5)*css=.sticky-cta-context*Step 2 of 5*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3css=.sticky-cta-context
assertTextcss=.sticky-cta-text > h3*Add Task Order (step 3 of 5)*css=.sticky-cta-context*Step 3 of 5*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3css=.sticky-cta-context
assertTextcss=.sticky-cta-text > h3*Add Task Order (step 4 of 5)*css=.sticky-cta-context*Step 4 of 5*
waitForPageToLoad
@@ -31,8 +31,7 @@ - @@ -44,8 +43,7 @@ Imported from: AT-AT CI - Login Brandon--> - @@ -62,8 +60,7 @@ Imported from: AT-AT CI - Login Brandon--> - @@ -80,8 +77,7 @@ Imported from: AT-AT CI - Login Brandon--> - @@ -98,10 +94,7 @@ Imported from: AT-AT CI - Login Brandon--> - @@ -114,10 +107,7 @@ Imported from: AT-AT CI - login--> - @@ -135,17 +125,14 @@ Imported from: AT-AT CI - login--> - - + @@ -155,30 +142,41 @@ Imported from: AT-AT CI - New Portfolio--> - - + - - + + - + + + + + + + + + + + + + + + + @@ -195,59 +193,16 @@ Imported from: AT-AT CI - New Portfolio--> - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + @@ -255,190 +210,7 @@ Imported from: AT-AT CI - New Portfolio--> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -446,68 +218,25 @@ Imported from: AT-AT CI - New Portfolio--> + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -515,18 +244,15 @@ Imported from: AT-AT CI - New Portfolio--> - + - + - + - + @@ -534,48 +260,7 @@ Imported from: AT-AT CI - New App Step 1--> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -591,34 +276,13 @@ Imported from: AT-AT CI - New App Step 1--> - - - - - - - - - - - - - - - - - + - + @@ -628,68 +292,13 @@ Imported from: AT-AT CI - New App Step 2--> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + @@ -699,82 +308,13 @@ Imported from: AT-AT CI - New App Step 3--> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + @@ -784,25 +324,7 @@ Imported from: AT-AT CI - New App Step 3--> - - - - - - - - - - - - - - - - - + @@ -818,8 +340,7 @@ Imported from: AT-AT CI - New App Step 3--> - + @@ -835,8 +356,7 @@ Imported from: AT-AT CI - New App Step 3--> - + @@ -845,32 +365,14 @@ Imported from: AT-AT CI - New App Step 3--> - + - - - - - - - - - - - - - - - - - + @@ -886,8 +388,7 @@ Imported from: AT-AT CI - New App Step 3--> - + @@ -903,31 +404,13 @@ Imported from: AT-AT CI - New App Step 3--> - - - - - - - - - - - - - - - - - + - + @@ -937,14 +420,13 @@ Imported from: AT-AT CI - New App Step 3--> - + - + @@ -954,14 +436,13 @@ Imported from: AT-AT CI - New App Step 3--> - + - + @@ -971,16 +452,15 @@ Imported from: AT-AT CI - New App Step 3--> - + - + - + @@ -988,16 +468,15 @@ Imported from: AT-AT CI - New App Step 3--> - + - + - + @@ -1005,8 +484,7 @@ Imported from: AT-AT CI - New App Step 3--> - + @@ -1022,81 +500,13 @@ Imported from: AT-AT CI - New App Step 3--> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + @@ -1106,15 +516,15 @@ Imported from: AT-AT CI - New App Step 3--> - + - + - + @@ -1122,23 +532,7 @@ Imported from: AT-AT CI - New App Step 3--> - - - - - - - - - - - - - - - - - + @@ -1154,7 +548,7 @@ Imported from: AT-AT CI - New App Step 3--> - + @@ -1170,7 +564,7 @@ Imported from: AT-AT CI - New App Step 3--> - + diff --git a/uitests/Resend_App_Member_Invite.html b/uitests/Resend_App_Member_Invite.html index 81dc7e36..e7f8afdf 100644 --- a/uitests/Resend_App_Member_Invite.html +++ b/uitests/Resend_App_Member_Invite.html @@ -16,7 +16,7 @@ - +
open
waitForElementPresent
waitForElementPresent
waitForElementPresent
waitForElementPresent css=a[href="/portfolios/new"]
click css=a[href="/portfolios/new"]
waitForElementPresentcss=main.usa-section > h1css=.portfolio-header__name > h1
assertTextcss=main.usa-section > h1*New Portfolio Form*css=.portfolio-header__name > h1*New Portfolio*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Create New Portfolio*
waitForPageToLoad
waitForElementPresent
waitForElementPresentcss=#defense_componentcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
typecss=#defense_componentDefense Logistics Agency
waitForPageToLoad
waitForElementPresentcss=#description
typecss=#descriptionMaintenance and monitoring of the energy grid
waitForPageToLoad
waitForElementPresentcss=#app_migration > li:nth-of-type(3) > label
clickcss=#app_migration > li:nth-of-type(3) > labelcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForElementPresentcss=#native_apps > li:nth-of-type(1) > label
clickcss=#native_apps > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#team_experience > li:nth-of-type(5) > label
clickcss=#team_experience > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresent
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.empty-state > h3
assertTextcss=input[type="submit"]Save
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.portfolio-header__name > h1
assertTextcss=.portfolio-header__name > h1*Tatooine Energy Maintenance Systems*
waitForPageToLoad
waitForElementPresentcss=.empty-state h3
assertTextcss=.empty-state h3css=.empty-state > h3 *You don't have any Applications yet*
waitForElementPresentcss=a.usa-button.usa-button-primarycss=.usa-button.usa-button-primary
clickcss=a.usa-button.usa-button-primarycss=.usa-button.usa-button-primary
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Name and Describe New Application*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-context
assertTextcss=.sticky-cta-context*Step 1 of 3*
waitForPageToLoad
waitForElementPresent css=#name
waitForElementPresentcss=#description
typecss=#descriptionAny basic application
waitForPageToLoad
waitForElementPresent css=button[type="submit"]
click css=button[type="submit"]
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Add Environments to Starter Application*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-context
assertTextcss=.sticky-cta-context*Step 2 of 3*
waitForPageToLoad
waitForElementPresentcss=h3.usa-alert-heading
assertTextcss=h3.usa-alert-heading*Application Saved*
waitForPageToLoad
waitForElementPresent css=button[type="submit"]
click css=button[type="submit"]
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Add Members to Starter Application*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-context
assertTextcss=.sticky-cta-context*Step 3 of 3*
waitForPageToLoad
waitForElementPresentcss=h3.usa-alert-heading
assertTextcss=h3.usa-alert-heading*Application environments updated*
waitForPageToLoad
waitForElementPresentcss=.empty-state__message
assertTextcss=.empty-state__message*This Application has no members*
waitForPageToLoad
waitForElementPresent css=a.usa-button.usa-button-secondary.add-new-button
click css=a.usa-button.usa-button-secondary.add-new-button
waitForElementPresentcss=#add-app-mem > div > div:nth-of-type(1) > h1
assertElementPresentcss=#add-app-mem > div > div:nth-of-type(1) > h1
waitForPageToLoad
waitForElementPresent css=#user_data-first_name
waitForElementPresent css=#user_data-last_name
waitForElementPresent css=#user_data-email
type css=#user_data-emailbrandon@example.comjay+brandon@promptworks.com
waitForPageToLoad
waitForElementPresentcss=#user_data-phone_number
typecss=#user_data-phone_number(206) 555-2342
waitForPageToLoad
waitForElementPresent css=#user_data-dod_id
waitForElementPresent css=#add-app-mem > div > div:nth-of-type(1) > .action-group > input[type="button"].action-group__action.usa-button
waitForElementPresentcss=#add-app-mem > div > div:nth-of-type(2) > h2
assertElementPresentcss=#add-app-mem > div > div:nth-of-type(2) > h2
waitForPageToLoad
waitForElementPresent css=.application-perms > div:nth-of-type(1) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
click css=.application-perms > div:nth-of-type(1) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
waitForElementPresent css=.application-perms > div:nth-of-type(2) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
click css=.application-perms > div:nth-of-type(2) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
waitForElementPresent css=.application-perms > div:nth-of-type(3) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
click css=.application-perms > div:nth-of-type(3) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
waitForElementPresentcss=[name=environment_roles-0-role]css=#environment_roles-0-role-None
typecss=[name=environment_roles-0-role]css=#environment_roles-0-role-None Basic Access
waitForElementPresentcss=[name=environment_roles-1-role]css=#environment_roles-1-role-None
typecss=[name=environment_roles-1-role]css=#environment_roles-1-role-None Network Admin
waitForElementPresent css=input[type="submit"]
waitForElementPresentcss=table.atat-table > tbody > tr > td:nth-of-type(1) > strong
assertTextcss=table.atat-table > tbody > tr > td:nth-of-type(1) > strong*Brandon Buchannan*
waitForPageToLoad
waitForElementPresentcss=.label
assertTextcss=.label*INVITE PENDING*
waitForPageToLoad
waitForElementPresentcss=section.member-list.application-list
assertElementPresentcss=section.member-list.application-list
waitForPageToLoad
waitForElementPresentcss=h3.usa-alert-heading
assertTextcss=h3.usa-alert-heading*Brandon's invitation has been sent*
waitForPageToLoad
waitForElementPresent css=span.action-group-footer > a.usa-button
click css=span.action-group-footer > a.usa-button
waitForElementPresentcss=.usa-input.usa-input--validation--anything > input[id="name"][type="text"]css=.sticky-cta-text > h3
assertTextcss=.usa-input.usa-input--validation--anything > input[id="name"][type="text"]css=.sticky-cta-text > h3 *Starter Application*
waitForElementPresentcss=#description
assertTextcss=#description*Any basic application*
waitForPageToLoad
waitForElementPresent css=.label
waitForElementPresent css=.accordion-table__items > .accordion-table__item:nth-of-type(1) > .accordion-table__item-content > .environment-list__item > .label.label--below
waitForElementPresent css=#delete-application
@@ -31,8 +31,7 @@ - @@ -44,8 +43,7 @@ Imported from: AT-AT CI - Login Brandon--> - @@ -62,8 +60,7 @@ Imported from: AT-AT CI - Login Brandon--> - @@ -80,8 +77,7 @@ Imported from: AT-AT CI - Login Brandon--> - @@ -98,10 +94,7 @@ Imported from: AT-AT CI - Login Brandon--> - @@ -114,10 +107,7 @@ Imported from: AT-AT CI - login--> - @@ -135,17 +125,14 @@ Imported from: AT-AT CI - login--> - - + @@ -155,30 +142,41 @@ Imported from: AT-AT CI - New Portfolio--> - - + - - + + - + + + + + + + + + + + + + + + + @@ -195,59 +193,16 @@ Imported from: AT-AT CI - New Portfolio--> - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + @@ -255,190 +210,7 @@ Imported from: AT-AT CI - New Portfolio--> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -446,68 +218,25 @@ Imported from: AT-AT CI - New Portfolio--> + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -515,18 +244,15 @@ Imported from: AT-AT CI - New Portfolio--> - + - + - + - + @@ -534,48 +260,7 @@ Imported from: AT-AT CI - New App Step 1--> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -591,34 +276,13 @@ Imported from: AT-AT CI - New App Step 1--> - - - - - - - - - - - - - - - - - + - + @@ -628,68 +292,13 @@ Imported from: AT-AT CI - New App Step 2--> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + @@ -699,82 +308,13 @@ Imported from: AT-AT CI - New App Step 3--> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + @@ -784,25 +324,7 @@ Imported from: AT-AT CI - New App Step 3--> - - - - - - - - - - - - - - - - - + @@ -818,8 +340,7 @@ Imported from: AT-AT CI - New App Step 3--> - + @@ -835,8 +356,7 @@ Imported from: AT-AT CI - New App Step 3--> - + @@ -845,32 +365,14 @@ Imported from: AT-AT CI - New App Step 3--> - + - - - - - - - - - - - - - - - - - + @@ -886,8 +388,7 @@ Imported from: AT-AT CI - New App Step 3--> - + @@ -903,31 +404,13 @@ Imported from: AT-AT CI - New App Step 3--> - - - - - - - - - - - - - - - - - + - + @@ -937,14 +420,13 @@ Imported from: AT-AT CI - New App Step 3--> - + - + @@ -954,14 +436,13 @@ Imported from: AT-AT CI - New App Step 3--> - + - + @@ -971,16 +452,15 @@ Imported from: AT-AT CI - New App Step 3--> - + - + - + @@ -988,16 +468,15 @@ Imported from: AT-AT CI - New App Step 3--> - + - + - + @@ -1005,8 +484,7 @@ Imported from: AT-AT CI - New App Step 3--> - + @@ -1022,81 +500,13 @@ Imported from: AT-AT CI - New App Step 3--> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + @@ -1106,15 +516,15 @@ Imported from: AT-AT CI - New App Step 3--> - + - + - + @@ -1122,23 +532,7 @@ Imported from: AT-AT CI - New App Step 3--> - - - - - - - - - - - - - - - - - + @@ -1154,7 +548,7 @@ Imported from: AT-AT CI - New App Step 3--> - + @@ -1170,7 +564,7 @@ Imported from: AT-AT CI - New App Step 3--> - + diff --git a/uitests/Revoke_App_Member_Invite.html b/uitests/Revoke_App_Member_Invite.html index df43cb2d..771cd4a0 100644 --- a/uitests/Revoke_App_Member_Invite.html +++ b/uitests/Revoke_App_Member_Invite.html @@ -16,7 +16,7 @@ - +
open
waitForElementPresent
waitForElementPresent
waitForElementPresent
waitForElementPresent css=a[href="/portfolios/new"]
click css=a[href="/portfolios/new"]
waitForElementPresentcss=main.usa-section > h1css=.portfolio-header__name > h1
assertTextcss=main.usa-section > h1*New Portfolio Form*css=.portfolio-header__name > h1*New Portfolio*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Create New Portfolio*
waitForPageToLoad
waitForElementPresent
waitForElementPresentcss=#defense_componentcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
typecss=#defense_componentDefense Logistics Agency
waitForPageToLoad
waitForElementPresentcss=#description
typecss=#descriptionMaintenance and monitoring of the energy grid
waitForPageToLoad
waitForElementPresentcss=#app_migration > li:nth-of-type(3) > label
clickcss=#app_migration > li:nth-of-type(3) > labelcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForElementPresentcss=#native_apps > li:nth-of-type(1) > label
clickcss=#native_apps > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#team_experience > li:nth-of-type(5) > label
clickcss=#team_experience > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresent
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.empty-state > h3
assertTextcss=input[type="submit"]Save
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.portfolio-header__name > h1
assertTextcss=.portfolio-header__name > h1*Tatooine Energy Maintenance Systems*
waitForPageToLoad
waitForElementPresentcss=.empty-state h3
assertTextcss=.empty-state h3css=.empty-state > h3 *You don't have any Applications yet*
waitForElementPresentcss=a.usa-button.usa-button-primarycss=.usa-button.usa-button-primary
clickcss=a.usa-button.usa-button-primarycss=.usa-button.usa-button-primary
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Name and Describe New Application*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-context
assertTextcss=.sticky-cta-context*Step 1 of 3*
waitForPageToLoad
waitForElementPresent css=#name
waitForElementPresentcss=#description
typecss=#descriptionAny basic application
waitForPageToLoad
waitForElementPresent css=button[type="submit"]
click css=button[type="submit"]
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Add Environments to Starter Application*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-context
assertTextcss=.sticky-cta-context*Step 2 of 3*
waitForPageToLoad
waitForElementPresentcss=h3.usa-alert-heading
assertTextcss=h3.usa-alert-heading*Application Saved*
waitForPageToLoad
waitForElementPresent css=button[type="submit"]
click css=button[type="submit"]
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Add Members to Starter Application*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-context
assertTextcss=.sticky-cta-context*Step 3 of 3*
waitForPageToLoad
waitForElementPresentcss=h3.usa-alert-heading
assertTextcss=h3.usa-alert-heading*Application environments updated*
waitForPageToLoad
waitForElementPresentcss=.empty-state__message
assertTextcss=.empty-state__message*This Application has no members*
waitForPageToLoad
waitForElementPresent css=a.usa-button.usa-button-secondary.add-new-button
click css=a.usa-button.usa-button-secondary.add-new-button
waitForElementPresentcss=#add-app-mem > div > div:nth-of-type(1) > h1
assertElementPresentcss=#add-app-mem > div > div:nth-of-type(1) > h1
waitForPageToLoad
waitForElementPresent css=#user_data-first_name
waitForElementPresent css=#user_data-last_name
waitForElementPresent css=#user_data-email
type css=#user_data-emailbrandon@example.comjay+brandon@promptworks.com
waitForPageToLoad
waitForElementPresentcss=#user_data-phone_number
typecss=#user_data-phone_number(206) 555-2342
waitForPageToLoad
waitForElementPresent css=#user_data-dod_id
waitForElementPresent css=#add-app-mem > div > div:nth-of-type(1) > .action-group > input[type="button"].action-group__action.usa-button
waitForElementPresentcss=#add-app-mem > div > div:nth-of-type(2) > h2
assertElementPresentcss=#add-app-mem > div > div:nth-of-type(2) > h2
waitForPageToLoad
waitForElementPresent css=.application-perms > div:nth-of-type(1) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
click css=.application-perms > div:nth-of-type(1) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
waitForElementPresent css=.application-perms > div:nth-of-type(2) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
click css=.application-perms > div:nth-of-type(2) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
waitForElementPresent css=.application-perms > div:nth-of-type(3) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
click css=.application-perms > div:nth-of-type(3) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
waitForElementPresentcss=[name=environment_roles-0-role]css=#environment_roles-0-role-None
typecss=[name=environment_roles-0-role]css=#environment_roles-0-role-None Basic Access
waitForElementPresentcss=[name=environment_roles-1-role]css=#environment_roles-1-role-None
typecss=[name=environment_roles-1-role]css=#environment_roles-1-role-None Network Admin
waitForElementPresent css=input[type="submit"]
waitForElementPresentcss=table.atat-table > tbody > tr > td:nth-of-type(1) > strong
assertTextcss=table.atat-table > tbody > tr > td:nth-of-type(1) > strong*Brandon Buchannan*
waitForPageToLoad
waitForElementPresentcss=.label
assertTextcss=.label*INVITE PENDING*
waitForPageToLoad
waitForElementPresentcss=section.member-list.application-list
assertElementPresentcss=section.member-list.application-list
waitForPageToLoad
waitForElementPresentcss=h3.usa-alert-heading
assertTextcss=h3.usa-alert-heading*Brandon's invitation has been sent*
waitForPageToLoad
waitForElementPresent css=span.action-group-footer > a.usa-button
click css=span.action-group-footer > a.usa-button
waitForElementPresentcss=.usa-input.usa-input--validation--anything > input[id="name"][type="text"]css=.sticky-cta-text > h3
assertTextcss=.usa-input.usa-input--validation--anything > input[id="name"][type="text"]css=.sticky-cta-text > h3 *Starter Application*
waitForElementPresentcss=#description
assertTextcss=#description*Any basic application*
waitForPageToLoad
waitForElementPresent css=.label
waitForElementPresent css=.accordion-table__items > .accordion-table__item:nth-of-type(1) > .accordion-table__item-content > .environment-list__item > .label.label--below
waitForElementPresent css=#delete-application
@@ -31,8 +31,7 @@ - @@ -44,8 +43,7 @@ Imported from: AT-AT CI - Login Brandon--> - @@ -62,8 +60,7 @@ Imported from: AT-AT CI - Login Brandon--> - @@ -80,8 +77,7 @@ Imported from: AT-AT CI - Login Brandon--> - @@ -98,10 +94,7 @@ Imported from: AT-AT CI - Login Brandon--> - @@ -114,10 +107,7 @@ Imported from: AT-AT CI - login--> - @@ -135,17 +125,14 @@ Imported from: AT-AT CI - login--> - - + @@ -155,30 +142,41 @@ Imported from: AT-AT CI - New Portfolio--> - - + - - + + - + + + + + + + + + + + + + + + + @@ -195,59 +193,16 @@ Imported from: AT-AT CI - New Portfolio--> - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + @@ -255,190 +210,7 @@ Imported from: AT-AT CI - New Portfolio--> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -446,68 +218,25 @@ Imported from: AT-AT CI - New Portfolio--> + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -515,18 +244,15 @@ Imported from: AT-AT CI - New Portfolio--> - + - + - + - + @@ -534,48 +260,7 @@ Imported from: AT-AT CI - New App Step 1--> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -591,34 +276,13 @@ Imported from: AT-AT CI - New App Step 1--> - - - - - - - - - - - - - - - - - + - + @@ -628,68 +292,13 @@ Imported from: AT-AT CI - New App Step 2--> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + @@ -699,82 +308,13 @@ Imported from: AT-AT CI - New App Step 3--> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + @@ -784,25 +324,7 @@ Imported from: AT-AT CI - New App Step 3--> - - - - - - - - - - - - - - - - - + @@ -818,8 +340,7 @@ Imported from: AT-AT CI - New App Step 3--> - + @@ -835,8 +356,7 @@ Imported from: AT-AT CI - New App Step 3--> - + @@ -845,32 +365,14 @@ Imported from: AT-AT CI - New App Step 3--> - + - - - - - - - - - - - - - - - - - + @@ -886,8 +388,7 @@ Imported from: AT-AT CI - New App Step 3--> - + @@ -903,31 +404,13 @@ Imported from: AT-AT CI - New App Step 3--> - - - - - - - - - - - - - - - - - + - + @@ -937,14 +420,13 @@ Imported from: AT-AT CI - New App Step 3--> - + - + @@ -954,14 +436,13 @@ Imported from: AT-AT CI - New App Step 3--> - + - + @@ -971,16 +452,15 @@ Imported from: AT-AT CI - New App Step 3--> - + - + - + @@ -988,16 +468,15 @@ Imported from: AT-AT CI - New App Step 3--> - + - + - + @@ -1005,8 +484,7 @@ Imported from: AT-AT CI - New App Step 3--> - + @@ -1022,81 +500,13 @@ Imported from: AT-AT CI - New App Step 3--> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + @@ -1106,15 +516,15 @@ Imported from: AT-AT CI - New App Step 3--> - + - + - + @@ -1122,23 +532,7 @@ Imported from: AT-AT CI - New App Step 3--> - - - - - - - - - - - - - - - - - + @@ -1154,7 +548,7 @@ Imported from: AT-AT CI - New App Step 3--> - + @@ -1170,7 +564,7 @@ Imported from: AT-AT CI - New App Step 3--> - + diff --git a/uitests/Revoke_Environment_Access.html b/uitests/Revoke_Environment_Access.html index 30feb757..56bc1bdb 100644 --- a/uitests/Revoke_Environment_Access.html +++ b/uitests/Revoke_Environment_Access.html @@ -16,7 +16,7 @@ - +
open
waitForElementPresent
waitForElementPresent
waitForElementPresent
waitForElementPresent css=a[href="/portfolios/new"]
click css=a[href="/portfolios/new"]
waitForElementPresentcss=main.usa-section > h1css=.portfolio-header__name > h1
assertTextcss=main.usa-section > h1*New Portfolio Form*css=.portfolio-header__name > h1*New Portfolio*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Create New Portfolio*
waitForPageToLoad
waitForElementPresent
waitForElementPresentcss=#defense_componentcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
typecss=#defense_componentDefense Logistics Agency
waitForPageToLoad
waitForElementPresentcss=#description
typecss=#descriptionMaintenance and monitoring of the energy grid
waitForPageToLoad
waitForElementPresentcss=#app_migration > li:nth-of-type(3) > label
clickcss=#app_migration > li:nth-of-type(3) > labelcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForElementPresentcss=#native_apps > li:nth-of-type(1) > label
clickcss=#native_apps > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#team_experience > li:nth-of-type(5) > label
clickcss=#team_experience > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresent
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.empty-state > h3
assertTextcss=input[type="submit"]Save
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.portfolio-header__name > h1
assertTextcss=.portfolio-header__name > h1*Tatooine Energy Maintenance Systems*
waitForPageToLoad
waitForElementPresentcss=.empty-state h3
assertTextcss=.empty-state h3css=.empty-state > h3 *You don't have any Applications yet*
waitForElementPresentcss=a.usa-button.usa-button-primarycss=.usa-button.usa-button-primary
clickcss=a.usa-button.usa-button-primarycss=.usa-button.usa-button-primary
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Name and Describe New Application*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-context
assertTextcss=.sticky-cta-context*Step 1 of 3*
waitForPageToLoad
waitForElementPresent css=#name
waitForElementPresentcss=#description
typecss=#descriptionAny basic application
waitForPageToLoad
waitForElementPresent css=button[type="submit"]
click css=button[type="submit"]
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Add Environments to Starter Application*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-context
assertTextcss=.sticky-cta-context*Step 2 of 3*
waitForPageToLoad
waitForElementPresentcss=h3.usa-alert-heading
assertTextcss=h3.usa-alert-heading*Application Saved*
waitForPageToLoad
waitForElementPresent css=button[type="submit"]
click css=button[type="submit"]
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Add Members to Starter Application*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-context
assertTextcss=.sticky-cta-context*Step 3 of 3*
waitForPageToLoad
waitForElementPresentcss=h3.usa-alert-heading
assertTextcss=h3.usa-alert-heading*Application environments updated*
waitForPageToLoad
waitForElementPresentcss=.empty-state__message
assertTextcss=.empty-state__message*This Application has no members*
waitForPageToLoad
waitForElementPresent css=a.usa-button.usa-button-secondary.add-new-button
click css=a.usa-button.usa-button-secondary.add-new-button
waitForElementPresentcss=#add-app-mem > div > div:nth-of-type(1) > h1
assertElementPresentcss=#add-app-mem > div > div:nth-of-type(1) > h1
waitForPageToLoad
waitForElementPresent css=#user_data-first_name
waitForElementPresent css=#user_data-last_name
waitForElementPresent css=#user_data-email
type css=#user_data-emailbrandon@example.comjay+brandon@promptworks.com
waitForPageToLoad
waitForElementPresentcss=#user_data-phone_number
typecss=#user_data-phone_number(206) 555-2342
waitForPageToLoad
waitForElementPresent css=#user_data-dod_id
waitForElementPresent css=#add-app-mem > div > div:nth-of-type(1) > .action-group > input[type="button"].action-group__action.usa-button
waitForElementPresentcss=#add-app-mem > div > div:nth-of-type(2) > h2
assertElementPresentcss=#add-app-mem > div > div:nth-of-type(2) > h2
waitForPageToLoad
waitForElementPresent css=.application-perms > div:nth-of-type(1) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
click css=.application-perms > div:nth-of-type(1) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
waitForElementPresent css=.application-perms > div:nth-of-type(2) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
click css=.application-perms > div:nth-of-type(2) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
waitForElementPresent css=.application-perms > div:nth-of-type(3) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
click css=.application-perms > div:nth-of-type(3) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
waitForElementPresentcss=[name=environment_roles-0-role]css=#environment_roles-0-role-None
typecss=[name=environment_roles-0-role]css=#environment_roles-0-role-None Basic Access
waitForElementPresentcss=[name=environment_roles-1-role]css=#environment_roles-1-role-None
typecss=[name=environment_roles-1-role]css=#environment_roles-1-role-None Network Admin
waitForElementPresent css=input[type="submit"]
waitForElementPresentcss=table.atat-table > tbody > tr > td:nth-of-type(1) > strong
assertTextcss=table.atat-table > tbody > tr > td:nth-of-type(1) > strong*Brandon Buchannan*
waitForPageToLoad
waitForElementPresentcss=.label
assertTextcss=.label*INVITE PENDING*
waitForPageToLoad
waitForElementPresentcss=section.member-list.application-list
assertElementPresentcss=section.member-list.application-list
waitForPageToLoad
waitForElementPresentcss=h3.usa-alert-heading
assertTextcss=h3.usa-alert-heading*Brandon's invitation has been sent*
waitForPageToLoad
waitForElementPresent css=span.action-group-footer > a.usa-button
click css=span.action-group-footer > a.usa-button
waitForElementPresentcss=.usa-input.usa-input--validation--anything > input[id="name"][type="text"]css=.sticky-cta-text > h3
assertTextcss=.usa-input.usa-input--validation--anything > input[id="name"][type="text"]css=.sticky-cta-text > h3 *Starter Application*
waitForElementPresentcss=#description
assertTextcss=#description*Any basic application*
waitForPageToLoad
waitForElementPresent css=.label
waitForElementPresent css=.accordion-table__items > .accordion-table__item:nth-of-type(1) > .accordion-table__item-content > .environment-list__item > .label.label--below
waitForElementPresent css=#delete-application
@@ -31,8 +31,7 @@ - @@ -44,8 +43,7 @@ Imported from: AT-AT CI - Login Brandon--> - @@ -62,8 +60,7 @@ Imported from: AT-AT CI - Login Brandon--> - @@ -80,8 +77,7 @@ Imported from: AT-AT CI - Login Brandon--> - @@ -98,10 +94,7 @@ Imported from: AT-AT CI - Login Brandon--> - @@ -114,10 +107,7 @@ Imported from: AT-AT CI - login--> - @@ -135,17 +125,14 @@ Imported from: AT-AT CI - login--> - - + @@ -155,30 +142,41 @@ Imported from: AT-AT CI - New Portfolio--> - - + - - + + - + + + + + + + + + + + + + + + + @@ -195,59 +193,16 @@ Imported from: AT-AT CI - New Portfolio--> - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + @@ -255,190 +210,7 @@ Imported from: AT-AT CI - New Portfolio--> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -446,68 +218,25 @@ Imported from: AT-AT CI - New Portfolio--> + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -515,18 +244,15 @@ Imported from: AT-AT CI - New Portfolio--> - + - + - + - + @@ -534,48 +260,7 @@ Imported from: AT-AT CI - New App Step 1--> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -591,34 +276,13 @@ Imported from: AT-AT CI - New App Step 1--> - - - - - - - - - - - - - - - - - + - + @@ -628,68 +292,13 @@ Imported from: AT-AT CI - New App Step 2--> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + @@ -699,82 +308,13 @@ Imported from: AT-AT CI - New App Step 3--> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + @@ -784,25 +324,7 @@ Imported from: AT-AT CI - New App Step 3--> - - - - - - - - - - - - - - - - - + @@ -818,8 +340,7 @@ Imported from: AT-AT CI - New App Step 3--> - + @@ -835,8 +356,7 @@ Imported from: AT-AT CI - New App Step 3--> - + @@ -845,32 +365,14 @@ Imported from: AT-AT CI - New App Step 3--> - + - - - - - - - - - - - - - - - - - + @@ -886,8 +388,7 @@ Imported from: AT-AT CI - New App Step 3--> - + @@ -903,31 +404,13 @@ Imported from: AT-AT CI - New App Step 3--> - - - - - - - - - - - - - - - - - + - + @@ -937,14 +420,13 @@ Imported from: AT-AT CI - New App Step 3--> - + - + @@ -954,14 +436,13 @@ Imported from: AT-AT CI - New App Step 3--> - + - + @@ -971,16 +452,15 @@ Imported from: AT-AT CI - New App Step 3--> - + - + - + @@ -988,16 +468,15 @@ Imported from: AT-AT CI - New App Step 3--> - + - + - + @@ -1005,8 +484,7 @@ Imported from: AT-AT CI - New App Step 3--> - + @@ -1022,81 +500,13 @@ Imported from: AT-AT CI - New App Step 3--> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + @@ -1106,15 +516,15 @@ Imported from: AT-AT CI - New App Step 3--> - + - + - + @@ -1122,23 +532,7 @@ Imported from: AT-AT CI - New App Step 3--> - - - - - - - - - - - - - - - - - + @@ -1154,7 +548,7 @@ Imported from: AT-AT CI - New App Step 3--> - + @@ -1170,7 +564,7 @@ Imported from: AT-AT CI - New App Step 3--> - + From 832234cbe1e370cdb33cce44ee82cac8de67be26 Mon Sep 17 00:00:00 2001 From: "Jay R. Newlin (PromptWorks)" Date: Wed, 18 Dec 2019 11:20:46 -0500 Subject: [PATCH 030/114] Various minor test adjustments --- uitests/Add_CCPO_User.html | 2 +- uitests/Delete_Portfolio_Member.html | 306 +---- uitests/Edit_Portfolio_Member.html | 306 +---- uitests/Login_Brandon.html | 2 +- uitests/New_App_Step_1.html | 274 +---- uitests/New_App_Step_2.html | 290 +---- uitests/New_App_Step_2_-_Add_Env.html | 306 +---- uitests/New_App_Step_3.html | 306 +---- uitests/New_Portfolio_Member.html | 290 +---- uitests/Portfolio_Settings.html | 274 +---- uitests/Remove_Portfolio_Member.html | 306 +---- uitests/Reports_-_Follow_Add_App_Button.html | 1090 ++++-------------- uitests/Reports_-_Follow_TO_link.html | 1090 ++++-------------- uitests/login.html | 2 +- 14 files changed, 872 insertions(+), 3972 deletions(-) diff --git a/uitests/Add_CCPO_User.html b/uitests/Add_CCPO_User.html index df3ad34d..c3de0b5d 100644 --- a/uitests/Add_CCPO_User.html +++ b/uitests/Add_CCPO_User.html @@ -16,7 +16,7 @@ - +
open
waitForElementPresent
waitForElementPresent
waitForElementPresent
waitForElementPresent css=a[href="/portfolios/new"]
click css=a[href="/portfolios/new"]
waitForElementPresentcss=main.usa-section > h1css=.portfolio-header__name > h1
assertTextcss=main.usa-section > h1*New Portfolio Form*css=.portfolio-header__name > h1*New Portfolio*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Create New Portfolio*
waitForPageToLoad
waitForElementPresent
waitForElementPresentcss=#defense_componentcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
typecss=#defense_componentDefense Logistics Agency
waitForPageToLoad
waitForElementPresentcss=#description
typecss=#descriptionMaintenance and monitoring of the energy grid
waitForPageToLoad
waitForElementPresentcss=#app_migration > li:nth-of-type(3) > label
clickcss=#app_migration > li:nth-of-type(3) > labelcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForElementPresentcss=#native_apps > li:nth-of-type(1) > label
clickcss=#native_apps > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#team_experience > li:nth-of-type(5) > label
clickcss=#team_experience > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresent
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.empty-state > h3
assertTextcss=input[type="submit"]Save
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.portfolio-header__name > h1
assertTextcss=.portfolio-header__name > h1*Tatooine Energy Maintenance Systems*
waitForPageToLoad
waitForElementPresentcss=.empty-state h3
assertTextcss=.empty-state h3css=.empty-state > h3 *You don't have any Applications yet*
waitForElementPresentcss=a.usa-button.usa-button-primarycss=.usa-button.usa-button-primary
clickcss=a.usa-button.usa-button-primarycss=.usa-button.usa-button-primary
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Name and Describe New Application*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-context
assertTextcss=.sticky-cta-context*Step 1 of 3*
waitForPageToLoad
waitForElementPresent css=#name
waitForElementPresentcss=#description
typecss=#descriptionAny basic application
waitForPageToLoad
waitForElementPresent css=button[type="submit"]
click css=button[type="submit"]
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Add Environments to Starter Application*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-context
assertTextcss=.sticky-cta-context*Step 2 of 3*
waitForPageToLoad
waitForElementPresentcss=h3.usa-alert-heading
assertTextcss=h3.usa-alert-heading*Application Saved*
waitForPageToLoad
waitForElementPresent css=button[type="submit"]
click css=button[type="submit"]
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Add Members to Starter Application*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-context
assertTextcss=.sticky-cta-context*Step 3 of 3*
waitForPageToLoad
waitForElementPresentcss=h3.usa-alert-heading
assertTextcss=h3.usa-alert-heading*Application environments updated*
waitForPageToLoad
waitForElementPresentcss=.empty-state__message
assertTextcss=.empty-state__message*This Application has no members*
waitForPageToLoad
waitForElementPresent css=a.usa-button.usa-button-secondary.add-new-button
click css=a.usa-button.usa-button-secondary.add-new-button
waitForElementPresentcss=#add-app-mem > div > div:nth-of-type(1) > h1
assertElementPresentcss=#add-app-mem > div > div:nth-of-type(1) > h1
waitForPageToLoad
waitForElementPresent css=#user_data-first_name
waitForElementPresent css=#user_data-last_name
waitForElementPresent css=#user_data-email
type css=#user_data-emailbrandon@example.comjay+brandon@promptworks.com
waitForPageToLoad
waitForElementPresentcss=#user_data-phone_number
typecss=#user_data-phone_number(206) 555-2342
waitForPageToLoad
waitForElementPresent css=#user_data-dod_id
waitForElementPresent css=#add-app-mem > div > div:nth-of-type(1) > .action-group > input[type="button"].action-group__action.usa-button
waitForElementPresentcss=#add-app-mem > div > div:nth-of-type(2) > h2
assertElementPresentcss=#add-app-mem > div > div:nth-of-type(2) > h2
waitForPageToLoad
waitForElementPresent css=.application-perms > div:nth-of-type(1) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
click css=.application-perms > div:nth-of-type(1) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
waitForElementPresent css=.application-perms > div:nth-of-type(2) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
click css=.application-perms > div:nth-of-type(2) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
waitForElementPresent css=.application-perms > div:nth-of-type(3) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
click css=.application-perms > div:nth-of-type(3) > .usa-input.input__inline-fields > fieldset.usa-input__choices > legend > label
waitForElementPresentcss=[name=environment_roles-0-role]css=#environment_roles-0-role-None
typecss=[name=environment_roles-0-role]css=#environment_roles-0-role-None Basic Access
waitForElementPresentcss=[name=environment_roles-1-role]css=#environment_roles-1-role-None
typecss=[name=environment_roles-1-role]css=#environment_roles-1-role-None Network Admin
waitForElementPresent css=input[type="submit"]
waitForElementPresentcss=table.atat-table > tbody > tr > td:nth-of-type(1) > strong
assertTextcss=table.atat-table > tbody > tr > td:nth-of-type(1) > strong*Brandon Buchannan*
waitForPageToLoad
waitForElementPresentcss=.label
assertTextcss=.label*INVITE PENDING*
waitForPageToLoad
waitForElementPresentcss=section.member-list.application-list
assertElementPresentcss=section.member-list.application-list
waitForPageToLoad
waitForElementPresentcss=h3.usa-alert-heading
assertTextcss=h3.usa-alert-heading*Brandon's invitation has been sent*
waitForPageToLoad
waitForElementPresent css=span.action-group-footer > a.usa-button
click css=span.action-group-footer > a.usa-button
waitForElementPresentcss=.usa-input.usa-input--validation--anything > input[id="name"][type="text"]css=.sticky-cta-text > h3
assertTextcss=.usa-input.usa-input--validation--anything > input[id="name"][type="text"]css=.sticky-cta-text > h3 *Starter Application*
waitForElementPresentcss=#description
assertTextcss=#description*Any basic application*
waitForPageToLoad
waitForElementPresent css=.label
waitForElementPresent css=.accordion-table__items > .accordion-table__item:nth-of-type(1) > .accordion-table__item-content > .environment-list__item > .label.label--below
waitForElementPresent css=#delete-application
diff --git a/uitests/Delete_Portfolio_Member.html b/uitests/Delete_Portfolio_Member.html index 4557fcfa..563113f0 100644 --- a/uitests/Delete_Portfolio_Member.html +++ b/uitests/Delete_Portfolio_Member.html @@ -16,7 +16,7 @@ - +
@@ -135,7 +135,7 @@ Imported from: AT-AT CI - New Portfolio--> - + @@ -150,13 +150,31 @@ Imported from: AT-AT CI - Portfolio Settings Imported from: AT-AT CI - New Portfolio--> - + - - + + + + + + + + + + + + + + + + + + @@ -186,210 +204,12 @@ Imported from: AT-AT CI - Portfolio Settings Imported from: AT-AT CI - New Portfolio--> - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -406,62 +226,26 @@ Imported from: AT-AT CI - New Portfolio--> + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/uitests/Edit_Portfolio_Member.html b/uitests/Edit_Portfolio_Member.html index e5003462..fea162c7 100644 --- a/uitests/Edit_Portfolio_Member.html +++ b/uitests/Edit_Portfolio_Member.html @@ -16,7 +16,7 @@ - +
css=a[href="/portfolios/new"]
click css=a[href="/portfolios/new"]
waitForElementPresentcss=main.usa-section > h1css=.portfolio-header__name > h1
assertTextcss=main.usa-section > h1*New Portfolio Form*css=.portfolio-header__name > h1*New Portfolio*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Create New Portfolio*
waitForPageToLoad
waitForElementPresentcss=#defense_componentcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
typecss=#defense_componentDefense Logistics Agency
waitForPageToLoad
waitForElementPresentcss=#description
typecss=#descriptionMaintenance and monitoring of the energy grid
waitForPageToLoad
waitForElementPresentcss=#app_migration > li:nth-of-type(3) > label
clickcss=#app_migration > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#native_apps > li:nth-of-type(1) > label
clickcss=#native_apps > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#team_experience > li:nth-of-type(5) > label
clickcss=#team_experience > li:nth-of-type(5) > labelcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.empty-state > h3
assertTextcss=input[type="submit"]Save
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.portfolio-header__name > h1
assertTextcss=.portfolio-header__name > h1*Tatooine Energy Maintenance Systems*
waitForPageToLoad
waitForElementPresentcss=.empty-state h3
assertTextcss=.empty-state h3css=.empty-state > h3 *You don't have any Applications yet*
@@ -135,7 +135,7 @@ Imported from: AT-AT CI - New Portfolio--> - + @@ -150,13 +150,31 @@ Imported from: AT-AT CI - Portfolio Settings Imported from: AT-AT CI - New Portfolio--> - + - - + + + + + + + + + + + + + + + + + + @@ -186,210 +204,12 @@ Imported from: AT-AT CI - Portfolio Settings Imported from: AT-AT CI - New Portfolio--> - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -406,62 +226,26 @@ Imported from: AT-AT CI - New Portfolio--> + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/uitests/Login_Brandon.html b/uitests/Login_Brandon.html index b5a2a58a..3ca75a4f 100644 --- a/uitests/Login_Brandon.html +++ b/uitests/Login_Brandon.html @@ -16,7 +16,7 @@ - +
css=a[href="/portfolios/new"]
click css=a[href="/portfolios/new"]
waitForElementPresentcss=main.usa-section > h1css=.portfolio-header__name > h1
assertTextcss=main.usa-section > h1*New Portfolio Form*css=.portfolio-header__name > h1*New Portfolio*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Create New Portfolio*
waitForPageToLoad
waitForElementPresentcss=#defense_componentcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
typecss=#defense_componentDefense Logistics Agency
waitForPageToLoad
waitForElementPresentcss=#description
typecss=#descriptionMaintenance and monitoring of the energy grid
waitForPageToLoad
waitForElementPresentcss=#app_migration > li:nth-of-type(3) > label
clickcss=#app_migration > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#native_apps > li:nth-of-type(1) > label
clickcss=#native_apps > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#team_experience > li:nth-of-type(5) > label
clickcss=#team_experience > li:nth-of-type(5) > labelcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.empty-state > h3
assertTextcss=input[type="submit"]Save
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.portfolio-header__name > h1
assertTextcss=.portfolio-header__name > h1*Tatooine Energy Maintenance Systems*
waitForPageToLoad
waitForElementPresentcss=.empty-state h3
assertTextcss=.empty-state h3css=.empty-state > h3 *You don't have any Applications yet*
diff --git a/uitests/New_App_Step_1.html b/uitests/New_App_Step_1.html index 0a36b66c..a65803c1 100644 --- a/uitests/New_App_Step_1.html +++ b/uitests/New_App_Step_1.html @@ -16,7 +16,7 @@ - +
@@ -66,7 +66,7 @@ Imported from: AT-AT CI - login--> - + @@ -79,13 +79,29 @@ Imported from: AT-AT CI - login--> - + - - + + + + + + + + + + + + + + + + + + @@ -111,188 +127,12 @@ Imported from: AT-AT CI - login--> - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -307,56 +147,24 @@ Imported from: AT-AT CI - login--> + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/uitests/New_App_Step_2.html b/uitests/New_App_Step_2.html index 16c2877a..735842b0 100644 --- a/uitests/New_App_Step_2.html +++ b/uitests/New_App_Step_2.html @@ -16,7 +16,7 @@ - +
css=a[href="/portfolios/new"]
click css=a[href="/portfolios/new"]
waitForElementPresentcss=main.usa-section > h1css=.portfolio-header__name > h1
assertTextcss=main.usa-section > h1*New Portfolio Form*css=.portfolio-header__name > h1*New Portfolio*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Create New Portfolio*
waitForPageToLoad
waitForElementPresentcss=#defense_componentcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
typecss=#defense_componentDefense Logistics Agency
waitForPageToLoad
waitForElementPresentcss=#description
typecss=#descriptionMaintenance and monitoring of the energy grid
waitForPageToLoad
waitForElementPresentcss=#app_migration > li:nth-of-type(3) > label
clickcss=#app_migration > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#native_apps > li:nth-of-type(1) > label
clickcss=#native_apps > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#team_experience > li:nth-of-type(5) > label
clickcss=#team_experience > li:nth-of-type(5) > labelcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.empty-state > h3
assertTextcss=input[type="submit"]Save
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.portfolio-header__name > h1
assertTextcss=.portfolio-header__name > h1*Tatooine Energy Maintenance Systems*
waitForPageToLoad
waitForElementPresentcss=.empty-state h3
assertTextcss=.empty-state h3css=.empty-state > h3 *You don't have any Applications yet*
@@ -69,7 +69,7 @@ Imported from: AT-AT CI - New Portfolio--> - + @@ -83,13 +83,30 @@ Imported from: AT-AT CI - New Portfolio--> Imported from: AT-AT CI - New Portfolio--> - + - - + + + + + + + + + + + + + + + + + + @@ -117,199 +134,12 @@ Imported from: AT-AT CI - New Portfolio--> Imported from: AT-AT CI - New Portfolio--> - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -325,59 +155,25 @@ Imported from: AT-AT CI - New Portfolio--> + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/uitests/New_App_Step_2_-_Add_Env.html b/uitests/New_App_Step_2_-_Add_Env.html index 5a89c577..877f6ed2 100644 --- a/uitests/New_App_Step_2_-_Add_Env.html +++ b/uitests/New_App_Step_2_-_Add_Env.html @@ -16,7 +16,7 @@ - +
css=a[href="/portfolios/new"]
click css=a[href="/portfolios/new"]
waitForElementPresentcss=main.usa-section > h1css=.portfolio-header__name > h1
assertTextcss=main.usa-section > h1*New Portfolio Form*css=.portfolio-header__name > h1*New Portfolio*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Create New Portfolio*
waitForPageToLoad
waitForElementPresentcss=#defense_componentcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
typecss=#defense_componentDefense Logistics Agency
waitForPageToLoad
waitForElementPresentcss=#description
typecss=#descriptionMaintenance and monitoring of the energy grid
waitForPageToLoad
waitForElementPresentcss=#app_migration > li:nth-of-type(3) > label
clickcss=#app_migration > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#native_apps > li:nth-of-type(1) > label
clickcss=#native_apps > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#team_experience > li:nth-of-type(5) > label
clickcss=#team_experience > li:nth-of-type(5) > labelcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.empty-state > h3
assertTextcss=input[type="submit"]Save
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.portfolio-header__name > h1
assertTextcss=.portfolio-header__name > h1*Tatooine Energy Maintenance Systems*
waitForPageToLoad
waitForElementPresentcss=.empty-state h3
assertTextcss=.empty-state h3css=.empty-state > h3 *You don't have any Applications yet*
@@ -72,7 +72,7 @@ Imported from: AT-AT CI - New Portfolio--> - + @@ -87,13 +87,31 @@ Imported from: AT-AT CI - New App Step 1 Imported from: AT-AT CI - New Portfolio--> - + - - + + + + + + + + + + + + + + + + + + @@ -123,210 +141,12 @@ Imported from: AT-AT CI - New App Step 1 Imported from: AT-AT CI - New Portfolio--> - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -343,62 +163,26 @@ Imported from: AT-AT CI - New Portfolio--> + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/uitests/New_App_Step_3.html b/uitests/New_App_Step_3.html index 5ebf05ce..4794e5d1 100644 --- a/uitests/New_App_Step_3.html +++ b/uitests/New_App_Step_3.html @@ -16,7 +16,7 @@ - +
css=a[href="/portfolios/new"]
click css=a[href="/portfolios/new"]
waitForElementPresentcss=main.usa-section > h1css=.portfolio-header__name > h1
assertTextcss=main.usa-section > h1*New Portfolio Form*css=.portfolio-header__name > h1*New Portfolio*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Create New Portfolio*
waitForPageToLoad
waitForElementPresentcss=#defense_componentcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
typecss=#defense_componentDefense Logistics Agency
waitForPageToLoad
waitForElementPresentcss=#description
typecss=#descriptionMaintenance and monitoring of the energy grid
waitForPageToLoad
waitForElementPresentcss=#app_migration > li:nth-of-type(3) > label
clickcss=#app_migration > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#native_apps > li:nth-of-type(1) > label
clickcss=#native_apps > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#team_experience > li:nth-of-type(5) > label
clickcss=#team_experience > li:nth-of-type(5) > labelcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.empty-state > h3
assertTextcss=input[type="submit"]Save
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.portfolio-header__name > h1
assertTextcss=.portfolio-header__name > h1*Tatooine Energy Maintenance Systems*
waitForPageToLoad
waitForElementPresentcss=.empty-state h3
assertTextcss=.empty-state h3css=.empty-state > h3 *You don't have any Applications yet*
@@ -131,7 +131,7 @@ Imported from: AT-AT CI - New Portfolio--> - + @@ -146,13 +146,31 @@ Imported from: AT-AT CI - New App Step 1 Imported from: AT-AT CI - New Portfolio--> - + - - + + + + + + + + + + + + + + + + + + @@ -182,210 +200,12 @@ Imported from: AT-AT CI - New App Step 1 Imported from: AT-AT CI - New Portfolio--> - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -402,62 +222,26 @@ Imported from: AT-AT CI - New Portfolio--> + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/uitests/New_Portfolio_Member.html b/uitests/New_Portfolio_Member.html index 13a426c2..cb960f1c 100644 --- a/uitests/New_Portfolio_Member.html +++ b/uitests/New_Portfolio_Member.html @@ -16,7 +16,7 @@ - +
css=a[href="/portfolios/new"]
click css=a[href="/portfolios/new"]
waitForElementPresentcss=main.usa-section > h1css=.portfolio-header__name > h1
assertTextcss=main.usa-section > h1*New Portfolio Form*css=.portfolio-header__name > h1*New Portfolio*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Create New Portfolio*
waitForPageToLoad
waitForElementPresentcss=#defense_componentcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
typecss=#defense_componentDefense Logistics Agency
waitForPageToLoad
waitForElementPresentcss=#description
typecss=#descriptionMaintenance and monitoring of the energy grid
waitForPageToLoad
waitForElementPresentcss=#app_migration > li:nth-of-type(3) > label
clickcss=#app_migration > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#native_apps > li:nth-of-type(1) > label
clickcss=#native_apps > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#team_experience > li:nth-of-type(5) > label
clickcss=#team_experience > li:nth-of-type(5) > labelcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.empty-state > h3
assertTextcss=input[type="submit"]Save
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.portfolio-header__name > h1
assertTextcss=.portfolio-header__name > h1*Tatooine Energy Maintenance Systems*
waitForPageToLoad
waitForElementPresentcss=.empty-state h3
assertTextcss=.empty-state h3css=.empty-state > h3 *You don't have any Applications yet*
@@ -128,7 +128,7 @@ Imported from: AT-AT CI - New Portfolio--> - + @@ -142,13 +142,30 @@ Imported from: AT-AT CI - New Portfolio--> Imported from: AT-AT CI - New Portfolio--> - + - - + + + + + + + + + + + + + + + + + + @@ -176,199 +193,12 @@ Imported from: AT-AT CI - New Portfolio--> Imported from: AT-AT CI - New Portfolio--> - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -384,59 +214,25 @@ Imported from: AT-AT CI - New Portfolio--> + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/uitests/Portfolio_Settings.html b/uitests/Portfolio_Settings.html index d12bdffd..02424caf 100644 --- a/uitests/Portfolio_Settings.html +++ b/uitests/Portfolio_Settings.html @@ -16,7 +16,7 @@ - +
css=a[href="/portfolios/new"]
click css=a[href="/portfolios/new"]
waitForElementPresentcss=main.usa-section > h1css=.portfolio-header__name > h1
assertTextcss=main.usa-section > h1*New Portfolio Form*css=.portfolio-header__name > h1*New Portfolio*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Create New Portfolio*
waitForPageToLoad
waitForElementPresentcss=#defense_componentcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
typecss=#defense_componentDefense Logistics Agency
waitForPageToLoad
waitForElementPresentcss=#description
typecss=#descriptionMaintenance and monitoring of the energy grid
waitForPageToLoad
waitForElementPresentcss=#app_migration > li:nth-of-type(3) > label
clickcss=#app_migration > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#native_apps > li:nth-of-type(1) > label
clickcss=#native_apps > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#team_experience > li:nth-of-type(5) > label
clickcss=#team_experience > li:nth-of-type(5) > labelcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.empty-state > h3
assertTextcss=input[type="submit"]Save
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.portfolio-header__name > h1
assertTextcss=.portfolio-header__name > h1*Tatooine Energy Maintenance Systems*
waitForPageToLoad
waitForElementPresentcss=.empty-state h3
assertTextcss=.empty-state h3css=.empty-state > h3 *You don't have any Applications yet*
@@ -66,7 +66,7 @@ Imported from: AT-AT CI - login--> - + @@ -79,13 +79,29 @@ Imported from: AT-AT CI - login--> - + - - + + + + + + + + + + + + + + + + + + @@ -111,188 +127,12 @@ Imported from: AT-AT CI - login--> - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -307,56 +147,24 @@ Imported from: AT-AT CI - login--> + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/uitests/Remove_Portfolio_Member.html b/uitests/Remove_Portfolio_Member.html index a6e3f87a..fc1844e2 100644 --- a/uitests/Remove_Portfolio_Member.html +++ b/uitests/Remove_Portfolio_Member.html @@ -16,7 +16,7 @@ - +
css=a[href="/portfolios/new"]
click css=a[href="/portfolios/new"]
waitForElementPresentcss=main.usa-section > h1css=.portfolio-header__name > h1
assertTextcss=main.usa-section > h1*New Portfolio Form*css=.portfolio-header__name > h1*New Portfolio*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Create New Portfolio*
waitForPageToLoad
waitForElementPresentcss=#defense_componentcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
typecss=#defense_componentDefense Logistics Agency
waitForPageToLoad
waitForElementPresentcss=#description
typecss=#descriptionMaintenance and monitoring of the energy grid
waitForPageToLoad
waitForElementPresentcss=#app_migration > li:nth-of-type(3) > label
clickcss=#app_migration > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#native_apps > li:nth-of-type(1) > label
clickcss=#native_apps > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#team_experience > li:nth-of-type(5) > label
clickcss=#team_experience > li:nth-of-type(5) > labelcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.empty-state > h3
assertTextcss=input[type="submit"]Save
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.portfolio-header__name > h1
assertTextcss=.portfolio-header__name > h1*Tatooine Energy Maintenance Systems*
waitForPageToLoad
waitForElementPresentcss=.empty-state h3
assertTextcss=.empty-state h3css=.empty-state > h3 *You don't have any Applications yet*
@@ -135,7 +135,7 @@ Imported from: AT-AT CI - New Portfolio--> - + @@ -150,13 +150,31 @@ Imported from: AT-AT CI - Portfolio Settings Imported from: AT-AT CI - New Portfolio--> - + - - + + + + + + + + + + + + + + + + + + @@ -186,210 +204,12 @@ Imported from: AT-AT CI - Portfolio Settings Imported from: AT-AT CI - New Portfolio--> - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -406,62 +226,26 @@ Imported from: AT-AT CI - New Portfolio--> + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/uitests/Reports_-_Follow_Add_App_Button.html b/uitests/Reports_-_Follow_Add_App_Button.html index 0c1b3bc5..abe9c94f 100644 --- a/uitests/Reports_-_Follow_Add_App_Button.html +++ b/uitests/Reports_-_Follow_Add_App_Button.html @@ -16,7 +16,7 @@ - +
css=a[href="/portfolios/new"]
click css=a[href="/portfolios/new"]
waitForElementPresentcss=main.usa-section > h1css=.portfolio-header__name > h1
assertTextcss=main.usa-section > h1*New Portfolio Form*css=.portfolio-header__name > h1*New Portfolio*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Create New Portfolio*
waitForPageToLoad
waitForElementPresentcss=#defense_componentcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
typecss=#defense_componentDefense Logistics Agency
waitForPageToLoad
waitForElementPresentcss=#description
typecss=#descriptionMaintenance and monitoring of the energy grid
waitForPageToLoad
waitForElementPresentcss=#app_migration > li:nth-of-type(3) > label
clickcss=#app_migration > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#native_apps > li:nth-of-type(1) > label
clickcss=#native_apps > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#team_experience > li:nth-of-type(5) > label
clickcss=#team_experience > li:nth-of-type(5) > labelcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.empty-state > h3
assertTextcss=input[type="submit"]Save
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.portfolio-header__name > h1
assertTextcss=.portfolio-header__name > h1*Tatooine Energy Maintenance Systems*
waitForPageToLoad
waitForElementPresentcss=.empty-state h3
assertTextcss=.empty-state h3css=.empty-state > h3 *You don't have any Applications yet*
@@ -31,12 +31,8 @@ - @@ -49,12 +45,8 @@ Imported from: AT-AT CI - login--> - @@ -72,19 +64,15 @@ Imported from: AT-AT CI - login--> - - + @@ -94,34 +82,44 @@ Imported from: AT-AT CI - New Portfolio--> - - + - - + + - + + + + + + + + + + + + + + + + @@ -138,65 +136,17 @@ Imported from: AT-AT CI - New Portfolio--> - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + @@ -204,210 +154,8 @@ Imported from: AT-AT CI - New Portfolio--> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -415,74 +163,26 @@ Imported from: AT-AT CI - New Portfolio--> + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -490,12 +190,8 @@ Imported from: AT-AT CI - New Portfolio--> - + @@ -511,41 +207,16 @@ Imported from: AT-AT CI - TO Step 1--> - + - + - - - - - - - - - - - - - - - - - + - + @@ -553,39 +224,14 @@ Imported from: AT-AT CI - TO Step 1--> - - - - - - - - - - - - - - - - - + - + @@ -595,12 +241,8 @@ Imported from: AT-AT CI - TO Step 1--> - + @@ -609,20 +251,16 @@ Imported from: AT-AT CI - TO Step 1--> - + - + @@ -633,32 +271,8 @@ This is Ghost Inspector flow control. The test will wait until the file is uploa - - - - - - - - - - - - - - - - - + @@ -674,31 +288,8 @@ Imported from: AT-AT CI - TO Step 2--> - - - - - - - - - - - - - - - - - + @@ -714,30 +305,8 @@ Imported from: AT-AT CI - TO Step 2--> - - - - - - - - - - - - - - - - - + @@ -753,29 +322,8 @@ Imported from: AT-AT CI - TO Step 3--> - - - - - - - - - - - - - - - - - + @@ -791,29 +339,8 @@ Imported from: AT-AT CI - TO Step 3--> - - - - - - - - - - - - - - - - - + @@ -829,29 +356,8 @@ Imported from: AT-AT CI - TO Step 3--> - - - - - - - - - - - - - - - - - + @@ -867,10 +373,8 @@ Imported from: AT-AT CI - TO Step 3--> - + @@ -886,48 +390,8 @@ Imported from: AT-AT CI - TO Step 3--> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -943,10 +407,8 @@ Imported from: AT-AT CI - TO Step 3--> - + @@ -955,17 +417,15 @@ Imported from: AT-AT CI - TO Step 3--> - + - + @@ -981,10 +441,8 @@ Imported from: AT-AT CI - TO Step 3--> - + @@ -993,17 +451,15 @@ Imported from: AT-AT CI - TO Step 3--> - + - + @@ -1019,10 +475,8 @@ Imported from: AT-AT CI - TO Step 3--> - + @@ -1038,18 +492,16 @@ Imported from: AT-AT CI - TO Step 3--> - + - + - + @@ -1057,28 +509,8 @@ Imported from: AT-AT CI - TO Step 3--> - - - - - - - - - - - - - - - - - + @@ -1094,104 +526,14 @@ Imported from: AT-AT CI - TO Step 4--> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + @@ -1201,31 +543,14 @@ Imported from: AT-AT CI - TO Step 5--> - - - - - - - - - - - - - - - - - + - + @@ -1235,8 +560,8 @@ Imported from: AT-AT CI - TO Step 5--> - + @@ -1252,8 +577,8 @@ Imported from: AT-AT CI - TO Step 5--> - + @@ -1269,66 +594,15 @@ Imported from: AT-AT CI - TO Step 5--> - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + @@ -1336,7 +610,7 @@ Imported from: AT-AT CI - TO Step 5--> - + @@ -1352,7 +626,7 @@ Imported from: AT-AT CI - TO Step 5--> - + @@ -1368,7 +642,7 @@ Imported from: AT-AT CI - TO Step 5--> - + @@ -1386,7 +660,7 @@ Imported from: AT-AT CI - TO Step 5--> - + @@ -1402,6 +676,118 @@ Imported from: AT-AT CI - TO Step 5--> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/uitests/Reports_-_Follow_TO_link.html b/uitests/Reports_-_Follow_TO_link.html index c55ace64..8af494c1 100644 --- a/uitests/Reports_-_Follow_TO_link.html +++ b/uitests/Reports_-_Follow_TO_link.html @@ -16,7 +16,7 @@ - +
waitForElementPresent css=a[href="/portfolios/new"]
click css=a[href="/portfolios/new"]
waitForElementPresentcss=main.usa-section > h1css=.portfolio-header__name > h1
assertTextcss=main.usa-section > h1*New Portfolio Form*css=.portfolio-header__name > h1*New Portfolio*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Create New Portfolio*
waitForPageToLoad
waitForElementPresent
waitForElementPresentcss=#defense_componentcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
typecss=#defense_componentDefense Logistics Agency
waitForPageToLoad
waitForElementPresentcss=#description
typecss=#descriptionMaintenance and monitoring of the energy grid
waitForPageToLoad
waitForElementPresentcss=#app_migration > li:nth-of-type(3) > label
clickcss=#app_migration > li:nth-of-type(3) > labelcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForElementPresentcss=#native_apps > li:nth-of-type(1) > label
clickcss=#native_apps > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#team_experience > li:nth-of-type(5) > label
clickcss=#team_experience > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresent
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.empty-state > h3
assertTextcss=input[type="submit"]Save
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.portfolio-header__name > h1
assertTextcss=.portfolio-header__name > h1*Tatooine Energy Maintenance Systems*
waitForPageToLoad
waitForElementPresentcss=.empty-state h3
assertTextcss=.empty-state h3css=.empty-state > h3 *You don't have any Applications yet*
waitForElementPresent css=.icon--funding
waitForElementPresentcss=.sticky-cta-text h3css=.sticky-cta-buttons > .usa-button.usa-button-primary
assertTextcss=.sticky-cta-text h3*Task Orders*
waitForPageToLoad
waitForElementPresentcss=.usa-button.usa-button-primary
clickcss=.usa-button.usa-button-primarycss=.sticky-cta-buttons > .usa-button.usa-button-primary
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Add Task Order (step 1 of 5)*
waitForPageToLoad
waitForElementPresent css=.upload-button
click css=.upload-button
waitForElementPresent css=#pdf
type css=#pdfhttps://ghostinspector-prod.s3.amazonaws.com/uploads/726e1c95-2d16-4793-85d8-b4d3ae9cd35d.pdfhttps://ghostinspector-prod.s3.amazonaws.com/uploads/310638bb-42fd-4158-b14f-417826ae4f79.pdf
waitForPageToLoad
assertElementNotPresent css=input[type="submit"][disabled="disabled"]
waitForElementPresentcss=a[href="#"].uploaded-file__remove
assertTextcss=a[href="#"].uploaded-file__remove*Remove*
waitForPageToLoad
waitForElementPresent css=input[type="submit"]
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Add Task Order (step 2 of 5)*
waitForPageToLoad
waitForElementPresent css=#number
waitForElementPresentcss=svg.svg-inline--fa.fa-check-circle > path
assertElementPresentcss=svg.svg-inline--fa.fa-check-circle > path
waitForPageToLoad
waitForElementPresent css=input[type="submit"]
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Add Task Order (step 3 of 5)*
waitForPageToLoad
waitForElementPresent css=#clins-0-number
waitForElementPresentcss=.card__title > .h4
assertTextcss=.card__title > .h4*CLIN 0002*
waitForPageToLoad
waitForElementPresent css=#clins-0-jedi_clin_type
waitForElementPresentcss=#percent-obligated
assertTextcss=#percent-obligated*0%*
waitForPageToLoad
waitForElementPresent css=#clins-0-total_amount
waitForElementPresent css=#clins-0-obligated_amount
waitForElementPresentcss=#percent-obligated
assertTextcss=#percent-obligated*13%*
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
clickcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
waitForPageToLoad
waitForElementPresent css=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
waitForElementPresent css=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
type css=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]011
waitForPageToLoad
waitForElementPresent css=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]
waitForElementPresent css=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
type css=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]066
waitForPageToLoad
waitForElementPresent css=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
waitForElementPresent css=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]css=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
clickcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]css=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > div:nth-of-type(4) > .usa-form-group-date-ok > .icon.icon--ok.icon--green > svg.svg-inline--fa.fa-check-circle.fa-w-16
assertElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > div:nth-of-type(4) > .usa-form-group-date-ok > .icon.icon--ok.icon--green > svg.svg-inline--fa.fa-check-circle.fa-w-16
waitForPageToLoad
waitForElementPresent css=input[type="submit"]
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Add Task Order (step 4 of 5)*
waitForPageToLoad
waitForElementPresentcss=.totals-box > .h3:nth-of-type(2)
assertTextcss=.totals-box > .h3:nth-of-type(2)*$100,000.00*
waitForPageToLoad
waitForElementPresentcss=.totals-box > .h3:nth-of-type(4)
assertTextcss=.totals-box > .h3:nth-of-type(4)*$800,000.00*
waitForPageToLoad
waitForElementPresentcss=.col.task-order__details > div:nth-of-type(2)
assertElementPresentcss=.col.task-order__details > div:nth-of-type(2)
waitForPageToLoad
waitForElementPresentcss=table.fixed-table-wrapper > thead > tr > th.task-order__amount:nth-of-type(6)
assertTextcss=table.fixed-table-wrapper > thead > tr > th.task-order__amount:nth-of-type(6)*Amount Obligated*
waitForPageToLoad
waitForElementPresent css=a.usa-button.usa-button-primary
click css=a.usa-button.usa-button-primary
waitForElementPresentcss=.h2
assertTextcss=.h2*Confirm Signature*
waitForPageToLoad
waitForElementPresent css=fieldset.usa-input__choices > legend > label
click css=fieldset.usa-input__choices > legend > label
waitForElementPresent css=input[type="submit"]
waitForElementPresent css=h3.usa-alert-heading
waitForElementPresentcss=.usa-alert-text
assertTextcss=.usa-alert-text*Your task order form for Tatooine Energy Maintenance Systems has been submitted.*
waitForPageToLoad
waitForElementPresentcss=.portfolio-funding
assertElementPresentcss=.portfolio-funding
waitForPageToLoad
waitForElementPresentcss=.action-group
assertElementPresentcss=.action-group
waitForPageToLoad
waitForElementPresentcss=.icon.icon--chart-pie > svgcss=.icon.icon--chart-pie
clickcss=.icon.icon--chart-pie > svgcss=.icon.icon--chart-pie
waitForElementPresent css=.sticky-cta-text > h3
waitForElementPresent css=.row > .col.col--grow.reporting-summary-item:nth-of-type(1) > .reporting-summary-item__value
waitForElementPresent css=.row > .col.col--grow.reporting-summary-item:nth-of-type(2) > .reporting-summary-item__value
waitForElementPresent css=.row > .col.col--grow.reporting-summary-item:nth-of-type(3) > h5.reporting-summary-item__header > .reporting-summary-item__header-text
waitForElementPresentcss=h3.h5
assertTextcss=h3.h5*IDIQ CLIN 0002 Classified IaaS/PaaS*
waitForPageToLoad
waitForElementPresentcss=.jedi-clin-funding__subheader
assertTextcss=.jedi-clin-funding__subheader*Total obligated amount: $100,000.00*
waitForPageToLoad
waitForElementPresentcss=.jedi-clin-funding__graph-values
assertElementPresentcss=.jedi-clin-funding__graph-values
waitForPageToLoad
waitForElementPresentcss=.jedi-clin-funding__graph-values > .jedi-clin-funding__meta:nth-of-type(3) > .h3.jedi-clin-funding__meta-value
assertTextcss=.jedi-clin-funding__graph-values > .jedi-clin-funding__meta:nth-of-type(3) > .h3.jedi-clin-funding__meta-value*$100,000.00*
waitForPageToLoad
waitForElementPresentcss=h3.h4
assertTextcss=h3.h4*Active Task Orders*
waitForPageToLoad
waitForElementPresentcss=.jedi-clin-funding__active-task-orders
assertElementPresentcss=.jedi-clin-funding__active-task-orders
waitForPageToLoad
waitForElementPresentcss=button.usa-accordion-button
clickcss=button.usa-accordion-button
waitForPageToLoad
waitForElementPresent css=div.empty-state__footer > a
@@ -31,12 +31,8 @@ - @@ -49,12 +45,8 @@ Imported from: AT-AT CI - login--> - @@ -72,19 +64,15 @@ Imported from: AT-AT CI - login--> - - + @@ -94,34 +82,44 @@ Imported from: AT-AT CI - New Portfolio--> - - + - - + + - + + + + + + + + + + + + + + + + @@ -138,65 +136,17 @@ Imported from: AT-AT CI - New Portfolio--> - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + @@ -204,210 +154,8 @@ Imported from: AT-AT CI - New Portfolio--> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -415,74 +163,26 @@ Imported from: AT-AT CI - New Portfolio--> + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -490,12 +190,8 @@ Imported from: AT-AT CI - New Portfolio--> - + @@ -511,41 +207,16 @@ Imported from: AT-AT CI - TO Step 1--> - + - + - - - - - - - - - - - - - - - - - + - + @@ -553,39 +224,14 @@ Imported from: AT-AT CI - TO Step 1--> - - - - - - - - - - - - - - - - - + - + @@ -595,12 +241,8 @@ Imported from: AT-AT CI - TO Step 1--> - + @@ -609,20 +251,16 @@ Imported from: AT-AT CI - TO Step 1--> - + - + @@ -633,32 +271,8 @@ This is Ghost Inspector flow control. The test will wait until the file is uploa - - - - - - - - - - - - - - - - - + @@ -674,31 +288,8 @@ Imported from: AT-AT CI - TO Step 2--> - - - - - - - - - - - - - - - - - + @@ -714,30 +305,8 @@ Imported from: AT-AT CI - TO Step 2--> - - - - - - - - - - - - - - - - - + @@ -753,29 +322,8 @@ Imported from: AT-AT CI - TO Step 3--> - - - - - - - - - - - - - - - - - + @@ -791,29 +339,8 @@ Imported from: AT-AT CI - TO Step 3--> - - - - - - - - - - - - - - - - - + @@ -829,29 +356,8 @@ Imported from: AT-AT CI - TO Step 3--> - - - - - - - - - - - - - - - - - + @@ -867,10 +373,8 @@ Imported from: AT-AT CI - TO Step 3--> - + @@ -886,48 +390,8 @@ Imported from: AT-AT CI - TO Step 3--> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -943,10 +407,8 @@ Imported from: AT-AT CI - TO Step 3--> - + @@ -955,17 +417,15 @@ Imported from: AT-AT CI - TO Step 3--> - + - + @@ -981,10 +441,8 @@ Imported from: AT-AT CI - TO Step 3--> - + @@ -993,17 +451,15 @@ Imported from: AT-AT CI - TO Step 3--> - + - + @@ -1019,10 +475,8 @@ Imported from: AT-AT CI - TO Step 3--> - + @@ -1038,18 +492,16 @@ Imported from: AT-AT CI - TO Step 3--> - + - + - + @@ -1057,28 +509,8 @@ Imported from: AT-AT CI - TO Step 3--> - - - - - - - - - - - - - - - - - + @@ -1094,104 +526,14 @@ Imported from: AT-AT CI - TO Step 4--> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + @@ -1201,31 +543,14 @@ Imported from: AT-AT CI - TO Step 5--> - - - - - - - - - - - - - - - - - + - + @@ -1235,8 +560,8 @@ Imported from: AT-AT CI - TO Step 5--> - + @@ -1252,8 +577,8 @@ Imported from: AT-AT CI - TO Step 5--> - + @@ -1269,66 +594,15 @@ Imported from: AT-AT CI - TO Step 5--> - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + @@ -1336,7 +610,7 @@ Imported from: AT-AT CI - TO Step 5--> - + @@ -1352,7 +626,7 @@ Imported from: AT-AT CI - TO Step 5--> - + @@ -1368,7 +642,7 @@ Imported from: AT-AT CI - TO Step 5--> - + @@ -1386,7 +660,7 @@ Imported from: AT-AT CI - TO Step 5--> - + @@ -1402,6 +676,118 @@ Imported from: AT-AT CI - TO Step 5--> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/uitests/login.html b/uitests/login.html index 3a95da4d..764b248f 100644 --- a/uitests/login.html +++ b/uitests/login.html @@ -16,7 +16,7 @@ - +
waitForElementPresent css=a[href="/portfolios/new"]
click css=a[href="/portfolios/new"]
waitForElementPresentcss=main.usa-section > h1css=.portfolio-header__name > h1
assertTextcss=main.usa-section > h1*New Portfolio Form*css=.portfolio-header__name > h1*New Portfolio*
waitForPageToLoad
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Create New Portfolio*
waitForPageToLoad
waitForElementPresent
waitForElementPresentcss=#defense_componentcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
typecss=#defense_componentDefense Logistics Agency
waitForPageToLoad
waitForElementPresentcss=#description
typecss=#descriptionMaintenance and monitoring of the energy grid
waitForPageToLoad
waitForElementPresentcss=#app_migration > li:nth-of-type(3) > label
clickcss=#app_migration > li:nth-of-type(3) > labelcss=fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForElementPresentcss=#native_apps > li:nth-of-type(1) > label
clickcss=#native_apps > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(1) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(4) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(6) > fieldset.usa-input__choices > ul > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
clickcss=#portfolio-create > .usa-input:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(2) > label
waitForPageToLoad
waitForElementPresentcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
clickcss=#portfolio-create > .usa-input.usa-input--success:nth-of-type(7) > fieldset.usa-input__choices > ul > li:nth-of-type(3) > label
waitForPageToLoad
waitForElementPresentcss=#team_experience > li:nth-of-type(5) > label
clickcss=#team_experience > li:nth-of-type(5) > label
waitForPageToLoad
waitForElementPresent
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.empty-state > h3
assertTextcss=input[type="submit"]Save
waitForPageToLoad
waitForElementPresentcss=input[type="submit"]
clickcss=input[type="submit"]
waitForPageToLoad
waitForElementPresentcss=.portfolio-header__name > h1
assertTextcss=.portfolio-header__name > h1*Tatooine Energy Maintenance Systems*
waitForPageToLoad
waitForElementPresentcss=.empty-state h3
assertTextcss=.empty-state h3css=.empty-state > h3 *You don't have any Applications yet*
waitForElementPresent css=.icon--funding
waitForElementPresentcss=.sticky-cta-text h3css=.sticky-cta-buttons > .usa-button.usa-button-primary
assertTextcss=.sticky-cta-text h3*Task Orders*
waitForPageToLoad
waitForElementPresentcss=.usa-button.usa-button-primary
clickcss=.usa-button.usa-button-primarycss=.sticky-cta-buttons > .usa-button.usa-button-primary
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Add Task Order (step 1 of 5)*
waitForPageToLoad
waitForElementPresent css=.upload-button
click css=.upload-button
waitForElementPresent css=#pdf
type css=#pdfhttps://ghostinspector-prod.s3.amazonaws.com/uploads/726e1c95-2d16-4793-85d8-b4d3ae9cd35d.pdfhttps://ghostinspector-prod.s3.amazonaws.com/uploads/310638bb-42fd-4158-b14f-417826ae4f79.pdf
waitForPageToLoad
assertElementNotPresent css=input[type="submit"][disabled="disabled"]
waitForElementPresentcss=a[href="#"].uploaded-file__remove
assertTextcss=a[href="#"].uploaded-file__remove*Remove*
waitForPageToLoad
waitForElementPresent css=input[type="submit"]
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Add Task Order (step 2 of 5)*
waitForPageToLoad
waitForElementPresent css=#number
waitForElementPresentcss=svg.svg-inline--fa.fa-check-circle > path
assertElementPresentcss=svg.svg-inline--fa.fa-check-circle > path
waitForPageToLoad
waitForElementPresent css=input[type="submit"]
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Add Task Order (step 3 of 5)*
waitForPageToLoad
waitForElementPresent css=#clins-0-number
waitForElementPresentcss=.card__title > .h4
assertTextcss=.card__title > .h4*CLIN 0002*
waitForPageToLoad
waitForElementPresent css=#clins-0-jedi_clin_type
waitForElementPresentcss=#percent-obligated
assertTextcss=#percent-obligated*0%*
waitForPageToLoad
waitForElementPresent css=#clins-0-total_amount
waitForElementPresent css=#clins-0-obligated_amount
waitForElementPresentcss=#percent-obligated
assertTextcss=#percent-obligated*13%*
waitForPageToLoad
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
clickcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
waitForPageToLoad
waitForElementPresent css=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
waitForElementPresent css=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
type css=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]011
waitForPageToLoad
waitForElementPresent css=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]
waitForElementPresent css=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]
type css=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]066
waitForPageToLoad
waitForElementPresent css=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
waitForElementPresent css=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-year > input[name="date-year"]
waitForElementPresentcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]css=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
clickcss=fieldset[name="clins-0-start_date"] > .date-picker-component > .usa-form-group.usa-form-group-month > input[name="date-month"]css=fieldset[name="clins-0-end_date"] > .date-picker-component > .usa-form-group.usa-form-group-day > input[name="date-day"]
waitForElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > div:nth-of-type(4) > .usa-form-group-date-ok > .icon.icon--ok.icon--green > svg.svg-inline--fa.fa-check-circle.fa-w-16
assertElementPresentcss=fieldset[name="clins-0-end_date"] > .date-picker-component > div:nth-of-type(4) > .usa-form-group-date-ok > .icon.icon--ok.icon--green > svg.svg-inline--fa.fa-check-circle.fa-w-16
waitForPageToLoad
waitForElementPresent css=input[type="submit"]
waitForElementPresentcss=.sticky-cta-text > h3
assertTextcss=.sticky-cta-text > h3*Add Task Order (step 4 of 5)*
waitForPageToLoad
waitForElementPresentcss=.totals-box > .h3:nth-of-type(2)
assertTextcss=.totals-box > .h3:nth-of-type(2)*$100,000.00*
waitForPageToLoad
waitForElementPresentcss=.totals-box > .h3:nth-of-type(4)
assertTextcss=.totals-box > .h3:nth-of-type(4)*$800,000.00*
waitForPageToLoad
waitForElementPresentcss=.col.task-order__details > div:nth-of-type(2)
assertElementPresentcss=.col.task-order__details > div:nth-of-type(2)
waitForPageToLoad
waitForElementPresentcss=table.fixed-table-wrapper > thead > tr > th.task-order__amount:nth-of-type(6)
assertTextcss=table.fixed-table-wrapper > thead > tr > th.task-order__amount:nth-of-type(6)*Amount Obligated*
waitForPageToLoad
waitForElementPresent css=a.usa-button.usa-button-primary
click css=a.usa-button.usa-button-primary
waitForElementPresentcss=.h2
assertTextcss=.h2*Confirm Signature*
waitForPageToLoad
waitForElementPresent css=fieldset.usa-input__choices > legend > label
click css=fieldset.usa-input__choices > legend > label
waitForElementPresent css=input[type="submit"]
waitForElementPresent css=h3.usa-alert-heading
waitForElementPresentcss=.usa-alert-text
assertTextcss=.usa-alert-text*Your task order form for Tatooine Energy Maintenance Systems has been submitted.*
waitForPageToLoad
waitForElementPresentcss=.portfolio-funding
assertElementPresentcss=.portfolio-funding
waitForPageToLoad
waitForElementPresentcss=.action-group
assertElementPresentcss=.action-group
waitForPageToLoad
waitForElementPresentcss=.icon.icon--chart-pie > svgcss=.icon.icon--chart-pie
clickcss=.icon.icon--chart-pie > svgcss=.icon.icon--chart-pie
waitForElementPresent css=.sticky-cta-text > h3
waitForElementPresent css=.row > .col.col--grow.reporting-summary-item:nth-of-type(1) > .reporting-summary-item__value
waitForElementPresent css=.row > .col.col--grow.reporting-summary-item:nth-of-type(2) > .reporting-summary-item__value
waitForElementPresent css=.row > .col.col--grow.reporting-summary-item:nth-of-type(3) > h5.reporting-summary-item__header > .reporting-summary-item__header-text
waitForElementPresentcss=h3.h5
assertTextcss=h3.h5*IDIQ CLIN 0002 Classified IaaS/PaaS*
waitForPageToLoad
waitForElementPresentcss=.jedi-clin-funding__subheader
assertTextcss=.jedi-clin-funding__subheader*Total obligated amount: $100,000.00*
waitForPageToLoad
waitForElementPresentcss=.jedi-clin-funding__graph-values
assertElementPresentcss=.jedi-clin-funding__graph-values
waitForPageToLoad
waitForElementPresentcss=.jedi-clin-funding__graph-values > .jedi-clin-funding__meta:nth-of-type(3) > .h3.jedi-clin-funding__meta-value
assertTextcss=.jedi-clin-funding__graph-values > .jedi-clin-funding__meta:nth-of-type(3) > .h3.jedi-clin-funding__meta-value*$100,000.00*
waitForPageToLoad
waitForElementPresentcss=h3.h4
assertTextcss=h3.h4*Active Task Orders*
waitForPageToLoad
waitForElementPresentcss=.jedi-clin-funding__active-task-orders
assertElementPresentcss=.jedi-clin-funding__active-task-orders
waitForPageToLoad
waitForElementPresentcss=button.usa-accordion-button
clickcss=button.usa-accordion-button
waitForPageToLoad
waitForElementPresent css=div.jedi-clin-funding__active-task-orders > a
From 13e8cb8ee108c213423cb702e399e0c24687f9c5 Mon Sep 17 00:00:00 2001 From: graham-dds Date: Tue, 17 Dec 2019 16:43:35 -0500 Subject: [PATCH 031/114] Move form buttons to floating bottom action bar Form action buttons were previously in the sicky CTA bar. This commit moves them to a bottom action bar. --- styles/elements/_action_group.scss | 2 +- templates/home.html | 11 ++----- templates/task_orders/builder_base.html | 39 +++++++++++++------------ templates/task_orders/step_1.html | 1 - translations.yaml | 3 +- 5 files changed, 26 insertions(+), 30 deletions(-) diff --git a/styles/elements/_action_group.scss b/styles/elements/_action_group.scss index 1f79f7d2..73cad181 100644 --- a/styles/elements/_action_group.scss +++ b/styles/elements/_action_group.scss @@ -46,7 +46,7 @@ background: white; right: 0; padding-right: $gap * 4; - border-top: 1px solid $color-gray-light; + border-top: 1px solid $color-gray-lighter; width: 100%; z-index: 1; } diff --git a/templates/home.html b/templates/home.html index 4e459639..aadcd2a8 100644 --- a/templates/home.html +++ b/templates/home.html @@ -13,12 +13,6 @@ {% set sticky_header = "home.get_started" | translate %} {% endif %} - {% call StickyCTA(sticky_header) %} - - {{ "home.add_portfolio_button_text" | translate }} - - {% endcall %} -
{% include "fragments/flash.html" %} @@ -92,9 +86,10 @@
- - JEDI heirarchy diagram + + {{ "home.add_portfolio_button_text" | translate }} + diff --git a/templates/task_orders/builder_base.html b/templates/task_orders/builder_base.html index 362a1038..70bc20c9 100644 --- a/templates/task_orders/builder_base.html +++ b/templates/task_orders/builder_base.html @@ -8,8 +8,26 @@
{{ form.csrf_token }} - {% call StickyCTA(text=('task_orders.form.sticky_header_text' | translate({"step": step}) )) %} - + {{ StickyCTA( + text='task_orders.form.sticky_header_text' | translate, + context=('task_orders.form.sticky_header_context' | translate({"step": step}) )) }} + + {% call Modal(name='cancel', dismissable=True) %} +
+

Do you want to save this draft?

+
+ + +
+
+ {% endcall %} + + {% include "fragments/flash.html" %} + +
+ {% block to_builder_form_field %}{% endblock %} +
+ {% block next_button %} - {% endcall %} - - {% call Modal(name='cancel', dismissable=True) %} -
-

Do you want to save this draft?

-
- - -
-
- {% endcall %} - - {% include "fragments/flash.html" %} - -
- {% block to_builder_form_field %}{% endblock %} -
diff --git a/templates/task_orders/step_1.html b/templates/task_orders/step_1.html index 758099fa..6be3218c 100644 --- a/templates/task_orders/step_1.html +++ b/templates/task_orders/step_1.html @@ -1,7 +1,6 @@ {% extends "task_orders/builder_base.html" %} {% from 'components/icon.html' import Icon %} -{% from "components/sticky_cta.html" import StickyCTA %} {% from "task_orders/form_header.html" import TOFormStepHeader %} {% from 'components/upload_input.html' import UploadInput %} diff --git a/translations.yaml b/translations.yaml index 6a678f48..8fe26475 100644 --- a/translations.yaml +++ b/translations.yaml @@ -526,7 +526,8 @@ task_orders: description: Finally, plase confirm that your uploaded document representing the information you've entered contains the required signature from your Contracting Officer. You will be informed as soon as CCPO completes their review. alert_message: All task orders require a Contracting Officer signature. next_button: 'Confirm & Submit' - sticky_header_text: 'Add Task Order (step {step} of 5)' + sticky_header_text: 'Add Task Order' + sticky_header_context: 'Step {step} of 5' empty_state: header: Add approved task orders message: Upload your approved Task Order here. You are required to confirm you have the appropriate signature. You will have the ability to add additional approved Task Orders with more funding to this Portfolio in the future. From 66cfaaa6c3e5a30e82931a884df5083986276f82 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Wed, 18 Dec 2019 11:29:34 -0500 Subject: [PATCH 032/114] Update copy on TO signature page --- atst/forms/task_order.py | 3 +++ templates/task_orders/form_header.html | 10 ++++++---- templates/task_orders/step_5.html | 17 ++++++++++------- translations.yaml | 12 ++++++++---- 4 files changed, 27 insertions(+), 15 deletions(-) diff --git a/atst/forms/task_order.py b/atst/forms/task_order.py index a5e02e8b..1c324736 100644 --- a/atst/forms/task_order.py +++ b/atst/forms/task_order.py @@ -151,3 +151,6 @@ class SignatureForm(BaseForm): translate("task_orders.sign.digital_signature_description"), validators=[Required()], ) + confirm = BooleanField( + translate("task_orders.sign.confirmation_description"), validators=[Required()], + ) diff --git a/templates/task_orders/form_header.html b/templates/task_orders/form_header.html index 79821bf7..05f9116a 100644 --- a/templates/task_orders/form_header.html +++ b/templates/task_orders/form_header.html @@ -1,8 +1,10 @@ -{% macro TOFormStepHeader(title, description, to_number=None) %} +{% macro TOFormStepHeader(description, title=None, to_number=None) %}
-
- {{ title }} -
+ {% if title -%} +
+ {{ title }} +
+ {%- endif %} {% if to_number %}

Task Order Number: {{ to_number }} diff --git a/templates/task_orders/step_5.html b/templates/task_orders/step_5.html index 2d19c35b..365174d9 100644 --- a/templates/task_orders/step_5.html +++ b/templates/task_orders/step_5.html @@ -10,11 +10,14 @@ {% set step = "5" %} {% block to_builder_form_field %} - {{ TOFormStepHeader('task_orders.form.step_5.title' | translate, 'task_orders.form.step_5.description' | translate, task_order.number) }} - - {% call Alert('', - message="task_orders.form.step_5.alert_message" | translate - ) %} - {{ CheckboxInput(form.signature) }} - {% endcall %} + {{ TOFormStepHeader('task_orders.form.step_5.description' | translate, to_number=task_order.number) }} + {{ CheckboxInput(form.signature) }} + {{ CheckboxInput(form.confirm) }} +


+
+ {{ "task_orders.sign.acknowledge.title" | translate }} +
+

+ {{ "task_orders.sign.acknowledge.text" | translate }} +

{% endblock %} diff --git a/translations.yaml b/translations.yaml index 6a678f48..1efb8a29 100644 --- a/translations.yaml +++ b/translations.yaml @@ -199,7 +199,7 @@ forms:

- defense_component: + defense_component: label: "Select DoD component(s) funding your Portfolio:" choices: air_force: Air Force @@ -211,7 +211,7 @@ forms: help_text: |

Select the DOD component(s) that will fund all Applications within this Portfolio. - In JEDI, multiple DoD organizations can fund the same Portfolio.
+ In JEDI, multiple DoD organizations can fund the same Portfolio.
Select all that apply.

attachment: @@ -523,7 +523,7 @@ task_orders: next_button: 'Next: Review Task Order' step_5: title: Confirm Signature - description: Finally, plase confirm that your uploaded document representing the information you've entered contains the required signature from your Contracting Officer. You will be informed as soon as CCPO completes their review. + description: Prior to submitting the Task Order, you must acknowledge, by marking the appropriate box below, that the uploaded Task Order is signed by an appropriate, duly warranted Contracting Officer who has the authority to execute the uploaded Task Order on your Agency’s behalf and has authorized you to upload the Task Order in accordance with Agency policy and procedures. You must further acknowledge, by marking the appropriate box below, that all information entered herein matches that of the submitted Task Order. alert_message: All task orders require a Contracting Officer signature. next_button: 'Confirm & Submit' sticky_header_text: 'Add Task Order (step {step} of 5)' @@ -539,7 +539,11 @@ task_orders: subtitle: Who will be involved in the work funded by this task order? team_title: Your team sign: - digital_signature_description: I acknowledge that the uploaded task order contains the required KO signature. + digital_signature_description: I confirm the uploaded Task Order is signed by the appropriate, duly warranted Agency Contracting Officer who authorized me to upload the Task Order. + confirmation_description: I confirm that the information entered here in matches that of the submitted Task Order. + acknowledge: + title: Acknowledge Statement + text: I acknowledge, by executing the confirmation above and submitting this verification, that I am subject to potential penalties that may include fines, imprisonment, or both, under the U.S. law and regulations for any false statement or misrepresentation in association with this Task Order submission or on any accompanying documentation. status_empty_state: 'This Portfolio has no {status} Task Orders.' status_list_title: '{status} Task Orders' JEDICLINType: From 72bb3009131f2f4b79169b92a541a04b4a2f8434 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Wed, 18 Dec 2019 12:00:09 -0500 Subject: [PATCH 033/114] Styling for TO signature page --- styles/elements/_inputs.scss | 9 +++++++++ styles/sections/_task_order.scss | 9 +++++---- templates/task_orders/step_5.html | 6 ++++-- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/styles/elements/_inputs.scss b/styles/elements/_inputs.scss index 47cc4f3c..a5040e41 100644 --- a/styles/elements/_inputs.scss +++ b/styles/elements/_inputs.scss @@ -165,6 +165,15 @@ margin-top: 0; margin-bottom: 0; } + + label { + margin-left: 3rem; + + &:before { + position: absolute; + left: -3rem; + } + } } select { diff --git a/styles/sections/_task_order.scss b/styles/sections/_task_order.scss index 228bf126..c09f49a7 100644 --- a/styles/sections/_task_order.scss +++ b/styles/sections/_task_order.scss @@ -20,10 +20,7 @@ } &__header { - .h2, - p { - margin-bottom: $gap * 0.5; - } + margin-bottom: $gap * 6; } .col { @@ -155,6 +152,10 @@ } } } + + &__confirmation { + margin-left: $gap * 8; + } } .task-order__modal-cancel { diff --git a/templates/task_orders/step_5.html b/templates/task_orders/step_5.html index 365174d9..e5ce9189 100644 --- a/templates/task_orders/step_5.html +++ b/templates/task_orders/step_5.html @@ -11,8 +11,10 @@ {% block to_builder_form_field %} {{ TOFormStepHeader('task_orders.form.step_5.description' | translate, to_number=task_order.number) }} - {{ CheckboxInput(form.signature) }} - {{ CheckboxInput(form.confirm) }} +
+ {{ CheckboxInput(form.signature) }} + {{ CheckboxInput(form.confirm) }} +

{{ "task_orders.sign.acknowledge.title" | translate }} From 5b55b5800e26ba8c8f5c422e562444dd0c900419 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Wed, 18 Dec 2019 12:18:43 -0500 Subject: [PATCH 034/114] Remove route, tests, and template code for deleting an application --- atst/routes/applications/settings.py | 15 ------ templates/applications/settings.html | 53 +--------------------- tests/routes/applications/test_settings.py | 35 -------------- tests/test_access.py | 34 -------------- 4 files changed, 1 insertion(+), 136 deletions(-) diff --git a/atst/routes/applications/settings.py b/atst/routes/applications/settings.py index f2d252a9..7d5c20d4 100644 --- a/atst/routes/applications/settings.py +++ b/atst/routes/applications/settings.py @@ -337,21 +337,6 @@ def update(application_id): return render_settings_page(application=application, application_form=form) -@applications_bp.route("/applications//delete", methods=["POST"]) -@user_can(Permissions.DELETE_APPLICATION, message="delete application") -def delete(application_id): - application = Applications.get(application_id) - Applications.delete(application) - - flash("application_deleted", application_name=application.name) - - return redirect( - url_for( - "applications.portfolio_applications", portfolio_id=application.portfolio_id - ) - ) - - @applications_bp.route("/environments//delete", methods=["POST"]) @user_can(Permissions.DELETE_ENVIRONMENT, message="delete environment") def delete_environment(environment_id): diff --git a/templates/applications/settings.html b/templates/applications/settings.html index c8e41fcd..9d2fb146 100644 --- a/templates/applications/settings.html +++ b/templates/applications/settings.html @@ -59,59 +59,8 @@ environments_obj, new_env_form) }} - {% if user_can(permissions.DELETE_APPLICATION) %} - {% set env_count = application.environments | length %} - {% if env_count == 1 %} - {% set pluralized_env = "environment" %} - {% else %} - {% set pluralized_env = "environments" %} - {% endif %} - -

- {{ "portfolios.applications.delete.subheading" | translate }} -

-
-
- {{ "portfolios.applications.delete.text" | translate({"application_name": application.name}) | safe }} -
-
-
- -
-
-
- - {% call Modal(name="delete-application") %} -

{{ "portfolios.applications.delete.header" | translate }}

-
- {{ - Alert( - title=("components.modal.destructive_title" | translate), - message=("portfolios.applications.delete.alert.message" | translate), - level="warning" - ) - }} - - {{ - DeleteConfirmation( - modal_id="delete_application", - delete_text=('portfolios.applications.delete.button' | translate), - delete_action= url_for('applications.delete', application_id=application.id), - form=application_form - ) - }} - {% endcall %} - {% endif %} - -
- {% if user_can(permissions.VIEW_APPLICATION_ACTIVITY_LOG) and config.get("USE_AUDIT_LOG", False) %} +
{% include "fragments/audit_events_log.html" %} {{ Pagination(audit_events, url=url_for('applications.settings', application_id=application.id)) }} {% endif %} diff --git a/tests/routes/applications/test_settings.py b/tests/routes/applications/test_settings.py index 08c979ad..cd075c80 100644 --- a/tests/routes/applications/test_settings.py +++ b/tests/routes/applications/test_settings.py @@ -288,41 +288,6 @@ def test_user_can_only_access_apps_in_their_portfolio(client, user_session): assert time_updated == other_application.time_updated -def test_delete_application(client, user_session): - user = UserFactory.create() - port = PortfolioFactory.create( - owner=user, - applications=[ - { - "name": "mos eisley", - "environments": [ - {"name": "bar"}, - {"name": "booth"}, - {"name": "band stage"}, - ], - } - ], - ) - application = port.applications[0] - user_session(user) - - response = client.post( - url_for("applications.delete", application_id=application.id) - ) - # appropriate response and redirect - assert response.status_code == 302 - assert response.location == url_for( - "applications.portfolio_applications", portfolio_id=port.id, _external=True - ) - # appropriate flash message - message = get_flashed_messages()[0] - assert "deleted" in message["message"] - assert application.name in message["message"] - # app and envs are soft deleted - assert len(port.applications) == 0 - assert len(application.environments) == 0 - - def test_new_environment(client, user_session): user = UserFactory.create() portfolio = PortfolioFactory(owner=user) diff --git a/tests/test_access.py b/tests/test_access.py index ad4bd5be..5c8d5ae1 100644 --- a/tests/test_access.py +++ b/tests/test_access.py @@ -343,40 +343,6 @@ def test_portfolios_invite_member_access(post_url_assert_status): post_url_assert_status(rando, url, 404) -# applications.delete -def test_applications_delete_access(post_url_assert_status, monkeypatch): - ccpo = UserFactory.create_ccpo() - owner = user_with() - app_admin = user_with() - rando = user_with() - - portfolio = PortfolioFactory.create( - owner=owner, applications=[{"name": "mos eisley"}] - ) - application = portfolio.applications[0] - - ApplicationRoleFactory.create( - user=app_admin, - application=application, - permission_sets=PermissionSets.get_many( - [ - PermissionSets.VIEW_APPLICATION, - PermissionSets.EDIT_APPLICATION_ENVIRONMENTS, - PermissionSets.EDIT_APPLICATION_TEAM, - PermissionSets.DELETE_APPLICATION_ENVIRONMENTS, - ] - ), - ) - - monkeypatch.setattr("atst.domain.applications.Applications.delete", lambda *a: True) - - url = url_for("applications.delete", application_id=application.id) - post_url_assert_status(app_admin, url, 404) - post_url_assert_status(rando, url, 404) - post_url_assert_status(owner, url, 302) - post_url_assert_status(ccpo, url, 302) - - # applications.settings def test_application_settings_access(get_url_assert_status): ccpo = user_with(PermissionSets.VIEW_PORTFOLIO_APPLICATION_MANAGEMENT) From 2b884f2c855c40e6dba5a23e7b932b053806be44 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Wed, 18 Dec 2019 12:22:14 -0500 Subject: [PATCH 035/114] Remove route, tests, and template code for deleting a portfolio --- atst/routes/portfolios/index.py | 10 ----- templates/portfolios/admin.html | 6 +-- .../fragments/delete_portfolio.html | 42 ------------------- tests/routes/portfolios/test_index.py | 32 -------------- tests/test_access.py | 31 -------------- 5 files changed, 1 insertion(+), 120 deletions(-) delete mode 100644 templates/portfolios/fragments/delete_portfolio.html diff --git a/atst/routes/portfolios/index.py b/atst/routes/portfolios/index.py index 0447be57..f9e7d5cf 100644 --- a/atst/routes/portfolios/index.py +++ b/atst/routes/portfolios/index.py @@ -56,13 +56,3 @@ def reports(portfolio_id): monthly_spending=Reports.monthly_spending(portfolio), retrieved=datetime.now(), # mocked datetime of reporting data retrival ) - - -@portfolios_bp.route("/portfolios//destroy", methods=["POST"]) -@user_can(Permissions.ARCHIVE_PORTFOLIO, message="archive portfolio") -def delete_portfolio(portfolio_id): - Portfolios.delete(portfolio=g.portfolio) - - flash("portfolio_deleted", portfolio_name=g.portfolio.name) - - return redirect(url_for("atst.home")) diff --git a/templates/portfolios/admin.html b/templates/portfolios/admin.html index 5bfb7d7c..d1e6e353 100644 --- a/templates/portfolios/admin.html +++ b/templates/portfolios/admin.html @@ -56,14 +56,10 @@ {% include "portfolios/fragments/primary_point_of_contact.html" %} {% endif %} - {% if user_can(permissions.ARCHIVE_PORTFOLIO) %} - {% include "portfolios/fragments/delete_portfolio.html" %} - {% endif %} - {% if user_can(permissions.VIEW_PORTFOLIO_USERS) %} {% include "portfolios/fragments/portfolio_members.html" %} {% endif %} - + {% if user_can(permissions.VIEW_PORTFOLIO_ACTIVITY_LOG) and config.get("USE_AUDIT_LOG", False) %} {% include "fragments/audit_events_log.html" %} {{ Pagination(audit_events, url_for('portfolios.admin', portfolio_id=portfolio.id)) }} diff --git a/templates/portfolios/fragments/delete_portfolio.html b/templates/portfolios/fragments/delete_portfolio.html deleted file mode 100644 index da83b2e7..00000000 --- a/templates/portfolios/fragments/delete_portfolio.html +++ /dev/null @@ -1,42 +0,0 @@ -{% from "components/delete_confirmation.html" import DeleteConfirmation %} -{% from "components/alert.html" import Alert %} -{% from "components/modal.html" import Modal %} - -
-
-

{{ "fragments.delete_portfolio.title" | translate }}

-

{{ "fragments.delete_portfolio.subtitle" | translate }}

- - -
- {{ "common.deactivate" | translate }} -
-
-
- -{% call Modal(name="delete_portfolio") %} -

- {{ 'fragments.delete_portfolio.title' | translate }} -

-
- {{ - Alert( - level="warning", - title=('components.modal.destructive_title' | translate), - message=('components.modal.destructive_message' | translate({"resource": "portfolio"})), - ) - }} - - {{ - DeleteConfirmation( - modal_id='delete_portfolio', - delete_text='Deactivate', - delete_action=url_for('portfolios.delete_portfolio', portfolio_id=portfolio.id), - form=portfolio_form, - confirmation_text="deactivate", - ) - }} -{% endcall %} diff --git a/tests/routes/portfolios/test_index.py b/tests/routes/portfolios/test_index.py index 745430f0..489f73b2 100644 --- a/tests/routes/portfolios/test_index.py +++ b/tests/routes/portfolios/test_index.py @@ -84,35 +84,3 @@ def test_portfolio_reports_with_mock_portfolio(client, user_session): response = client.get(url_for("portfolios.reports", portfolio_id=portfolio.id)) assert response.status_code == 200 assert portfolio.name in response.data.decode() - - -def test_delete_portfolio_success(client, user_session): - portfolio = PortfolioFactory.create() - owner = portfolio.owner - user_session(owner) - - assert len(Portfolios.for_user(user=owner)) == 1 - - response = client.post( - url_for("portfolios.delete_portfolio", portfolio_id=portfolio.id) - ) - - assert response.status_code == 302 - assert url_for("atst.home") in response.location - assert len(Portfolios.for_user(user=owner)) == 0 - - -def test_delete_portfolio_failure(no_debug_client, user_session): - portfolio = PortfolioFactory.create() - application = ApplicationFactory.create(portfolio=portfolio) - owner = portfolio.owner - user_session(owner) - - assert len(Portfolios.for_user(user=owner)) == 1 - - response = no_debug_client.post( - url_for("portfolios.delete_portfolio", portfolio_id=portfolio.id) - ) - - assert response.status_code == 500 - assert len(Portfolios.for_user(user=owner)) == 1 diff --git a/tests/test_access.py b/tests/test_access.py index 5c8d5ae1..1adcb65d 100644 --- a/tests/test_access.py +++ b/tests/test_access.py @@ -665,34 +665,3 @@ def test_task_orders_new_post_routes(post_url_assert_status): post_url_assert_status(owner, url, 302, data=data) post_url_assert_status(ccpo, url, 302, data=data) post_url_assert_status(rando, url, 404, data=data) - - -def test_portfolio_delete_access(post_url_assert_status): - rando = UserFactory.create() - owner = UserFactory.create() - ccpo = UserFactory.create_ccpo() - - post_url_assert_status( - ccpo, - url_for( - "portfolios.delete_portfolio", portfolio_id=PortfolioFactory.create().id - ), - 302, - ) - - post_url_assert_status( - owner, - url_for( - "portfolios.delete_portfolio", - portfolio_id=PortfolioFactory.create(owner=owner).id, - ), - 302, - ) - - post_url_assert_status( - rando, - url_for( - "portfolios.delete_portfolio", portfolio_id=PortfolioFactory.create().id - ), - 404, - ) From 83690ccf1a22266e2e03dee414fd1710ba0562fa Mon Sep 17 00:00:00 2001 From: Rob Gil Date: Wed, 18 Dec 2019 15:14:22 -0500 Subject: [PATCH 036/114] 169163334 - Adds redis module Adds basic redis module. --- terraform/modules/redis/main.tf | 24 +++++++++++ terraform/modules/redis/outputs.tf | 0 terraform/modules/redis/variables.tf | 60 ++++++++++++++++++++++++++++ terraform/providers/dev/redis.tf | 7 ++++ 4 files changed, 91 insertions(+) create mode 100644 terraform/modules/redis/main.tf create mode 100644 terraform/modules/redis/outputs.tf create mode 100644 terraform/modules/redis/variables.tf create mode 100644 terraform/providers/dev/redis.tf diff --git a/terraform/modules/redis/main.tf b/terraform/modules/redis/main.tf new file mode 100644 index 00000000..1e47f767 --- /dev/null +++ b/terraform/modules/redis/main.tf @@ -0,0 +1,24 @@ +resource "azurerm_resource_group" "redis" { + name = "${var.name}-${var.environment}-redis" + location = var.region +} + +# NOTE: the Name used for Redis needs to be globally unique +resource "azurerm_redis_cache" "redis" { + name = "${var.name}-${var.environment}-redis" + location = azurerm_resource_group.redis.location + resource_group_name = azurerm_resource_group.redis.name + capacity = var.capacity + family = var.family + sku_name = var.sku_name + enable_non_ssl_port = var.enable_non_ssl_port + minimum_tls_version = var.minimum_tls_version + + redis_configuration { + enable_authentication = var.enable_authentication + } + tags = { + environment = var.environment + owner = var.owner + } +} diff --git a/terraform/modules/redis/outputs.tf b/terraform/modules/redis/outputs.tf new file mode 100644 index 00000000..e69de29b diff --git a/terraform/modules/redis/variables.tf b/terraform/modules/redis/variables.tf new file mode 100644 index 00000000..ecdb7636 --- /dev/null +++ b/terraform/modules/redis/variables.tf @@ -0,0 +1,60 @@ +variable "region" { + type = string + description = "Region this module and resources will be created in" +} + +variable "name" { + type = string + description = "Unique name for the services in this module" +} + +variable "environment" { + type = string + description = "Environment these resources reside (prod, dev, staging, etc)" +} + +variable "owner" { + type = string + description = "Owner of the environment and resources created in this module" +} + +variable "capacity" { + type = string + default = 2 + description = "The capacity of the redis cache" + +} + +variable "family" { + type = string + default = "C" + description = "The subscription family for redis" + +} + +variable "sku_name" { + type = string + default = "Standard" + description = "The sku to use" + +} + +variable "enable_non_ssl_port" { + type = bool + default = false + description = "Enable non TLS port (default: false)" + +} + +variable "minimum_tls_version" { + type = string + default = "1.2" + description = "Minimum TLS version to use" + +} + +variable "enable_authentication" { + type = bool + default = true + description = "Enable or disable authentication (default: true)" +} diff --git a/terraform/providers/dev/redis.tf b/terraform/providers/dev/redis.tf new file mode 100644 index 00000000..fca3a4e3 --- /dev/null +++ b/terraform/providers/dev/redis.tf @@ -0,0 +1,7 @@ +module "redis" { + source = "../../modules/redis" + owner = var.owner + environment = var.environment + region = var.region + name = var.name +} From d247620c514eb2c15cc93c98241555dd02a3f4b3 Mon Sep 17 00:00:00 2001 From: graham-dds Date: Wed, 18 Dec 2019 12:04:38 -0500 Subject: [PATCH 037/114] Slience output from curl for integration tests We use curl in our integration test script to make sure the application container is available before moving on. We expect many connection errors and don't care about the output of curl, so this will just swallow all of the output. --- script/integration_tests | 7 +++++-- uitests/README.md | 1 - 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/script/integration_tests b/script/integration_tests index e84b103a..cb0d813a 100755 --- a/script/integration_tests +++ b/script/integration_tests @@ -72,15 +72,18 @@ $CONTAINER_IMAGE \ # Use curl to wait for application container to become available docker pull curlimages/curl:latest +echo "Waiting for application container to become available" docker run --network atat \ curlimages/curl:latest \ - curl --connect-timeout 3 \ + curl \ + --silent \ + --connect-timeout 3 \ --max-time 5 \ --retry $CONTAINER_TIMEOUT \ --retry-connrefused \ --retry-delay 1 \ --retry-max-time $CONTAINER_TIMEOUT \ - test-atat:8000 + test-atat:8000 >/dev/null # Run Ghost Inspector tests docker pull ghostinspector/test-runner-standalone:latest diff --git a/uitests/README.md b/uitests/README.md index aa1dfd93..c05b92b2 100644 --- a/uitests/README.md +++ b/uitests/README.md @@ -58,6 +58,5 @@ NGROK_TOKEN= GI_API_KEY= GI_SUITE= CONTAINER_IMAGE=atat:b - If you get errors regarding ports being in use, make sure you don't have instances of the Flask app, Postgres, or Redis running locally using those ports. - If the curl command used to wait for the application container times out and fails, you can increase the timeout by setting a CONTAINER_TIMEOUT environment variable. It defaults to 200 in the script. -- The curl command will print errors until it successfully connects to the application container. These are normal and expected. When it finally connects, it will print the ATAT home page HTML to STDOUT. - You may see errors like "No such container". The script attempts to clean up any previous incarnations of the containers before it starts, and it may print errors when it doesn't find them. This is fine. - The script is, for the most part, a series of docker commands, so try running the commands individually and debugging that way. From 8166c05ec25c2273e6586dc99ad8442a1c27406b Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Wed, 18 Dec 2019 14:17:03 -0500 Subject: [PATCH 038/114] Always show side nav and update styling --- styles/elements/_sidenav.scss | 52 ++++++++++++++++-------- templates/base.html | 4 +- templates/navigation/global_sidenav.html | 34 ++++++++-------- 3 files changed, 54 insertions(+), 36 deletions(-) diff --git a/styles/elements/_sidenav.scss b/styles/elements/_sidenav.scss index 0a6b201c..224895fb 100644 --- a/styles/elements/_sidenav.scss +++ b/styles/elements/_sidenav.scss @@ -1,8 +1,3 @@ -@mixin sidenav__header { - padding: $gap ($gap * 2); - font-weight: bold; -} - .sidenav-container { box-shadow: $box-shadow; overflow: hidden; @@ -26,34 +21,58 @@ margin: 0px; } - &__title { - @include sidenav__header; + &__header { + padding: $gap ($gap * 2); + font-weight: bold; + border-bottom: 1px solid $color-gray-lighter; - font-size: $h3-font-size; + &--minimized { + @extend .sidenav__header; + + padding: $gap; + width: $sidenav-collapsed-width; + } + } + + &__title { + font-size: $h6-font-size; text-transform: uppercase; width: 50%; color: $color-gray-dark; opacity: 0.54; + white-space: nowrap; + padding: $gap; + display: inline-flex; + align-items: center; } &__toggle { - @include sidenav__header; - font-size: $small-font-size; - line-height: 2.8rem; - float: right; - color: $color-blue-darker; + color: $color-blue; + text-decoration: none; + padding: $gap; + display: inline-flex; + align-items: center; .toggle-arrows { vertical-align: middle; + @include icon-size(20); + + &:first-child { + margin-left: 0; + } + + &:last-child { + margin-right: 0; + } } } ul { &.sidenav__list--padded { - margin-top: 4 * $gap; + margin-top: 3 * $gap; margin-bottom: $footer-height; - padding-bottom: $gap; + padding: 0 $gap ($gap * 2); position: fixed; overflow-y: scroll; top: $topbar-height + $usa-banner-height + 4rem; @@ -69,6 +88,7 @@ li { margin: 0; display: block; + color: $color-black-light; } } @@ -90,7 +110,7 @@ display: block; padding: $gap ($gap * 2); color: $color-black; - text-decoration: underline; + text-decoration: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; diff --git a/templates/base.html b/templates/base.html index fabcb92c..f4964add 100644 --- a/templates/base.html +++ b/templates/base.html @@ -21,9 +21,7 @@ {% include 'navigation/topbar.html' %}
- {% if portfolios %} - {% include 'navigation/global_sidenav.html' %} - {% endif %} + {% include 'navigation/global_sidenav.html' %}
{% block sidenav %}{% endblock %} diff --git a/templates/navigation/global_sidenav.html b/templates/navigation/global_sidenav.html index c6141641..84ce99e6 100644 --- a/templates/navigation/global_sidenav.html +++ b/templates/navigation/global_sidenav.html @@ -7,29 +7,29 @@
- +
- +
-
Portfolios
    - {% if portfolios %} - {% for other_portfolio in portfolios|sort(attribute='name') %} - {{ SidenavItem(other_portfolio.name, - href=url_for("applications.portfolio_applications", portfolio_id=other_portfolio.id), - active=(other_portfolio.id | string) == request.view_args.get('portfolio_id') - ) }} - {% endfor %} - {% else %} -
  • You have no portfolios yet
  • - {% endif %} + {% for other_portfolio in portfolios|sort(attribute='name') %} + {{ SidenavItem(other_portfolio.name, + href=url_for("applications.portfolio_applications", portfolio_id=other_portfolio.id), + active=(other_portfolio.id | string) == request.view_args.get('portfolio_id') + ) }} + {% endfor %}
From 2584c43c90af23641e0a99ac20b8a587c99a4726 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Wed, 18 Dec 2019 15:29:10 -0500 Subject: [PATCH 039/114] Home page styling updates: - Update copy - Update menu description section --- styles/core/_variables.scss | 1 + styles/elements/_icons.scss | 15 +++++ styles/sections/_home.scss | 54 ++++-------------- templates/home.html | 107 +++++++++++++----------------------- translations.yaml | 10 ++-- 5 files changed, 71 insertions(+), 116 deletions(-) diff --git a/styles/core/_variables.scss b/styles/core/_variables.scss index fe81b498..44fc53c8 100644 --- a/styles/core/_variables.scss +++ b/styles/core/_variables.scss @@ -17,6 +17,7 @@ $usa-banner-height: 2.8rem; $sidenav-expanded-width: 25rem; $sidenav-collapsed-width: 10rem; $max-panel-width: 80rem; +$home-pg-icon-width: 6rem; /* * USWDS Variables diff --git a/styles/elements/_icons.scss b/styles/elements/_icons.scss index c7a43414..b2980227 100644 --- a/styles/elements/_icons.scss +++ b/styles/elements/_icons.scss @@ -94,4 +94,19 @@ &--primary { @include icon-color($color-primary); } + + &--home-pg-badge { + @include icon-size(27); + @include icon-color($color-white); + + background-color: $color-primary; + height: $home-pg-icon-width; + width: $home-pg-icon-width; + border-radius: 100%; + display: inline-flex; + + svg { + margin: auto; + } + } } diff --git a/styles/sections/_home.scss b/styles/sections/_home.scss index 1ca33efc..25aac6e3 100644 --- a/styles/sections/_home.scss +++ b/styles/sections/_home.scss @@ -2,48 +2,23 @@ .sticky-cta { margin: -1.6rem -1.6rem 0 -1.6rem; } -} -.about-cloud { - margin: 4rem auto; - max-width: 900px; -} + &__content { + margin: 4rem auto; + max-width: 900px; -.your-project { - margin-top: 3rem; - padding: 3rem; - background-color: $color-gray-lightest; + &--descriptions { + .col { + margin-left: $home-pg-icon-width; + padding: ($gap * 2) ($gap * 4); + position: relative; - h2 { - margin-top: 0; - } - - .links { - justify-content: flex-start; - - .icon-link { - padding: $gap ($gap * 4); - - &:first-child { - padding-left: 0; - } - - &:last-child { - padding-right: 0; - } - - &:hover { - background-color: transparent; - color: $color-gray-dark; - - .svg * { - fill: $color-gray-dark; + .icon--home-pg-badge { + position: absolute; + left: -$home-pg-icon-width; + top: $gap * 3; } } - - &.active:hover { - color: $color-blue; - } } } } @@ -112,8 +87,3 @@ } } } - -#jedi-heirarchy { - max-width: 65rem; - margin-top: $gap * 8; -} diff --git a/templates/home.html b/templates/home.html index aadcd2a8..03dfd0fd 100644 --- a/templates/home.html +++ b/templates/home.html @@ -1,8 +1,7 @@ {% extends "base.html" %} -{% from "components/sticky_cta.html" import StickyCTA %} {% from "components/icon.html" import Icon %} -{% from "components/semi_collapsible_text.html" import SemiCollapsibleText %} +{% from "components/sticky_cta.html" import StickyCTA %} {% block content %} @@ -13,80 +12,50 @@ {% set sticky_header = "home.get_started" | translate %} {% endif %} -
+
{% include "fragments/flash.html" %}

{{ "home.head" | translate }}

+

Set up a Portfolio

+

New Portfolios will be visible in the left side bar of this page.

+

All TOs associated to a specific Application or set of related Applications will be entered at the Portfolio level. Funding is applied and managed at the Portfolio level as well.

+
- {{ SemiCollapsibleText(first_half=("home.about_cloud.part1"|translate), second_half=("home.about_cloud.part2"|translate)) }} - -
-

{{ "home.your_project" | translate }}

-

{{ "home.your_project_descrip" | translate }}

- -
- - {% macro Link(icon, text, section, default=False) %} - {% if default %} -
- {% else %} -
- {% endif %} -
- - -
+
+
+
+ {{ Icon('funding', classes="icon--home-pg-badge") }} +

{{ "navigation.portfolio_navigation.breadcrumbs.funding" | translate }}

+

+ {{ "home.funding_descrip" | translate }} +

- {% endmacro %} - - -
-
- -
- {% macro Description(section, default=False) %} - {% if default %} -

- {% else %} -

- {% endif %} - - {{ "navigation.portfolio_navigation.breadcrumbs.%s" | format(section) | translate }} - - {{ "home.%s_descrip" | format(section) | translate }} -

- {% endmacro %} -
- {{ Description('funding', default=True) }} - {{ Description('applications') }} - {{ Description('reports') }} - {{ Description('admin') }} -
+
+ {{ Icon('chart-pie', classes="icon--home-pg-badge") }} +

{{ "navigation.portfolio_navigation.breadcrumbs.reports" | translate }}

+

+ {{ "home.reports_descrip" | translate }} +

- +
+
+
+ {{ Icon('applications', classes="icon--home-pg-badge") }} +

{{ "navigation.portfolio_navigation.breadcrumbs.applications" | translate }}

+

+ {{ "home.applications_descrip" | translate }} +

+
+
+ {{ Icon('cog', classes="icon--home-pg-badge") }} +

{{ "navigation.portfolio_navigation.breadcrumbs.admin" | translate }}

+

+ {{ "home.admin_descrip" | translate }} +

+
+
+ {{ "home.add_portfolio_button_text" | translate }} diff --git a/translations.yaml b/translations.yaml index 773202bd..b7c0ffae 100644 --- a/translations.yaml +++ b/translations.yaml @@ -22,13 +22,13 @@ home: add_portfolio_button_text: Add New Portfolio new_portfolio: New Portfolio get_started: Get Started - head: About Cloud Services + head: JEDI Cloud Services your_project: Your Project your_project_descrip: Your portfolio is where all task orders pertaining to a specific project or set of related projects live. In JEDI, every task order in your portfolio has four components. - funding_descrip: is information about all approved task orders associated to your portfolio. - applications_descrip: ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod - reports_descrip: enim ad minim veniam, quis nostrud exercitation ullamco - admin_descrip: aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat + funding_descrip: The Task Orders section allows you to enter, manage, and edit awarded TOs associated to a specific Portfolio. + applications_descrip: The Applications section allows you to easily create and define new Applications within a Portfolio, as well as manage user permissions and Environments. + reports_descrip: The Reports section allows you to view and monitor funding usage within a specific Portfolio. + admin_descrip: Within the Settings section, you can manage your Portfolio name and description, as well as add, edit, and delete Portfolio managers. ccpo: users_title: CCPO Users add_user: Add new CCPO user From 217a29b0dcb120341ebb02b4e473644bddc9028d Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Wed, 18 Dec 2019 16:18:47 -0500 Subject: [PATCH 040/114] Adjust margins on home page, globally fix hr elements to default to having margins, and add class for hr elements to span full width of their container --- styles/core/_util.scss | 6 +++++- styles/sections/_home.scss | 1 + templates/applications/fragments/member_form_fields.html | 2 +- templates/applications/fragments/members.html | 4 ++-- .../applications/fragments/new_member_modal_content.html | 2 +- .../portfolios/fragments/add_new_portfolio_member.html | 4 ++-- templates/portfolios/fragments/change_ppoc.html | 4 ++-- 7 files changed, 14 insertions(+), 9 deletions(-) diff --git a/styles/core/_util.scss b/styles/core/_util.scss index ff6e8e3f..5203da45 100644 --- a/styles/core/_util.scss +++ b/styles/core/_util.scss @@ -88,5 +88,9 @@ p { hr { border: 0; border-bottom: 1px solid $color-gray-light; - margin: ($gap * 3) ($site-margins * -4); + margin: ($gap * 3) 0; + + &.full-width { + margin: ($gap * 3) ($site-margins * -4); + } } diff --git a/styles/sections/_home.scss b/styles/sections/_home.scss index 25aac6e3..a721b71c 100644 --- a/styles/sections/_home.scss +++ b/styles/sections/_home.scss @@ -1,4 +1,5 @@ .home { + margin: $gap * 3; .sticky-cta { margin: -1.6rem -1.6rem 0 -1.6rem; } diff --git a/templates/applications/fragments/member_form_fields.html b/templates/applications/fragments/member_form_fields.html index 20ecc210..3aa97687 100644 --- a/templates/applications/fragments/member_form_fields.html +++ b/templates/applications/fragments/member_form_fields.html @@ -100,7 +100,7 @@ {{ CheckboxInput(form.perms_env_mgmt, classes="input__inline-fields", key=env_mgmt, id=env_mgmt, optional=True) }} {{ CheckboxInput(form.perms_del_env, classes="input__inline-fields", key=del_env, id=del_env, optional=True) }}
-
+

{{ "portfolios.applications.members.form.env_access.title" | translate }}

diff --git a/templates/applications/fragments/members.html b/templates/applications/fragments/members.html index 1a7bcb4a..be312351 100644 --- a/templates/applications/fragments/members.html +++ b/templates/applications/fragments/members.html @@ -40,7 +40,7 @@ {% call Modal(modal_name, classes="form-content--app-mem") %}

@@ -59,7 +59,7 @@ {% call Modal(resend_invite_modal, classes="form-content--app-mem") %} diff --git a/templates/applications/fragments/new_member_modal_content.html b/templates/applications/fragments/new_member_modal_content.html index bee6f303..14bb00a2 100644 --- a/templates/applications/fragments/new_member_modal_content.html +++ b/templates/applications/fragments/new_member_modal_content.html @@ -2,7 +2,7 @@ {% import "applications/fragments/member_form_fields.html" as member_fields %} {% macro MemberFormTemplate(title=None, next_button=None, previous=True) %} -
+
{% if title %}

{{ title }}

{% endif %} {{ caller() }} diff --git a/templates/portfolios/fragments/add_new_portfolio_member.html b/templates/portfolios/fragments/add_new_portfolio_member.html index 06ca6038..644f5062 100644 --- a/templates/portfolios/fragments/add_new_portfolio_member.html +++ b/templates/portfolios/fragments/add_new_portfolio_member.html @@ -16,7 +16,7 @@ {% endmacro %} {% set step_one %} -
+

Invite new portfolio member

-
+
{{ TextInput(form.description, paragraph=True, optional=True) }} diff --git a/templates/applications/new/step_2.html b/templates/applications/new/step_2.html index bb622f8f..9adfddca 100644 --- a/templates/applications/new/step_2.html +++ b/templates/applications/new/step_2.html @@ -19,7 +19,7 @@

{{ 'portfolios.applications.new.step_2_description' | translate }}

-
+
{{ 'portfolios.applications.environments_heading' | translate }}
diff --git a/templates/applications/new/step_3.html b/templates/applications/new/step_3.html index 06dd4e0d..a4e1aa53 100644 --- a/templates/applications/new/step_3.html +++ b/templates/applications/new/step_3.html @@ -15,7 +15,7 @@

{{ ('portfolios.applications.new.step_3_description' | translate) }}

-
+
{{ MemberManagementTemplate( application, From 8fbb0e99ae153013bba6e9a39465bad1b6c2b313 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Wed, 18 Dec 2019 16:49:58 -0500 Subject: [PATCH 042/114] Fix side nav to match designs and delete unused html and css --- styles/elements/_sidenav.scss | 91 ++------------------------ templates/applications/new/step_2.html | 4 +- templates/components/sidenav_item.html | 34 ++-------- 3 files changed, 12 insertions(+), 117 deletions(-) diff --git a/styles/elements/_sidenav.scss b/styles/elements/_sidenav.scss index 224895fb..d4a538f0 100644 --- a/styles/elements/_sidenav.scss +++ b/styles/elements/_sidenav.scss @@ -72,7 +72,7 @@ &.sidenav__list--padded { margin-top: 3 * $gap; margin-bottom: $footer-height; - padding: 0 $gap ($gap * 2); + padding-bottom: ($gap * 2); position: fixed; overflow-y: scroll; top: $topbar-height + $usa-banner-height + 4rem; @@ -109,100 +109,19 @@ &__link { display: block; padding: $gap ($gap * 2); - color: $color-black; - text-decoration: none; white-space: nowrap; overflow: hidden; + color: $color-black-light; + text-decoration: none; text-overflow: ellipsis; - &-icon { - margin-left: -($gap * 0.5); - } - - &--disabled { - color: $color-shadow; - pointer-events: none; - } - - &--add { - color: $color-blue; - font-size: $small-font-size; - - .icon { - @include icon-color($color-blue); - @include icon-size(14); - } - } - &--active { @include h4; - color: $color-primary; background-color: $color-aqua-lightest; - box-shadow: inset ($gap / 2) 0 0 0 $color-primary; - - .sidenav__link-icon { - @include icon-style-active; - } - + box-shadow: inset ($gap / 2) 0 0 0 $color-primary-darker; position: relative; - - &_indicator .icon { - @include icon-color($color-primary); - - position: absolute; - right: 0; - } - - + ul { - background-color: $color-primary; - - .sidenav__link { - color: $color-white; - background-color: $color-primary; - - &:hover { - background-color: $color-blue-darker; - } - - &--active { - @include h5; - - color: $color-white; - background-color: $color-primary; - box-shadow: none; - } - - .icon { - @include icon-color($color-white); - } - } - } - } - - + ul { - li { - .sidenav__link { - @include h5; - - padding: $gap * 0.75; - padding-left: 4.5rem; - border: 0; - font-weight: normal; - - .sidenav__link-icon { - @include icon-size(12); - - flex-shrink: 0; - margin-right: 1.5rem; - margin-left: -3rem; - } - - .sidenav__link-label { - padding-left: 0; - } - } - } + color: $color-primary-darker; } &:hover { diff --git a/templates/applications/new/step_2.html b/templates/applications/new/step_2.html index 9adfddca..462c0f46 100644 --- a/templates/applications/new/step_2.html +++ b/templates/applications/new/step_2.html @@ -58,9 +58,9 @@ {{ Icon("plus") }}
-
+
-
+
{% block next_button %} {{ SaveButton(text=('portfolios.applications.new.step_2_button_text' | translate)) }} diff --git a/templates/components/sidenav_item.html b/templates/components/sidenav_item.html index 8e3c5135..ec6be364 100644 --- a/templates/components/sidenav_item.html +++ b/templates/components/sidenav_item.html @@ -1,35 +1,11 @@ {% from "components/icon.html" import Icon %} -{% macro SidenavItem(label, href, active=False, icon=None, subnav=None) -%} +{% macro SidenavItem(label, href, active=False) -%}
  • - - {% if icon %} - {{ Icon(icon, classes="sidenav__link-icon") }} - {% endif %} - - - {{label}} - - {% if active %} - - {{ Icon("caret_right") }} + + + {{label}} - {% endif %} - - - {% if subnav and active %} - - {% endif %} +
  • {%- endmacro %} From a231ba5210289772a4e7df6d24d848260ccd0175 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Wed, 18 Dec 2019 16:54:55 -0500 Subject: [PATCH 043/114] Update styling for add new portfolio button on home page --- templates/home.html | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/templates/home.html b/templates/home.html index 03dfd0fd..986c6e41 100644 --- a/templates/home.html +++ b/templates/home.html @@ -55,10 +55,13 @@
    - - - {{ "home.add_portfolio_button_text" | translate }} - +
    From c642708c44afb15da3d70edfd088ba92cf9df666 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Wed, 18 Dec 2019 16:57:15 -0500 Subject: [PATCH 044/114] Left align home page content --- styles/sections/_home.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/styles/sections/_home.scss b/styles/sections/_home.scss index a721b71c..b0d715d2 100644 --- a/styles/sections/_home.scss +++ b/styles/sections/_home.scss @@ -5,7 +5,7 @@ } &__content { - margin: 4rem auto; + margin: 4rem; max-width: 900px; &--descriptions { From 6d64665474b0aaa440ed2b8672a56d25dd086f70 Mon Sep 17 00:00:00 2001 From: Rob Gil Date: Wed, 18 Dec 2019 18:45:25 -0500 Subject: [PATCH 045/114] 169163334 - Adds CDN module Basic CDN module with configurable origin. --- terraform/modules/cdn/main.tf | 31 ++++++++++++++++++++++++++++++ terraform/modules/cdn/outputs.tf | 0 terraform/modules/cdn/variables.tf | 31 ++++++++++++++++++++++++++++++ terraform/providers/dev/cdn.tf | 8 ++++++++ 4 files changed, 70 insertions(+) create mode 100644 terraform/modules/cdn/main.tf create mode 100644 terraform/modules/cdn/outputs.tf create mode 100644 terraform/modules/cdn/variables.tf create mode 100644 terraform/providers/dev/cdn.tf diff --git a/terraform/modules/cdn/main.tf b/terraform/modules/cdn/main.tf new file mode 100644 index 00000000..5debd443 --- /dev/null +++ b/terraform/modules/cdn/main.tf @@ -0,0 +1,31 @@ +resource "random_id" "server" { + keepers = { + azi_id = 1 + } + + byte_length = 8 +} + +resource "azurerm_resource_group" "cdn" { + name = "${var.name}-${var.environment}-cdn" + location = var.region +} + +resource "azurerm_cdn_profile" "cdn" { + name = "${var.name}-${var.environment}-profile" + location = azurerm_resource_group.cdn.location + resource_group_name = azurerm_resource_group.cdn.name + sku = var.sku +} + +resource "azurerm_cdn_endpoint" "cdn" { + name = "${var.name}-${var.environment}-${random_id.server.hex}" + profile_name = azurerm_cdn_profile.cdn.name + location = azurerm_resource_group.cdn.location + resource_group_name = azurerm_resource_group.cdn.name + + origin { + name = "${var.name}-${var.environment}-origin" + host_name = var.origin_host_name + } +} diff --git a/terraform/modules/cdn/outputs.tf b/terraform/modules/cdn/outputs.tf new file mode 100644 index 00000000..e69de29b diff --git a/terraform/modules/cdn/variables.tf b/terraform/modules/cdn/variables.tf new file mode 100644 index 00000000..a026ffed --- /dev/null +++ b/terraform/modules/cdn/variables.tf @@ -0,0 +1,31 @@ +variable "region" { + type = string + description = "Region this module and resources will be created in" +} + +variable "name" { + type = string + description = "Unique name for the services in this module" +} + +variable "environment" { + type = string + description = "Environment these resources reside (prod, dev, staging, etc)" +} + +variable "owner" { + type = string + description = "Owner of the environment and resources created in this module" +} + +variable "sku" { + type = string + description = "SKU of which CDN to use" + default = "Standard_Verizon" +} + +variable "origin_host_name" { + type = string + description = "Subdomain to use for the origin in requests to the CDN" +} + diff --git a/terraform/providers/dev/cdn.tf b/terraform/providers/dev/cdn.tf new file mode 100644 index 00000000..3b379b90 --- /dev/null +++ b/terraform/providers/dev/cdn.tf @@ -0,0 +1,8 @@ +module "cdn" { + source = "../../modules/cdn" + origin_host_name = "staging.atat.code.mil" + owner = var.owner + environment = var.environment + name = var.name + region = var.region +} From 0925c73c6878eec2e596d3dad92b9fde1c1b264d Mon Sep 17 00:00:00 2001 From: Rob Gil Date: Wed, 18 Dec 2019 18:47:02 -0500 Subject: [PATCH 046/114] Terraform fmt across new modules --- terraform/modules/cdn/variables.tf | 10 +++--- terraform/modules/redis/main.tf | 6 ++-- terraform/modules/redis/variables.tf | 46 ++++++++++++++-------------- terraform/providers/dev/cdn.tf | 10 +++--- terraform/providers/dev/redis.tf | 8 ++--- 5 files changed, 40 insertions(+), 40 deletions(-) diff --git a/terraform/modules/cdn/variables.tf b/terraform/modules/cdn/variables.tf index a026ffed..3abe4851 100644 --- a/terraform/modules/cdn/variables.tf +++ b/terraform/modules/cdn/variables.tf @@ -19,13 +19,13 @@ variable "owner" { } variable "sku" { - type = string - description = "SKU of which CDN to use" - default = "Standard_Verizon" + type = string + description = "SKU of which CDN to use" + default = "Standard_Verizon" } variable "origin_host_name" { - type = string - description = "Subdomain to use for the origin in requests to the CDN" + type = string + description = "Subdomain to use for the origin in requests to the CDN" } diff --git a/terraform/modules/redis/main.tf b/terraform/modules/redis/main.tf index 1e47f767..90a88a2b 100644 --- a/terraform/modules/redis/main.tf +++ b/terraform/modules/redis/main.tf @@ -15,10 +15,10 @@ resource "azurerm_redis_cache" "redis" { minimum_tls_version = var.minimum_tls_version redis_configuration { - enable_authentication = var.enable_authentication + enable_authentication = var.enable_authentication } tags = { - environment = var.environment - owner = var.owner + environment = var.environment + owner = var.owner } } diff --git a/terraform/modules/redis/variables.tf b/terraform/modules/redis/variables.tf index ecdb7636..dac8819b 100644 --- a/terraform/modules/redis/variables.tf +++ b/terraform/modules/redis/variables.tf @@ -19,42 +19,42 @@ variable "owner" { } variable "capacity" { - type = string - default = 2 - description = "The capacity of the redis cache" - + type = string + default = 2 + description = "The capacity of the redis cache" + } variable "family" { - type = string - default = "C" - description = "The subscription family for redis" - + type = string + default = "C" + description = "The subscription family for redis" + } variable "sku_name" { - type = string - default = "Standard" - description = "The sku to use" - + type = string + default = "Standard" + description = "The sku to use" + } variable "enable_non_ssl_port" { - type = bool - default = false - description = "Enable non TLS port (default: false)" - + type = bool + default = false + description = "Enable non TLS port (default: false)" + } variable "minimum_tls_version" { - type = string - default = "1.2" - description = "Minimum TLS version to use" - + type = string + default = "1.2" + description = "Minimum TLS version to use" + } variable "enable_authentication" { - type = bool - default = true - description = "Enable or disable authentication (default: true)" + type = bool + default = true + description = "Enable or disable authentication (default: true)" } diff --git a/terraform/providers/dev/cdn.tf b/terraform/providers/dev/cdn.tf index 3b379b90..02c17e3d 100644 --- a/terraform/providers/dev/cdn.tf +++ b/terraform/providers/dev/cdn.tf @@ -1,8 +1,8 @@ module "cdn" { - source = "../../modules/cdn" + source = "../../modules/cdn" origin_host_name = "staging.atat.code.mil" - owner = var.owner - environment = var.environment - name = var.name - region = var.region + owner = var.owner + environment = var.environment + name = var.name + region = var.region } diff --git a/terraform/providers/dev/redis.tf b/terraform/providers/dev/redis.tf index fca3a4e3..bfe47a84 100644 --- a/terraform/providers/dev/redis.tf +++ b/terraform/providers/dev/redis.tf @@ -1,7 +1,7 @@ module "redis" { - source = "../../modules/redis" - owner = var.owner + source = "../../modules/redis" + owner = var.owner environment = var.environment - region = var.region - name = var.name + region = var.region + name = var.name } From 7aeda9377e9a810cc542d5866bbb238f4eaaeb8c Mon Sep 17 00:00:00 2001 From: Rob Gil Date: Wed, 18 Dec 2019 20:55:58 -0500 Subject: [PATCH 047/114] 169163334 - Adds LB module --- terraform/modules/lb/main.tf | 22 ++++++++++++++++++++++ terraform/modules/lb/outputs.tf | 0 terraform/modules/lb/variables.tf | 19 +++++++++++++++++++ terraform/providers/dev/k8s.tf | 7 +++++++ 4 files changed, 48 insertions(+) create mode 100644 terraform/modules/lb/main.tf create mode 100644 terraform/modules/lb/outputs.tf create mode 100644 terraform/modules/lb/variables.tf diff --git a/terraform/modules/lb/main.tf b/terraform/modules/lb/main.tf new file mode 100644 index 00000000..1c9acace --- /dev/null +++ b/terraform/modules/lb/main.tf @@ -0,0 +1,22 @@ +resource "azurerm_resource_group" "lb" { + name = "${var.name}-${var.environment}-lb" + location = var.region +} + +resource "azurerm_public_ip" "lb" { + name = "${var.name}-${var.environment}-ip" + location = var.region + resource_group_name = azurerm_resource_group.lb.name + allocation_method = "Static" +} + +resource "azurerm_lb" "lb" { + name = "${var.name}-${var.environment}-lb" + location = var.region + resource_group_name = azurerm_resource_group.lb.name + + frontend_ip_configuration { + name = "${var.name}-${var.environment}-ip" + public_ip_address_id = azurerm_public_ip.lb.id + } +} diff --git a/terraform/modules/lb/outputs.tf b/terraform/modules/lb/outputs.tf new file mode 100644 index 00000000..e69de29b diff --git a/terraform/modules/lb/variables.tf b/terraform/modules/lb/variables.tf new file mode 100644 index 00000000..10fa56e9 --- /dev/null +++ b/terraform/modules/lb/variables.tf @@ -0,0 +1,19 @@ +variable "region" { + type = string + description = "Region this module and resources will be created in" +} + +variable "name" { + type = string + description = "Unique name for the services in this module" +} + +variable "environment" { + type = string + description = "Environment these resources reside (prod, dev, staging, etc)" +} + +variable "owner" { + type = string + description = "Owner of the environment and resources created in this module" +} \ No newline at end of file diff --git a/terraform/providers/dev/k8s.tf b/terraform/providers/dev/k8s.tf index b41df8a4..22120c93 100644 --- a/terraform/providers/dev/k8s.tf +++ b/terraform/providers/dev/k8s.tf @@ -9,3 +9,10 @@ module "k8s" { vnet_subnet_id = module.vpc.subnets #FIXME - output from module.vpc.subnets should be map } +module "lb" { + source = "../../modules/lb" + region = var.region + name = var.name + environment = var.environment + owner = var.owner +} From 2cf643daa573aca7923c61f4881fd6af7ee522e3 Mon Sep 17 00:00:00 2001 From: "Jay R. Newlin (PromptWorks)" Date: Thu, 19 Dec 2019 13:16:45 -0500 Subject: [PATCH 048/114] Changes based on new checkbox in TO Step 5 --- uitests/Add_expired_TO.html | 21 ++++++++++++++++++--- uitests/Add_future_TO.html | 21 ++++++++++++++++++--- uitests/Create_TO_after_other_steps.html | 21 ++++++++++++++++++--- 3 files changed, 54 insertions(+), 9 deletions(-) diff --git a/uitests/Add_expired_TO.html b/uitests/Add_expired_TO.html index 71f6a617..4ee5fa85 100644 --- a/uitests/Add_expired_TO.html +++ b/uitests/Add_expired_TO.html @@ -329,12 +329,27 @@
    - + - + - + + + + + + + + + + + + + + + + diff --git a/uitests/Add_future_TO.html b/uitests/Add_future_TO.html index 89b22c7a..f48059f7 100644 --- a/uitests/Add_future_TO.html +++ b/uitests/Add_future_TO.html @@ -329,12 +329,27 @@ - + - + - + + + + + + + + + + + + + + + + diff --git a/uitests/Create_TO_after_other_steps.html b/uitests/Create_TO_after_other_steps.html index 9583a99e..030e24a7 100644 --- a/uitests/Create_TO_after_other_steps.html +++ b/uitests/Create_TO_after_other_steps.html @@ -344,12 +344,27 @@ - + - + - + + + + + + + + + + + + + + + + From 74b2510730e4bbbecb271304265ce3cc43bc6bbd Mon Sep 17 00:00:00 2001 From: Rob Gil Date: Thu, 19 Dec 2019 20:12:20 -0500 Subject: [PATCH 049/114] 169163334 - Adds Azure Container Registry Adds the ACR. Georeplication disabled for the moment until we add the DR site. --- terraform/modules/container_registry/main.tf | 13 +++++++ .../modules/container_registry/outputs.tf | 0 .../modules/container_registry/variables.tf | 37 +++++++++++++++++++ terraform/providers/dev/container_registry.tf | 8 ++++ terraform/providers/dev/variables.tf | 5 +++ 5 files changed, 63 insertions(+) create mode 100644 terraform/modules/container_registry/main.tf create mode 100644 terraform/modules/container_registry/outputs.tf create mode 100644 terraform/modules/container_registry/variables.tf create mode 100644 terraform/providers/dev/container_registry.tf diff --git a/terraform/modules/container_registry/main.tf b/terraform/modules/container_registry/main.tf new file mode 100644 index 00000000..a22bacf0 --- /dev/null +++ b/terraform/modules/container_registry/main.tf @@ -0,0 +1,13 @@ +resource "azurerm_resource_group" "acr" { + name = "${var.name}-${var.environment}-acr" + location = var.region +} + +resource "azurerm_container_registry" "acr" { + name = "${var.name}${var.environment}registry" # Alpha Numeric Only + resource_group_name = azurerm_resource_group.acr.name + location = azurerm_resource_group.acr.location + sku = var.sku + admin_enabled = var.admin_enabled + #georeplication_locations = [azurerm_resource_group.acr.location, var.backup_region] +} \ No newline at end of file diff --git a/terraform/modules/container_registry/outputs.tf b/terraform/modules/container_registry/outputs.tf new file mode 100644 index 00000000..e69de29b diff --git a/terraform/modules/container_registry/variables.tf b/terraform/modules/container_registry/variables.tf new file mode 100644 index 00000000..6fe16ad5 --- /dev/null +++ b/terraform/modules/container_registry/variables.tf @@ -0,0 +1,37 @@ +variable "region" { + type = string + description = "Region this module and resources will be created in" +} + +variable "name" { + type = string + description = "Unique name for the services in this module" +} + +variable "environment" { + type = string + description = "Environment these resources reside (prod, dev, staging, etc)" +} + +variable "owner" { + type = string + description = "Owner of the environment and resources created in this module" +} + +variable "backup_region" { + type = string + description = "Backup region for georeplicating the container registry" +} + +variable "sku" { + type = string + description = "SKU to use for the container registry service" + default = "Premium" +} + +variable "admin_enabled" { + type = string + description = "Admin enabled? (true/false default: false)" + default = false + +} diff --git a/terraform/providers/dev/container_registry.tf b/terraform/providers/dev/container_registry.tf new file mode 100644 index 00000000..0bbf0901 --- /dev/null +++ b/terraform/providers/dev/container_registry.tf @@ -0,0 +1,8 @@ +module "container_registry" { + source = "../../modules/container_registry" + name = var.name + region = var.region + environment = var.environment + owner = var.owner + backup_region = var.backup_region +} diff --git a/terraform/providers/dev/variables.tf b/terraform/providers/dev/variables.tf index 7a9eea21..0a16e69b 100644 --- a/terraform/providers/dev/variables.tf +++ b/terraform/providers/dev/variables.tf @@ -7,6 +7,11 @@ variable "region" { } +variable "backup_region" { + default = "westus2" +} + + variable "owner" { default = "dev" } From 866b789b6c1c829f9debb8e6423b96749d26623b Mon Sep 17 00:00:00 2001 From: Rob Gil Date: Thu, 19 Dec 2019 22:33:27 -0500 Subject: [PATCH 050/114] 169163334 - Adds Virtual Network Gateway for VPN The Virtual Network Gateway is required for OpenVPN connectivity. The change to the VPC module also adds a subnet which is exclusively used for the Gateway. --- terraform/modules/vpc/main.tf | 58 ++++++++++++++++++++++++---- terraform/modules/vpc/variables.tf | 5 +++ terraform/providers/dev/variables.tf | 6 +++ terraform/providers/dev/vpc.tf | 1 + 4 files changed, 62 insertions(+), 8 deletions(-) diff --git a/terraform/modules/vpc/main.tf b/terraform/modules/vpc/main.tf index e614b9e4..629be9f1 100644 --- a/terraform/modules/vpc/main.tf +++ b/terraform/modules/vpc/main.tf @@ -36,9 +36,9 @@ resource "azurerm_subnet" "subnet" { address_prefix = element(split(",", each.value), 0) # See https://github.com/terraform-providers/terraform-provider-azurerm/issues/3471 - lifecycle { - ignore_changes = [route_table_id] - } + lifecycle { + ignore_changes = [route_table_id] + } #delegation { # name = "acctestdelegation" # @@ -57,16 +57,58 @@ resource "azurerm_route_table" "route_table" { } resource "azurerm_subnet_route_table_association" "route_table" { - for_each = var.networks - subnet_id = azurerm_subnet.subnet[each.key].id + for_each = var.networks + subnet_id = azurerm_subnet.subnet[each.key].id route_table_id = azurerm_route_table.route_table[each.key].id } resource "azurerm_route" "route" { - for_each = var.route_tables - name = "${var.name}-${var.environment}-default" + for_each = var.route_tables + name = "${var.name}-${var.environment}-default" resource_group_name = azurerm_resource_group.vpc.name - route_table_name = azurerm_route_table.route_table[each.key].name + route_table_name = azurerm_route_table.route_table[each.key].name address_prefix = "0.0.0.0/0" next_hop_type = each.value } + +# Required for the gateway +resource "azurerm_subnet" "gateway" { + name = "GatewaySubnet" + resource_group_name = azurerm_resource_group.vpc.name + virtual_network_name = azurerm_virtual_network.vpc.name + address_prefix = var.gateway_subnet +} + + +resource "azurerm_public_ip" "vpn_ip" { + name = "test" + location = azurerm_resource_group.vpc.location + resource_group_name = azurerm_resource_group.vpc.name + + allocation_method = "Dynamic" +} + +resource "azurerm_virtual_network_gateway" "vnet_gateway" { + name = "test" + location = azurerm_resource_group.vpc.location + resource_group_name = azurerm_resource_group.vpc.name + + type = "Vpn" + vpn_type = "RouteBased" + + active_active = false + enable_bgp = false + sku = "Standard" + + ip_configuration { + name = "vnetGatewayConfig" + public_ip_address_id = azurerm_public_ip.vpn_ip.id + private_ip_address_allocation = "Dynamic" + subnet_id = azurerm_subnet.gateway.id + } + + vpn_client_configuration { + address_space = ["172.16.1.0/24"] + vpn_client_protocols = ["OpenVPN"] + } +} \ No newline at end of file diff --git a/terraform/modules/vpc/variables.tf b/terraform/modules/vpc/variables.tf index ab2aa894..9f331534 100644 --- a/terraform/modules/vpc/variables.tf +++ b/terraform/modules/vpc/variables.tf @@ -41,3 +41,8 @@ variable "route_tables" { type = map description = "A map with the route tables to create" } + +variable "gateway_subnet" { + type = string + description = "The Subnet CIDR that we'll use for the virtual_network_gateway 'GatewaySubnet'" +} diff --git a/terraform/providers/dev/variables.tf b/terraform/providers/dev/variables.tf index 7a9eea21..164577ef 100644 --- a/terraform/providers/dev/variables.tf +++ b/terraform/providers/dev/variables.tf @@ -31,6 +31,12 @@ variable "networks" { } } +variable "gateway_subnet" { + type = string + default = "10.1.20.0/24" +} + + variable "route_tables" { description = "Route tables and their default routes" type = map diff --git a/terraform/providers/dev/vpc.tf b/terraform/providers/dev/vpc.tf index 0b930a0d..b7fac8ae 100644 --- a/terraform/providers/dev/vpc.tf +++ b/terraform/providers/dev/vpc.tf @@ -4,6 +4,7 @@ module "vpc" { region = var.region virtual_network = var.virtual_network networks = var.networks + gateway_subnet = var.gateway_subnet route_tables = var.route_tables owner = var.owner name = var.name From b61956080ead4202c4b29b3800e1f1efdff9b48b Mon Sep 17 00:00:00 2001 From: dandds Date: Fri, 13 Dec 2019 16:32:46 -0500 Subject: [PATCH 051/114] Initial policies and method for creating policy definition. This adds some initial example policies: - One for region restrictions - One for service restrictions Note that the MS ARM team has said that region restrictions may be controlled by ARM, so that policy might prove unnecessary. The parameters list for the service restrictions is stubbed for now, pending the full list. I also added an internal method for adding policy definitions to a management group. This method is agnostic about what tier of management group the policy is being defined at. It requires that a dictionary representing the properties section of a valid Azure JSON policy definition be passed as an argument. --- Pipfile | 1 + Pipfile.lock | 213 +++++++++++------- atst/domain/csp/cloud.py | 47 ++++ atst/domain/csp/policy.py | 12 + .../portfolios/allowed-resource-types.json | 40 ++++ policies/portfolios/region-restriction.json | 51 +++++ tests/domain/cloud/test_azure_csp.py | 25 ++ tests/mock_azure.py | 7 + 8 files changed, 309 insertions(+), 87 deletions(-) create mode 100644 atst/domain/csp/policy.py create mode 100644 policies/portfolios/allowed-resource-types.json create mode 100644 policies/portfolios/region-restriction.json diff --git a/Pipfile b/Pipfile index edc8bbfc..b4591d6f 100644 --- a/Pipfile +++ b/Pipfile @@ -30,6 +30,7 @@ azure-graphrbac = "*" msrestazure = "*" azure-mgmt-authorization = "*" azure-mgmt-managementgroups = "*" +azure-mgmt-resource = "*" [dev-packages] bandit = "*" diff --git a/Pipfile.lock b/Pipfile.lock index 80f6fc96..b97cfe92 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "c2b19c436646705ea3bf4df8c35c2833083f048da37fc619e66f7236153607c5" + "sha256": "dc6d11d395668b3e1ae047bec87eac86848348a4d322e00fc9f9837a301a072c" }, "pipfile-spec": 6, "requires": { @@ -25,10 +25,10 @@ }, "alembic": { "hashes": [ - "sha256:49277bb7242192bbb9eac58fed4fe02ec6c3a2a4b4345d2171197459266482b2" + "sha256:3b0cb1948833e062f4048992fbc97ecfaaaac24aaa0d83a1202a99fb58af8c6d" ], "index": "pypi", - "version": "==1.3.1" + "version": "==1.3.2" }, "amqp": { "hashes": [ @@ -39,11 +39,11 @@ }, "apache-libcloud": { "hashes": [ - "sha256:9bc5cd5c32151bb7a04a7c7de0be9b4a4b8271e348ac91dd79eaaeeae627115f", - "sha256:fcc165f2cc2db9a379c6d3a17b3beb9081bb64ba5c0bf7bbb58da864810092f0" + "sha256:294d17774618dfb0896b14e69cdc3721850ec44dba81e7f91e701e75235a6eb1", + "sha256:29ee7d13b9b12d1335e752a489c01eed0c270940147f418cfff89ab66faf1305" ], "index": "pypi", - "version": "==2.6.1" + "version": "==2.7.0" }, "azure-common": { "hashes": [ @@ -76,6 +76,14 @@ "index": "pypi", "version": "==0.2.0" }, + "azure-mgmt-resource": { + "hashes": [ + "sha256:20b3394e4dc76fbd9459723cb8c0300fb18a8c32100076f023b5470426b9f104", + "sha256:eaea8b5d05495d1b74220052275d46b6bed93b59245bcaa747279a52e41c3bdf" + ], + "index": "pypi", + "version": "==7.0.0" + }, "azure-mgmt-subscription": { "hashes": [ "sha256:504b4c42ba859070c3c50637ec07ca36aca600e613fcccaa398db22822fe21f1", @@ -117,11 +125,11 @@ }, "celery": { "hashes": [ - "sha256:65f4d67fc1037edacecbf39fcf956da68b984cf2a6d89bd73a8a5a80e35e3dd7", - "sha256:8a59d80235b876881d9893751f2a87936165fc1347efee66095620b3cadf533b" + "sha256:7c544f37a84a5eadc44cab1aa8c9580dff94636bb81978cdf9bf8012d9ea7d8f", + "sha256:d3363bb5df72d74420986a435449f3c3979285941dff57d5d97ecba352a0e3e2" ], "index": "pypi", - "version": "==4.4.0rc4" + "version": "==4.4.0" }, "certifi": { "hashes": [ @@ -208,6 +216,15 @@ ], "version": "==2.8" }, + "enum34": { + "hashes": [ + "sha256:2d81cbbe0e73112bdfe6ef8576f2238f2ba27dd0d55752a776c41d38b7da2850", + "sha256:644837f692e5f550741432dd3f223bbb9852018674981b1664e5dc339387588a", + "sha256:6bd0f6ad48ec2aa117d3d141940d484deccda84d4fcd884f5c3d93c23ecd8c79", + "sha256:8ad8c4783bf61ded74527bffb48ed9b54166685e4230386a9ed9b1279e2df5b1" + ], + "version": "==1.1.6" + }, "flask": { "hashes": [ "sha256:13f9f196f330c7c2c5d7a5cf91af894110ca0215ac051b5844701f2bfd934d52", @@ -256,10 +273,11 @@ }, "importlib-metadata": { "hashes": [ - "sha256:b044f07694ef14a6683b097ba56bd081dbc7cdc7c7fe46011e499dfecc082f21", - "sha256:e6ac600a142cf2db707b1998382cc7fc3b02befb7273876e01b8ad10b9652742" + "sha256:073a852570f92da5f744a3472af1b61e28e9f78ccf0c9117658dc32b15de7b45", + "sha256:d95141fbfa7ef2ec65cfd945e2af7e5a6ddbd7c8d9a25e66ff3be8e3daf9f60f" ], - "version": "==1.1.0" + "markers": "python_version < '3.8'", + "version": "==1.3.0" }, "isodate": { "hashes": [ @@ -284,10 +302,10 @@ }, "kombu": { "hashes": [ - "sha256:1760b54b1d15a547c9a26d3598a1c8cdaf2436386ac1f5561934bc8a3cbbbd86", - "sha256:e7465aa85a1db889116819f08c5de29520d2fa103324dcdca5e90af345f01771" + "sha256:2a9e7adff14d046c9996752b2c48b6d9185d0b992106d5160e1a179907a5d4ac", + "sha256:67b32ccb6fea030f8799f8fd50dd08e03a4b99464ebc4952d71d8747b1a52ad1" ], - "version": "==4.6.6" + "version": "==4.6.7" }, "lockfile": { "hashes": [ @@ -338,10 +356,10 @@ }, "more-itertools": { "hashes": [ - "sha256:53ff73f186307d9c8ef17a9600309154a6ae27f25579e80af4db8f047ba14bc2", - "sha256:a0ea684c39bc4315ba7aae406596ef191fd84f873d2d2751f84d64e81a7a2d45" + "sha256:b84b238cce0d9adad5ed87e745778d20a3f8487d0f0cb8b8a586816c7496458d", + "sha256:c833ef592a0324bcc6a60e48440da07645063c453880c9477ceb22490aec1564" ], - "version": "==8.0.0" + "version": "==8.0.2" }, "msrest": { "hashes": [ @@ -514,10 +532,18 @@ }, "sqlalchemy": { "hashes": [ - "sha256:afa5541e9dea8ad0014251bc9d56171ca3d8b130c9627c6cb3681cff30be3f8a" + "sha256:bfb8f464a5000b567ac1d350b9090cf081180ec1ab4aa87e7bca12dab25320ec" ], "index": "pypi", - "version": "==1.3.11" + "version": "==1.3.12" + }, + "typing": { + "hashes": [ + "sha256:91dfe6f3f706ee8cc32d38edbbf304e9b7583fb37108fef38229617f8b3eba23", + "sha256:c8cabb5ab8945cd2f54917be357d134db9cc1eb039e59d1606dc1e60cb1d9d36", + "sha256:f38d83c5a7a7086543a0f649564d661859c5146a85775ab90c0d2f93ffaa9714" + ], + "version": "==3.7.4.1" }, "unipath": { "hashes": [ @@ -677,44 +703,46 @@ }, "colorama": { "hashes": [ - "sha256:05eed71e2e327246ad6b38c540c4a3117230b19679b875190486ddd2d721422d", - "sha256:f8ac84de7840f5b9c4e3347b3c1eaa50f7e49c2b07596221daec5edaabbd7c48" + "sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff", + "sha256:e96da0d330793e2cb9485e9ddfd918d456036c7149416295932478192f4436a1" ], - "version": "==0.4.1" + "version": "==0.4.3" }, "coverage": { "hashes": [ - "sha256:2358e685d0253125da42a48396038d4c7b4cd1448c00bbc4bda0cb8c43c2a870", - "sha256:25017cf384eeed2e6caf72efd3ec4124e32a8b7a4387600499104387975400c7", - "sha256:2e2de9423ff8b14303a97eafddd16c479fbcc9a0b8b0be3b7c3843a3e0cf6d69", - "sha256:324ed908e4e40a6e2451056fe502470ad4e79495cb7a03ecab94e6309c3e117e", - "sha256:34f865a0cf6255b694a46e4383a7131c61ea72c5b4c4f81d20e522fb1e440b4b", - "sha256:3a2bcc464b60a18f1f7167b95b2773ede93bf3722bfa59e0802717f652b6cc25", - "sha256:48d70865266d649b6602e2ba94820d7972ef470d3b72a8fd41a3d17321feed3a", - "sha256:50cf23523ab3a724c6905d3b60f87fa8250d9bae3995e09f49f63effa2b54f15", - "sha256:54c84a68abd8c4c5b71878b35eb85321df41f3d144c78181867d5b026ec74994", - "sha256:5b59d661ee7f3200aedd7b71882b7927ea7ed522df75e3853f316a79ad872a2e", - "sha256:5ffb39624bc573177888a21fb301ccee46838c600b27d58c3e9dae495f44d34a", - "sha256:699b3072b7f0e69ed175a88fa8b2ec7eefc4f34d490c54ed9a52feff21a15fdc", - "sha256:79ef4a2bb862110bd585174e551a783bee5c3aa461734a2ac7429193be357589", - "sha256:8210a6f93c4a8c6d460b402e20e38399529b99200c3318542faf6a520c9b6a5c", - "sha256:8d30c10cfd0a6fdf0a2d5023de00ef7b329cd6ead2310c9e53eab79c209acb70", - "sha256:97ac79ff28f2cda6ac00a803ee582b965951755f61ab43377482bfba450b619a", - "sha256:9fe4aacacff9028ed167db108bf013510654f148d83c4857fed61d2ce0588bf2", - "sha256:a5b6395d5957d638f8b1870561607e3c39b1a236ea6cff9eafe5b9bb1db913f2", - "sha256:ab32c5fad6905986a7e34e3acf01180a69bb60c2aa7331815b46e51c776a1943", - "sha256:ad67f0cfdfecbd49b9da46a7e488e6dc32a69388740b85c36a4ef4b33082cbad", - "sha256:aedad67c30326a1af324f45833a40b97180664912deb29942459ddbe9fa0ce19", - "sha256:b077cd0e70f41366ac1f9d09275258fa1906758a5d4f31cacc18b10dfcf90784", - "sha256:b8ea210810d3c14aec7561f8fe0d3eec582d1088100aaa0bb8153d53d867d20f", - "sha256:bf572722326ce6704e863447a070039a827072b7179352570859be899b9e6551", - "sha256:c0df57e189dacd2606cae6386acf127d01d85b2bf49acd9a65543b5d6c359ddc", - "sha256:d523e75f2a8a0b4a6a8be1287c0e0e3a561b8832b05ddd987d4cd7c62f3ad3bc", - "sha256:e10593c60c5f0bfd8b241bf9f27ef2191a3005b73dde8ada0424f642543a1e59", - "sha256:e9128444c83bc260aea988bf1ca6278a33ba730955bf94720468c656b61353eb", - "sha256:f7162f2e3711f3a08a8a741f92e1f63afd58d0713177979f2cf9723dd50161cf" + "sha256:0cd13a6e98c37b510a2d34c8281d5e1a226aaf9b65b7d770ef03c63169965351", + "sha256:1a4b6b6a2a3a6612e6361130c2cc3dc4378d8c221752b96167ccbad94b47f3cd", + "sha256:2ee55e6dba516ddf6f484aa83ccabbb0adf45a18892204c23486938d12258cde", + "sha256:3be5338a2eb4ef03c57f20917e1d12a1fd10e3853fed060b6d6b677cb3745898", + "sha256:44b783b02db03c4777d8cf71bae19eadc171a6f2a96777d916b2c30a1eb3d070", + "sha256:475bf7c4252af0a56e1abba9606f1e54127cdf122063095c75ab04f6f99cf45e", + "sha256:47c81ee687eafc2f1db7f03fbe99aab81330565ebc62fb3b61edfc2216a550c8", + "sha256:4a7f8e72b18f2aca288ff02255ce32cc830bc04d993efbc87abf6beddc9e56c0", + "sha256:50197163a22fd17f79086e087a787883b3ec9280a509807daf158dfc2a7ded02", + "sha256:56b13000acf891f700f5067512b804d1ec8c301d627486c678b903859d07f798", + "sha256:79388ae29c896299b3567965dbcd93255f175c17c6c7bca38614d12718c47466", + "sha256:79fd5d3d62238c4f583b75d48d53cdae759fe04d4fb18fe8b371d88ad2b6f8be", + "sha256:7fe3e2fde2bf1d7ce25ebcd2d3de3650b8d60d9a73ce6dcef36e20191291613d", + "sha256:81042a24f67b96e4287774014fa27220d8a4d91af1043389e4d73892efc89ac6", + "sha256:81326f1095c53111f8afc95da281e1414185f4a538609a77ca50bdfa39a6c207", + "sha256:8873dc0d8f42142ea9f20c27bbdc485190fff93823c6795be661703369e5877d", + "sha256:88d2cbcb0a112f47eef71eb95460b6995da18e6f8ca50c264585abc2c473154b", + "sha256:91f2491aeab9599956c45a77c5666d323efdec790bfe23fcceafcd91105d585a", + "sha256:979daa8655ae5a51e8e7a24e7d34e250ae8309fd9719490df92cbb2fe2b0422b", + "sha256:9c871b006c878a890c6e44a5b2f3c6291335324b298c904dc0402ee92ee1f0be", + "sha256:a6d092545e5af53e960465f652e00efbf5357adad177b2630d63978d85e46a72", + "sha256:b5ed7837b923d1d71c4f587ae1539ccd96bfd6be9788f507dbe94dab5febbb5d", + "sha256:ba259f68250f16d2444cbbfaddaa0bb20e1560a4fdaad50bece25c199e6af864", + "sha256:be1d89614c6b6c36d7578496dc8625123bda2ff44f224cf8b1c45b810ee7383f", + "sha256:c1b030a79749aa8d1f1486885040114ee56933b15ccfc90049ba266e4aa2139f", + "sha256:c95bb147fab76f2ecde332d972d8f4138b8f2daee6c466af4ff3b4f29bd4c19e", + "sha256:d52c1c2d7e856cecc05aa0526453cb14574f821b7f413cc279b9514750d795c1", + "sha256:d609a6d564ad3d327e9509846c2c47f170456344521462b469e5cb39e48ba31c", + "sha256:e1bad043c12fb58e8c7d92b3d7f2f49977dcb80a08a6d1e7a5114a11bf819fca", + "sha256:e5a675f6829c53c87d79117a8eb656cc4a5f8918185a32fc93ba09778e90f6db", + "sha256:fec32646b98baf4a22fdceb08703965bd16dea09051fbeb31a04b5b6e72b846c" ], - "version": "==5.0b1" + "version": "==5.0" }, "decorator": { "hashes": [ @@ -747,10 +775,10 @@ }, "faker": { "hashes": [ - "sha256:48c03580720e0b46538d528b1296e4e5b24a809dcaf33a7dddec719489a9edb8", - "sha256:6327c665c0d8721280b3036d9c9e851c60092bc1f30c8394cc433f8723e2bda5" + "sha256:202ad3b2ec16ae7c51c02904fb838831f8d2899e61bf18db1e91a5a582feab11", + "sha256:92c84a10bec81217d9cb554ee12b3838c8986ce0b5d45f72f769da22e4bb5432" ], - "version": "==2.0.4" + "version": "==3.0.0" }, "flask": { "hashes": [ @@ -791,25 +819,26 @@ }, "importlib-metadata": { "hashes": [ - "sha256:b044f07694ef14a6683b097ba56bd081dbc7cdc7c7fe46011e499dfecc082f21", - "sha256:e6ac600a142cf2db707b1998382cc7fc3b02befb7273876e01b8ad10b9652742" + "sha256:073a852570f92da5f744a3472af1b61e28e9f78ccf0c9117658dc32b15de7b45", + "sha256:d95141fbfa7ef2ec65cfd945e2af7e5a6ddbd7c8d9a25e66ff3be8e3daf9f60f" ], - "version": "==1.1.0" + "markers": "python_version < '3.8'", + "version": "==1.3.0" }, "ipdb": { "hashes": [ - "sha256:473fdd798a099765f093231a8b1fabfa95b0b682fce12de0c74b61a4b4d8ee57" + "sha256:5d9a4a0e3b7027a158fc6f2929934341045b9c3b0b86ed5d7e84e409653f72fd" ], "index": "pypi", - "version": "==0.12.2" + "version": "==0.12.3" }, "ipython": { "hashes": [ - "sha256:c66c7e27239855828a764b1e8fc72c24a6f4498a2637572094a78c5551fb9d51", - "sha256:f186b01b36609e0c5d0de27c7ef8e80c990c70478f8c880863004b3489a9030e" + "sha256:190a279bd3d4fc585a611e9358a88f1048cc57fd688254a86f9461889ee152a6", + "sha256:762d79a62b6aa96b04971e920543f558dfbeedc0468b899303c080c8068d4ac2" ], "index": "pypi", - "version": "==7.10.1" + "version": "==7.10.2" }, "ipython-genutils": { "hashes": [ @@ -914,10 +943,10 @@ }, "more-itertools": { "hashes": [ - "sha256:53ff73f186307d9c8ef17a9600309154a6ae27f25579e80af4db8f047ba14bc2", - "sha256:a0ea684c39bc4315ba7aae406596ef191fd84f873d2d2751f84d64e81a7a2d45" + "sha256:b84b238cce0d9adad5ed87e745778d20a3f8487d0f0cb8b8a586816c7496458d", + "sha256:c833ef592a0324bcc6a60e48440da07645063c453880c9477ceb22490aec1564" ], - "version": "==8.0.0" + "version": "==8.0.2" }, "mypy": { "hashes": [ @@ -948,10 +977,10 @@ }, "parso": { "hashes": [ - "sha256:63854233e1fadb5da97f2744b6b24346d2750b85965e7e399bec1620232797dc", - "sha256:666b0ee4a7a1220f65d367617f2cd3ffddff3e205f3f16a0284df30e774c2a9c" + "sha256:55cf25df1a35fd88b878715874d2c4dc1ad3f0eebd1e0266a67e1f55efccfbe1", + "sha256:5c1f7791de6bd5dbbeac8db0ef5594b36799de198b3f7f7014643b0c5536b9d3" ], - "version": "==0.5.1" + "version": "==0.5.2" }, "pathspec": { "hashes": [ @@ -1063,11 +1092,11 @@ }, "pytest-mock": { "hashes": [ - "sha256:96a0cebc66e09930be2a15b03333d90b59584d3fb011924f81c14b50ee0afbba", - "sha256:e5381be2608e49547f5e47633c5f81241ebf6206d17ce516a7a18d5a917e3859" + "sha256:67e414b3caef7bff6fc6bd83b22b5bc39147e4493f483c2679bc9d4dc485a94d", + "sha256:e24a911ec96773022ebcc7030059b57cd3480b56d4f5d19b7c370ec635e6aed5" ], "index": "pypi", - "version": "==1.12.1" + "version": "==1.13.0" }, "pytest-watch": { "hashes": [ @@ -1102,21 +1131,31 @@ }, "regex": { "hashes": [ - "sha256:15454b37c5a278f46f7aa2d9339bda450c300617ca2fca6558d05d870245edc7", - "sha256:1ad40708c255943a227e778b022c6497c129ad614bb7a2a2f916e12e8a359ee7", - "sha256:5e00f65cc507d13ab4dfa92c1232d004fa202c1d43a32a13940ab8a5afe2fb96", - "sha256:604dc563a02a74d70ae1f55208ddc9bfb6d9f470f6d1a5054c4bd5ae58744ab1", - "sha256:720e34a539a76a1fedcebe4397290604cc2bdf6f81eca44adb9fb2ea071c0c69", - "sha256:7caf47e4a9ac6ef08cabd3442cc4ca3386db141fb3c8b2a7e202d0470028e910", - "sha256:7faf534c1841c09d8fefa60ccde7b9903c9b528853ecf41628689793290ca143", - "sha256:b4e0406d822aa4993ac45072a584d57aa4931cf8288b5455bbf30c1d59dbad59", - "sha256:c31eaf28c6fe75ea329add0022efeed249e37861c19681960f99bbc7db981fb2", - "sha256:c7393597191fc2043c744db021643549061e12abe0b3ff5c429d806de7b93b66", - "sha256:d2b302f8cdd82c8f48e9de749d1d17f85ce9a0f082880b9a4859f66b07037dc6", - "sha256:e3d8dd0ec0ea280cf89026b0898971f5750a7bd92cb62c51af5a52abd020054a", - "sha256:ec032cbfed59bd5a4b8eab943c310acfaaa81394e14f44454ad5c9eba4f24a74" + "sha256:3d2d5952639615815a5dde7431265fc45b58106ca687ea16b60699c6946bfe02", + "sha256:3dbd8333fd2ebd50977ac8747385a73aa1f546eb6b16fcd83d274470fe11f243", + "sha256:40b7d1291a56897927e08bb973f8c186c2feb14c7f708bfe7aaee09483e85a20", + "sha256:517a827c4c9bcd4a158f48970258c17a52bdd133300c93affe8b5e9ae7b4675d", + "sha256:580e849ba64d7d82019c52d766b1f42cd8a398622278e8f89126800d7e5d52ea", + "sha256:719978a9145d59fc78509ea1d1bb74243f93583ef2a34dcc5623cf8118ae9726", + "sha256:75cf3796f89f75f83207a5c6a6e14eaf57e0369ef0ffff8e22bf36bbcfa0f1de", + "sha256:77396cf80be8b2a35db863cca4c1a902d88ceeb183adab328b81184e71a5eafe", + "sha256:77a3799152951d6d14ae5720ca162c97c64f85d4755da585418eac216b736cad", + "sha256:91235c98283d2bddf1a588f0fbc2da8afa37959294bbd18b76297bdf316ba4d6", + "sha256:99981ccc110b55d3bc2f5140167b8515c57f782ccdd0cd85d8217e1af1f1c632", + "sha256:a07f449fef6b8159080fd0be0e15b593ea55c2760f6340076fecc2845eac6c42", + "sha256:a35d1353ec805cea8a74bc5e141cc20083f2ade3d68bd92aa8b54115f08b902b", + "sha256:a70eb00ea3c18f68102cb125677812f66cacecc5a6187fa48eaef898b3ba45e5", + "sha256:aaffd68c4c1ed891366d5c390081f4bf6337595e76a157baf453603d8e53fbcb", + "sha256:ad9e3c7260809c0d1ded100269f78ea0217c0704f1eaaf40a382008461848b45", + "sha256:ba442ecf7df4c1657db237fa284719d95a8298bbac0056a73aca4e8a127f2968", + "sha256:bbddddfc768052abe88d02010c1f00c7dcd88430b775239fcc44ad2b1c9285b1", + "sha256:c203c9ee755e9656d0af8fab82754d5a664ebaf707b3f883c7eff6a3dd5151cf", + "sha256:c630f23491d0810767d3523b18b9c1e67c35319e298ed7e1a05dea0402ebd424", + "sha256:ccb78a4bf24b150e5b62cf5edff1e5f0b700064407dd0f03a5db7ff8451ee437", + "sha256:e865bc508e316a3a09d36c8621596e6599a203bc54f1cd41020a127ccdac468a", + "sha256:f8e3ca4669f6b09fdcbb3da71b358c7976f203d3e86b9e1be47790ed8915085e" ], - "version": "==2019.11.1" + "version": "==2019.12.9" }, "requests": { "hashes": [ diff --git a/atst/domain/csp/cloud.py b/atst/domain/csp/cloud.py index ea48ba4e..adb2260f 100644 --- a/atst/domain/csp/cloud.py +++ b/atst/domain/csp/cloud.py @@ -401,6 +401,7 @@ REMOTE_ROOT_ROLE_DEF_ID = "/providers/Microsoft.Authorization/roleDefinitions/00 class AzureSDKProvider(object): def __init__(self): from azure.mgmt import subscription, authorization, managementgroups + from azure.mgmt.resource import policy import azure.graphrbac as graphrbac import azure.common.credentials as credentials from msrestazure.azure_cloud import AZURE_PUBLIC_CLOUD @@ -410,6 +411,7 @@ class AzureSDKProvider(object): self.managementgroups = managementgroups self.graphrbac = graphrbac self.credentials = credentials + self.policy = policy # may change to a JEDI cloud self.cloud = AZURE_PUBLIC_CLOUD @@ -561,6 +563,51 @@ class AzureCloudProvider(CloudProviderInterface): # but we just don't have a valid ID pass + AZURE_MANAGEMENT_API = "https://management.azure.com" + + def _create_policy_definition( + self, credentials, subscription_id, management_group_id, properties, + ): + """ + Requires credentials that have AZURE_MANAGEMENT_API + specified as the resource. The Service Principal + specified in the credentials must have the "Resource + Policy Contributor" role assigned with a scope at least + as high as the management group specified by + management_group_id. + + Arguments: + credentials -- ServicePrincipalCredentials + subscription_id -- str, ID of the subscription (just the UUID, not the path) + management_group_id -- str, ID of the management group (just the UUID, not the path) + properties -- dictionary, the "properties" section of a valid Azure policy definition document + + Returns: + azure.mgmt.resource.policy.[api version].models.PolicyDefinition: the PolicyDefinition object provided to Azure + + Raises: + TBD + """ + # TODO: which subscription would this be? + client = self.sdk.policy.PolicyClient(credentials, subscription_id) + + definition = client.policy_definitions.models.PolicyDefinition( + policy_type=properties.get("policyType"), + mode=properties.get("mode"), + display_name=properties.get("displayName"), + description=properties.get("description"), + policy_rule=properties.get("policyRule"), + parameters=properties.get("parameters"), + ) + + name = properties.get("displayName") + + return client.policy_definitions.create_or_update_at_management_group( + policy_definition_name=name, + parameters=definition, + management_group_id=management_group_id, + ) + def _get_management_service_principal(self): # we really should be using graph.microsoft.com, but i'm getting # "expired token" errors for that diff --git a/atst/domain/csp/policy.py b/atst/domain/csp/policy.py new file mode 100644 index 00000000..43b4e232 --- /dev/null +++ b/atst/domain/csp/policy.py @@ -0,0 +1,12 @@ +class AzurePolicyManager: + def __init__(self, static_policy_location): + self._static_policy_location = static_policy_location + + def portfolio_definitions(): + pass + + def application_definitions(): + pass + + def environment_definitions(): + pass diff --git a/policies/portfolios/allowed-resource-types.json b/policies/portfolios/allowed-resource-types.json new file mode 100644 index 00000000..7e4dcb7f --- /dev/null +++ b/policies/portfolios/allowed-resource-types.json @@ -0,0 +1,40 @@ +{ + "definitionPoint": "portfolio-parent", + "policyDefinition": { + "properties": { + "displayName": "Allowed resource types", + "policyType": "Custom", + "mode": "Indexed", + "description": "This policy enables you to specify the resource types that your organization can deploy.", + "parameters": { + "listOfResourceTypesAllowed": { + "type": "Array", + "metadata": { + "description": "The list of resource types that can be deployed.", + "displayName": "Allowed resource types", + "strongType": "resourceTypes" + } + } + }, + "policyRule": { + "if": { + "not": { + "field": "type", + "in": "[parameters('listOfResourceTypesAllowed')]" + } + }, + "then": { + "effect": "deny" + } + } + }, + "type": "Microsoft.Authorization/policyDefinitions" + }, + "parameters": { + "listOfResourceTypesAllowed": { + "value": [ + "Microsoft.Cache" + ] + } + } +} diff --git a/policies/portfolios/region-restriction.json b/policies/portfolios/region-restriction.json new file mode 100644 index 00000000..9a7f57ba --- /dev/null +++ b/policies/portfolios/region-restriction.json @@ -0,0 +1,51 @@ +{ + "definitionPoint": "portfolio-parent", + "policyDefinition": { + "properties": { + "displayName": "Custom - Region Restriction", + "policyType": "Custom", + "mode": "Indexed", + "parameters": { + "listOfAllowedLocations": { + "type": "Array", + "metadata": { + "displayName": "Allowed locations", + "description": "The list of locations that can be specified when deploying resources.", + "strongType": "location" + } + } + }, + "policyRule": { + "if": { + "allOf": [ + { + "field": "location", + "notIn": "[parameters('listOfAllowedLocations')]" + }, + { + "field": "location", + "notEquals": "global" + }, + { + "field": "type", + "notEquals": "Microsoft.AzureActiveDirectory/b2cDirectories" + } + ] + }, + "then": { + "effect": "Deny" + } + } + }, + "type": "Microsoft.Authorization/policyDefinitions" + }, + "parameters": { + "listOfAllowedLocations": { + "value": [ + "eastus", + "southcentralus", + "westus" + ] + } + } +} diff --git a/tests/domain/cloud/test_azure_csp.py b/tests/domain/cloud/test_azure_csp.py index 39c6655e..dc10a6df 100644 --- a/tests/domain/cloud/test_azure_csp.py +++ b/tests/domain/cloud/test_azure_csp.py @@ -90,3 +90,28 @@ def test_create_atat_admin_user_succeeds(mock_azure: AzureCloudProvider): result = mock_azure.create_atat_admin_user(AUTH_CREDENTIALS, environment_id) assert result.get("csp_user_id") == csp_user_id + + +def test_create_policy_definition_succeeds(mock_azure: AzureCloudProvider): + subscription_id = str(uuid4()) + management_group_id = str(uuid4()) + properties = { + "policyType": "test", + "displayName": "test policy", + } + + result = mock_azure._create_policy_definition( + AUTH_CREDENTIALS, subscription_id, management_group_id, properties + ) + azure_sdk_method = ( + mock_azure.sdk.policy.PolicyClient.return_value.policy_definitions.create_or_update_at_management_group + ) + mock_policy_definition = ( + mock_azure.sdk.policy.PolicyClient.return_value.policy_definitions.models.PolicyDefinition() + ) + assert azure_sdk_method.called + azure_sdk_method.assert_called_with( + management_group_id=management_group_id, + policy_definition_name=properties.get("displayName"), + parameters=mock_policy_definition, + ) diff --git a/tests/mock_azure.py b/tests/mock_azure.py index a360df64..b8391811 100644 --- a/tests/mock_azure.py +++ b/tests/mock_azure.py @@ -46,6 +46,12 @@ def mock_credentials(): return Mock(spec=credentials) +def mock_policy(): + from azure.mgmt.resource import policy + + return Mock(spec=policy) + + class MockAzureSDK(object): def __init__(self): from msrestazure.azure_cloud import AZURE_PUBLIC_CLOUD @@ -55,6 +61,7 @@ class MockAzureSDK(object): self.managementgroups = mock_managementgroups() self.graphrbac = mock_graphrbac() self.credentials = mock_credentials() + self.policy = mock_policy() # may change to a JEDI cloud self.cloud = AZURE_PUBLIC_CLOUD From 6460c912dd64a72817b0f31b693220f90beba636 Mon Sep 17 00:00:00 2001 From: dandds Date: Wed, 18 Dec 2019 12:19:50 -0500 Subject: [PATCH 052/114] Remove Libcloud dependency --- Pipfile | 1 - Pipfile.lock | 102 +++++++++++++++++++-------------------------------- 2 files changed, 37 insertions(+), 66 deletions(-) diff --git a/Pipfile b/Pipfile index b4591d6f..ed87d000 100644 --- a/Pipfile +++ b/Pipfile @@ -18,7 +18,6 @@ flask-session = "*" flask-wtf = "*" pyopenssl = "*" requests = "*" -apache-libcloud = "*" lockfile = "*" werkzeug = "*" PyYAML = "*" diff --git a/Pipfile.lock b/Pipfile.lock index b97cfe92..d30bcbb2 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "dc6d11d395668b3e1ae047bec87eac86848348a4d322e00fc9f9837a301a072c" + "sha256": "c203c47b00f413fd40056ef6d2d8e51b37ad3ff5f7693db5eb170b7f8fd43234" }, "pipfile-spec": 6, "requires": { @@ -37,14 +37,6 @@ ], "version": "==2.5.2" }, - "apache-libcloud": { - "hashes": [ - "sha256:294d17774618dfb0896b14e69cdc3721850ec44dba81e7f91e701e75235a6eb1", - "sha256:29ee7d13b9b12d1335e752a489c01eed0c270940147f418cfff89ab66faf1305" - ], - "index": "pypi", - "version": "==2.7.0" - }, "azure-common": { "hashes": [ "sha256:53b1195b8f20943ccc0e71a17849258f7781bc6db1c72edc7d6c055f79bd54e3", @@ -216,15 +208,6 @@ ], "version": "==2.8" }, - "enum34": { - "hashes": [ - "sha256:2d81cbbe0e73112bdfe6ef8576f2238f2ba27dd0d55752a776c41d38b7da2850", - "sha256:644837f692e5f550741432dd3f223bbb9852018674981b1664e5dc339387588a", - "sha256:6bd0f6ad48ec2aa117d3d141940d484deccda84d4fcd884f5c3d93c23ecd8c79", - "sha256:8ad8c4783bf61ded74527bffb48ed9b54166685e4230386a9ed9b1279e2df5b1" - ], - "version": "==1.1.6" - }, "flask": { "hashes": [ "sha256:13f9f196f330c7c2c5d7a5cf91af894110ca0215ac051b5844701f2bfd934d52", @@ -537,14 +520,6 @@ "index": "pypi", "version": "==1.3.12" }, - "typing": { - "hashes": [ - "sha256:91dfe6f3f706ee8cc32d38edbbf304e9b7583fb37108fef38229617f8b3eba23", - "sha256:c8cabb5ab8945cd2f54917be357d134db9cc1eb039e59d1606dc1e60cb1d9d36", - "sha256:f38d83c5a7a7086543a0f649564d661859c5146a85775ab90c0d2f93ffaa9714" - ], - "version": "==3.7.4.1" - }, "unipath": { "hashes": [ "sha256:09839adcc72e8a24d4f76d63656f30b5a1f721fc40c9bcd79d8c67bdd8b47dae", @@ -950,23 +925,22 @@ }, "mypy": { "hashes": [ - "sha256:02d9bdd3398b636723ecb6c5cfe9773025a9ab7f34612c1cde5c7f2292e2d768", - "sha256:088f758a50af31cf8b42688118077292370c90c89232c783ba7979f39ea16646", - "sha256:28e9fbc96d13397a7ddb7fad7b14f373f91b5cff538e0772e77c270468df083c", - "sha256:30e123b24931f02c5d99307406658ac8f9cd6746f0d45a3dcac2fe5fbdd60939", - "sha256:3294821b5840d51a3cd7a2bb63b40fc3f901f6a3cfb3c6046570749c4c7ef279", - "sha256:41696a7d912ce16fdc7c141d87e8db5144d4be664a0c699a2b417d393994b0c2", - "sha256:4f42675fa278f3913340bb8c3371d191319704437758d7c4a8440346c293ecb2", - "sha256:54d205ccce6ed930a8a2ccf48404896d456e8b87812e491cb907a355b1a9c640", - "sha256:6992133c95a2847d309b4b0c899d7054adc60481df6f6b52bb7dee3d5fd157f7", - "sha256:6ecbd0e8e371333027abca0922b0c2c632a5b4739a0c61ffbd0733391e39144c", - "sha256:83fa87f556e60782c0fc3df1b37b7b4a840314ba1ac27f3e1a1e10cb37c89c17", - "sha256:c87ac7233c629f305602f563db07f5221950fe34fe30af072ac838fa85395f78", - "sha256:de9ec8dba773b78c49e7bec9a35c9b6fc5235682ad1fc2105752ae7c22f4b931", - "sha256:f385a0accf353ca1bca4bbf473b9d83ed18d923fdb809d3a70a385da23e25b6a" + "sha256:0308c35fd16c96a81b8dfc4d09ec63b8fa607cfec087acf5aafb44c2c45197de", + "sha256:39f7be2f89668d21b2bbab45ce5aa15e69bf8d6f3b46f9e1cc1a88e4fcc84f3d", + "sha256:4223f576813c79a10d0fd14192c86f1b85e3bd235c93792f22ed811a20b5ee4e", + "sha256:4c8f812a2fbefa96185933fbe05aa035e9cf791cf3a23bbdb6a219c80b60e0b1", + "sha256:4ea9ee847ea5bb38ea275441f3aea7eeba1b96187a3f968ee359d33d9dcc0eda", + "sha256:573c68df69f0e399fa57866a0b72989acf0a56c4008eee59c789c2ca5ea9df03", + "sha256:588c0e38466306aa7dbe6522ceacf37dde8b13cfa5edde90be2ce382f078875f", + "sha256:6d1bd2e675823a19e6bf72149540ab9851bfe698b796aea698fb926ab2bedd02", + "sha256:aa8e3bd1540dd5c39ef580ec2146a9c99c45f7c62af890095fec9e87b5ca19fb", + "sha256:b978ba1ea90d0abe2fc720ec9a41824b7d3a1304569bd58c9038d8d61dc4dfdb", + "sha256:c85c5367c2e8247e06cc0aba84e3633e90f48e8a0677bc51b351e138b5ff80b1", + "sha256:ce69577b424058bfa177df27213869f37c1e964c3e1ebd3b3d54f1d10b234c4d", + "sha256:ec6eaf98a57624d96d9916352a5bad2d73959f6358fabf43838f7d1a4d2f8389" ], "index": "pypi", - "version": "==0.750" + "version": "==0.760" }, "mypy-extensions": { "hashes": [ @@ -1131,31 +1105,29 @@ }, "regex": { "hashes": [ - "sha256:3d2d5952639615815a5dde7431265fc45b58106ca687ea16b60699c6946bfe02", - "sha256:3dbd8333fd2ebd50977ac8747385a73aa1f546eb6b16fcd83d274470fe11f243", - "sha256:40b7d1291a56897927e08bb973f8c186c2feb14c7f708bfe7aaee09483e85a20", - "sha256:517a827c4c9bcd4a158f48970258c17a52bdd133300c93affe8b5e9ae7b4675d", - "sha256:580e849ba64d7d82019c52d766b1f42cd8a398622278e8f89126800d7e5d52ea", - "sha256:719978a9145d59fc78509ea1d1bb74243f93583ef2a34dcc5623cf8118ae9726", - "sha256:75cf3796f89f75f83207a5c6a6e14eaf57e0369ef0ffff8e22bf36bbcfa0f1de", - "sha256:77396cf80be8b2a35db863cca4c1a902d88ceeb183adab328b81184e71a5eafe", - "sha256:77a3799152951d6d14ae5720ca162c97c64f85d4755da585418eac216b736cad", - "sha256:91235c98283d2bddf1a588f0fbc2da8afa37959294bbd18b76297bdf316ba4d6", - "sha256:99981ccc110b55d3bc2f5140167b8515c57f782ccdd0cd85d8217e1af1f1c632", - "sha256:a07f449fef6b8159080fd0be0e15b593ea55c2760f6340076fecc2845eac6c42", - "sha256:a35d1353ec805cea8a74bc5e141cc20083f2ade3d68bd92aa8b54115f08b902b", - "sha256:a70eb00ea3c18f68102cb125677812f66cacecc5a6187fa48eaef898b3ba45e5", - "sha256:aaffd68c4c1ed891366d5c390081f4bf6337595e76a157baf453603d8e53fbcb", - "sha256:ad9e3c7260809c0d1ded100269f78ea0217c0704f1eaaf40a382008461848b45", - "sha256:ba442ecf7df4c1657db237fa284719d95a8298bbac0056a73aca4e8a127f2968", - "sha256:bbddddfc768052abe88d02010c1f00c7dcd88430b775239fcc44ad2b1c9285b1", - "sha256:c203c9ee755e9656d0af8fab82754d5a664ebaf707b3f883c7eff6a3dd5151cf", - "sha256:c630f23491d0810767d3523b18b9c1e67c35319e298ed7e1a05dea0402ebd424", - "sha256:ccb78a4bf24b150e5b62cf5edff1e5f0b700064407dd0f03a5db7ff8451ee437", - "sha256:e865bc508e316a3a09d36c8621596e6599a203bc54f1cd41020a127ccdac468a", - "sha256:f8e3ca4669f6b09fdcbb3da71b358c7976f203d3e86b9e1be47790ed8915085e" + "sha256:0472acc4b6319801c1bc681d838c88ba1446f9ae199e01f6e41091c701fb3d42", + "sha256:16709434c4e2332ee8ba26ae339aceb8ab0b24b8398ebd0f52ebc943f45c4fc2", + "sha256:223fb63ec8dcab20b3318e93dcec4aee89e98b062934090bf29ffc374d2000a2", + "sha256:23c3ebf05d1cd3adb26723fd598e75724e0cdb7d6a35185ac0caf061cc6edb49", + "sha256:2404a50fb48badaf214b700f08822b68d93d79200e0aefd9569d0332d21fbfcb", + "sha256:2af3a7a16fed6eff85c25da106effa36f61cbbe801d00ade349b53ce7619eb15", + "sha256:37e018d3746baf159aedfc9773c3cafacbd10d354ba15484f5cfc8ed9da5748b", + "sha256:3c9c2988d02a9238a1975c70e87c6ce94e6f36dd8e372b66f468990cfe077434", + "sha256:47298bc8b89d1c747f0f5974aa528fc0b6b17396f1694136a224d51461279d83", + "sha256:4eeb0fe936797ae00a085f99802642bfc722b3b4ea557e9e7849cb621ea10c91", + "sha256:6881be0218b47ed76db033f252bab3f912dfe7ed1fe7baa9daebf51de08546a0", + "sha256:7ac08cee5055f548eed3889e9aaef15fd00172d037949496f1f0b34acb8a7c3e", + "sha256:7c5e2efcf079c35ff266c3f3a6708834f88f9fd04a3c16b855e036b2b7b1b543", + "sha256:8355eaa64724a0fdb010a1654b77cb3e375dc08b7f592cc4a1c05ac606aa481c", + "sha256:999a885f7f5194464238ad5d74b05982acee54002f3aa775d8e0e8c5fb74c06c", + "sha256:9fd2f4813eaa3e421e82819d38e5b634d900faff7ae5a80cd89ccff407175e69", + "sha256:a2e1e53df7dd27943da2b512895125b33fb20f81862c9fed7b3bab2a1de684d1", + "sha256:ab43bc0836820b7900dfffc025b996784aec26ec87dc1df4f95a40398760223f", + "sha256:ba449b56fa419fb19bf2a2438adbd2433f27087a6fe115917eaf9cfca684d5b6", + "sha256:d3f632cefad2cf247bd845794002585e3772288bfcb0dbac59fdecd32cd38b67", + "sha256:d51311496061863caae2cfe120cf1ef37900019b86c89c2d75f0918e0b4b8bf3" ], - "version": "==2019.12.9" + "version": "==2019.12.19" }, "requests": { "hashes": [ From 3bfb6c9621901672be05c5e0fe9a150a28c6b6b9 Mon Sep 17 00:00:00 2001 From: dandds Date: Wed, 18 Dec 2019 17:31:04 -0500 Subject: [PATCH 053/114] Basic implementation for a policy wrapper. The implementation here is meant to wrap a library of JSON policy documents. Policies should be added to directories corresponding to where they will be defined (portfolio, application, environment). Functionality for parsing portfolio policy definitions is included. When the policies need to be defined on a management group, the AzureCloudProvider can iterate the appropriate tier of the policy manager and add those definitions. --- .secrets.baseline | 4 +- atst/domain/csp/cloud.py | 3 ++ atst/domain/csp/policy.py | 43 +++++++++++++++++-- config/base.ini | 1 + .../portfolios/allowed-resource-types.json | 2 +- policies/portfolios/region-restriction.json | 2 +- tests/domain/cloud/test_policy.py | 8 ++++ tests/mock_azure.py | 1 + 8 files changed, 56 insertions(+), 8 deletions(-) create mode 100644 tests/domain/cloud/test_policy.py diff --git a/.secrets.baseline b/.secrets.baseline index ffa18c6e..857d311a 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "^.secrets.baseline$|^.*pgsslrootcert.yml$", "lines": null }, - "generated_at": "2019-12-18T15:29:41Z", + "generated_at": "2019-12-18T22:26:52Z", "plugins_used": [ { "base64_limit": 4.5, @@ -98,7 +98,7 @@ "hashed_secret": "afc848c316af1a89d49826c5ae9d00ed769415f3", "is_secret": false, "is_verified": false, - "line_number": 29, + "line_number": 30, "type": "Secret Keyword" } ], diff --git a/atst/domain/csp/cloud.py b/atst/domain/csp/cloud.py index adb2260f..36c91c95 100644 --- a/atst/domain/csp/cloud.py +++ b/atst/domain/csp/cloud.py @@ -6,6 +6,7 @@ from atst.models.user import User from atst.models.application import Application from atst.models.environment import Environment from atst.models.environment_role import EnvironmentRole +from .policy import AzurePolicyManager class GeneralCSPException(Exception): @@ -429,6 +430,8 @@ class AzureCloudProvider(CloudProviderInterface): else: self.sdk = azure_sdk_provider + self.policy_manager = AzurePolicyManager(config["AZURE_POLICY_LOCATION"]) + def create_environment( self, auth_credentials: Dict, user: User, environment: Environment ): diff --git a/atst/domain/csp/policy.py b/atst/domain/csp/policy.py index 43b4e232..cfff9aae 100644 --- a/atst/domain/csp/policy.py +++ b/atst/domain/csp/policy.py @@ -1,12 +1,47 @@ +from glob import glob +import json +from dataclasses import dataclass +from os.path import join as path_join + + class AzurePolicyManager: def __init__(self, static_policy_location): self._static_policy_location = static_policy_location - def portfolio_definitions(): + @property + def portfolio_definitions(self): + if getattr(self, "_portfolio_definitions", None) is None: + portfolio_files = self._glob_json("portfolios") + self._portfolio_definitions = self._load_policies(portfolio_files) + + return self._portfolio_definitions + + @property + def application_definitions(self): pass - def application_definitions(): + @property + def environment_definitions(self): pass - def environment_definitions(): - pass + def _glob_json(self, path): + return glob(path_join(self._static_policy_location, "portfolios", "*.json")) + + def _load_policies(self, json_policies): + return [self._load_policy(pol) for pol in json_policies] + + def _load_policy(self, policy_file): + with open(policy_file, "r") as file_: + doc = json.loads(file_.read()) + return AzurePolicy( + definition_point=doc["definitionPoint"], + definition=doc["policyDefinition"], + parameters=doc["parameters"], + ) + + +@dataclass +class AzurePolicy: + definition_point: str + definition: dict + parameters: dict diff --git a/config/base.ini b/config/base.ini index 2cc8fd93..0feba51f 100644 --- a/config/base.ini +++ b/config/base.ini @@ -3,6 +3,7 @@ ASSETS_URL AZURE_ACCOUNT_NAME AZURE_STORAGE_KEY AZURE_TO_BUCKET_NAME +AZURE_POLICY_LOCATION=policies BLOB_STORAGE_URL=http://localhost:8000/ CAC_URL = http://localhost:8000/login-redirect CA_CHAIN = ssl/server-certs/ca-chain.pem diff --git a/policies/portfolios/allowed-resource-types.json b/policies/portfolios/allowed-resource-types.json index 7e4dcb7f..1358a9f4 100644 --- a/policies/portfolios/allowed-resource-types.json +++ b/policies/portfolios/allowed-resource-types.json @@ -1,5 +1,5 @@ { - "definitionPoint": "portfolio-parent", + "definitionPoint": "portfolio", "policyDefinition": { "properties": { "displayName": "Allowed resource types", diff --git a/policies/portfolios/region-restriction.json b/policies/portfolios/region-restriction.json index 9a7f57ba..a828c40e 100644 --- a/policies/portfolios/region-restriction.json +++ b/policies/portfolios/region-restriction.json @@ -1,5 +1,5 @@ { - "definitionPoint": "portfolio-parent", + "definitionPoint": "portfolio", "policyDefinition": { "properties": { "displayName": "Custom - Region Restriction", diff --git a/tests/domain/cloud/test_policy.py b/tests/domain/cloud/test_policy.py new file mode 100644 index 00000000..c0189262 --- /dev/null +++ b/tests/domain/cloud/test_policy.py @@ -0,0 +1,8 @@ +from atst.domain.csp.policy import AzurePolicyManager, AzurePolicy + + +def test_portfolio_definitions(): + manager = AzurePolicyManager("policies") + assert len(manager.portfolio_definitions) > 0 + policy = manager.portfolio_definitions[0] + assert isinstance(policy, AzurePolicy) diff --git a/tests/mock_azure.py b/tests/mock_azure.py index b8391811..417e69fb 100644 --- a/tests/mock_azure.py +++ b/tests/mock_azure.py @@ -7,6 +7,7 @@ AZURE_CONFIG = { "AZURE_CLIENT_ID": "MOCK", "AZURE_SECRET_KEY": "MOCK", "AZURE_TENANT_ID": "MOCK", + "AZURE_POLICY_LOCATION": "policies", } AUTH_CREDENTIALS = { From 591c0f2315f26b795ee54bea10988dca71c4f270 Mon Sep 17 00:00:00 2001 From: "Jay R. Newlin (PromptWorks)" Date: Fri, 20 Dec 2019 10:51:25 -0500 Subject: [PATCH 054/114] Updates based on design changes and/or general maintenance of tests --- uitests/Application_Index_with_App.html | 22 +--- uitests/Create_New_Application.html | 21 +--- uitests/Create_New_TO.html | 27 +++-- uitests/Delete_Portfolio_Member.html | 6 +- uitests/Edit_App_Member.html | 22 +--- uitests/Edit_Portfolio_Member.html | 6 +- uitests/New_App_Step_1.html | 6 +- uitests/New_App_Step_2.html | 6 +- uitests/New_App_Step_2_-_Add_Env.html | 6 +- uitests/New_App_Step_3.html | 6 +- uitests/New_Portfolio.html | 6 +- uitests/New_Portfolio_Member.html | 6 +- uitests/Portfolio_Settings.html | 6 +- uitests/Remove_Portfolio_Member.html | 6 +- uitests/Reports_-_Basics.html | 28 +++-- uitests/Reports_-_Empty_State.html | 6 +- uitests/Reports_-_Follow_Add_App_Button.html | 29 +++-- uitests/Reports_-_Follow_TO_link.html | 29 +++-- ...orts_-_with_TO,_App,_and_Environments.html | 44 ++++---- uitests/Reports_-_with_expired_TO.html | 66 +++++++----- uitests/Resend_App_Member_Invite.html | 22 +--- uitests/Revoke_App_Member_Invite.html | 22 +--- uitests/Revoke_Environment_Access.html | 22 +--- ...TO_Index_(Landing)_Page_-_Empty_State.html | 6 +- uitests/TO_Index_with_Draft_TO.html | 28 +++-- uitests/TO_Index_with_TO.html | 28 +++-- uitests/TO_Index_with_Unsigned_TO.html | 28 +++-- uitests/TO_Index_with_expired_TO.html | 50 +++++++-- uitests/TO_Index_with_future_TO.html | 50 +++++++-- uitests/TO_Step_1.html | 6 +- uitests/TO_Step_2.html | 6 +- uitests/TO_Step_3.html | 6 +- uitests/TO_Step_3_-_Add_CLIN.html | 6 +- uitests/TO_Step_4.html | 6 +- uitests/TO_Step_5.html | 101 ++++++++++++++++-- uitests/login.html | 6 +- 36 files changed, 465 insertions(+), 282 deletions(-) diff --git a/uitests/Application_Index_with_App.html b/uitests/Application_Index_with_App.html index 67f34a53..99fbbb2d 100644 --- a/uitests/Application_Index_with_App.html +++ b/uitests/Application_Index_with_App.html @@ -112,13 +112,13 @@ Imported from: AT-AT CI - New Portfolio Imported from: AT-AT CI - login--> - + - - + + @@ -564,22 +564,6 @@ Imported from: AT-AT CI - New Portfolio--> - - - - - - - - - - - - - - - - diff --git a/uitests/Create_New_Application.html b/uitests/Create_New_Application.html index 0bac9367..6429feed 100644 --- a/uitests/Create_New_Application.html +++ b/uitests/Create_New_Application.html @@ -106,13 +106,13 @@ Imported from: AT-AT CI - login--> Imported from: AT-AT CI - login--> - + - - + + @@ -526,21 +526,6 @@ Imported from: AT-AT CI - login--> - - - - - - - - - - - - - - -
    waitForElementPresentcss=fieldset.usa-input__choices > legend > labelcss=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label
    clickcss=fieldset.usa-input__choices > legend > labelcss=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label
    waitForPageToLoad
    waitForElementPresentcss=.task-order__confirmation > div:nth-of-type(2) > .usa-input > fieldset.usa-input__choices > legend > label
    clickcss=.task-order__confirmation > div:nth-of-type(2) > .usa-input > fieldset.usa-input__choices > legend > label
    waitForElementPresentcss=fieldset.usa-input__choices > legend > labelcss=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label
    clickcss=fieldset.usa-input__choices > legend > labelcss=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label
    waitForPageToLoad
    waitForElementPresentcss=.task-order__confirmation > div:nth-of-type(2) > .usa-input > fieldset.usa-input__choices > legend > label
    clickcss=.task-order__confirmation > div:nth-of-type(2) > .usa-input > fieldset.usa-input__choices > legend > label
    waitForElementPresentcss=fieldset.usa-input__choices > legend > labelcss=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label
    clickcss=fieldset.usa-input__choices > legend > labelcss=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label
    waitForPageToLoad
    waitForElementPresentcss=.task-order__confirmation > div:nth-of-type(2) > .usa-input > fieldset.usa-input__choices > legend > label
    clickcss=.task-order__confirmation > div:nth-of-type(2) > .usa-input > fieldset.usa-input__choices > legend > label
    waitForElementPresentcss=.about-cloud > h1css=.home__content > h1
    assertTextcss=.about-cloud > h1About Cloud Servicescss=.home__content > h1JEDI Cloud Services
    waitForPageToLoad
    waitForElementPresentcss=#delete-application
    assertTextcss=#delete-application*Delete application*
    waitForPageToLoad
    waitForElementPresent css=.icon--applications
    waitForElementPresentcss=.about-cloud > h1css=.home__content > h1
    assertTextcss=.about-cloud > h1About Cloud Servicescss=.home__content > h1JEDI Cloud Services
    waitForPageToLoadcss=.accordion-table__items > .accordion-table__item:nth-of-type(1) > .accordion-table__item-content > .environment-list__item > .label.label--below
    waitForPageToLoad
    waitForElementPresentcss=#delete-application
    assertTextcss=#delete-application*Delete application*
    diff --git a/uitests/Create_New_TO.html b/uitests/Create_New_TO.html index 1980dfc8..8a20a1d4 100644 --- a/uitests/Create_New_TO.html +++ b/uitests/Create_New_TO.html @@ -47,13 +47,13 @@ Imported from: AT-AT CI - login--> Imported from: AT-AT CI - login--> waitForElementPresent -css=.about-cloud > h1 +css=.home__content > h1 assertText -css=.about-cloud > h1 -About Cloud Services +css=.home__content > h1 +JEDI Cloud Services waitForPageToLoad @@ -485,12 +485,27 @@ Imported from: AT-AT CI - login--> waitForElementPresent -css=fieldset.usa-input__choices > legend > label +css=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label - + click -css=fieldset.usa-input__choices > legend > label +css=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label + + + +waitForPageToLoad + + + + +waitForElementPresent +css=.task-order__confirmation > div:nth-of-type(2) > .usa-input > fieldset.usa-input__choices > legend > label + + + +click +css=.task-order__confirmation > div:nth-of-type(2) > .usa-input > fieldset.usa-input__choices > legend > label diff --git a/uitests/Delete_Portfolio_Member.html b/uitests/Delete_Portfolio_Member.html index 563113f0..a23c577f 100644 --- a/uitests/Delete_Portfolio_Member.html +++ b/uitests/Delete_Portfolio_Member.html @@ -114,13 +114,13 @@ Imported from: AT-AT CI - New Portfolio Imported from: AT-AT CI - login--> waitForElementPresent -css=.about-cloud > h1 +css=.home__content > h1 assertText -css=.about-cloud > h1 -About Cloud Services +css=.home__content > h1 +JEDI Cloud Services waitForPageToLoad diff --git a/uitests/Edit_App_Member.html b/uitests/Edit_App_Member.html index 5fa57810..835fe110 100644 --- a/uitests/Edit_App_Member.html +++ b/uitests/Edit_App_Member.html @@ -112,13 +112,13 @@ Imported from: AT-AT CI - New Portfolio Imported from: AT-AT CI - login--> waitForElementPresent -css=.about-cloud > h1 +css=.home__content > h1 assertText -css=.about-cloud > h1 -About Cloud Services +css=.home__content > h1 +JEDI Cloud Services waitForPageToLoad @@ -564,22 +564,6 @@ Imported from: AT-AT CI - New Portfolio--> - - -waitForElementPresent -css=#delete-application - - - -assertText -css=#delete-application -*Delete application* - - -waitForPageToLoad - - - waitForElementPresent css=svg.svg-inline--fa.fa-ellipsis-h diff --git a/uitests/Edit_Portfolio_Member.html b/uitests/Edit_Portfolio_Member.html index fea162c7..71d82e8f 100644 --- a/uitests/Edit_Portfolio_Member.html +++ b/uitests/Edit_Portfolio_Member.html @@ -114,13 +114,13 @@ Imported from: AT-AT CI - New Portfolio Imported from: AT-AT CI - login--> waitForElementPresent -css=.about-cloud > h1 +css=.home__content > h1 assertText -css=.about-cloud > h1 -About Cloud Services +css=.home__content > h1 +JEDI Cloud Services waitForPageToLoad diff --git a/uitests/New_App_Step_1.html b/uitests/New_App_Step_1.html index a65803c1..e3633143 100644 --- a/uitests/New_App_Step_1.html +++ b/uitests/New_App_Step_1.html @@ -47,13 +47,13 @@ Imported from: AT-AT CI - login--> Imported from: AT-AT CI - login--> waitForElementPresent -css=.about-cloud > h1 +css=.home__content > h1 assertText -css=.about-cloud > h1 -About Cloud Services +css=.home__content > h1 +JEDI Cloud Services waitForPageToLoad diff --git a/uitests/New_App_Step_2.html b/uitests/New_App_Step_2.html index 735842b0..1440a4ee 100644 --- a/uitests/New_App_Step_2.html +++ b/uitests/New_App_Step_2.html @@ -49,13 +49,13 @@ Imported from: AT-AT CI - New Portfolio Imported from: AT-AT CI - login--> waitForElementPresent -css=.about-cloud > h1 +css=.home__content > h1 assertText -css=.about-cloud > h1 -About Cloud Services +css=.home__content > h1 +JEDI Cloud Services waitForPageToLoad diff --git a/uitests/New_App_Step_2_-_Add_Env.html b/uitests/New_App_Step_2_-_Add_Env.html index 877f6ed2..fc806710 100644 --- a/uitests/New_App_Step_2_-_Add_Env.html +++ b/uitests/New_App_Step_2_-_Add_Env.html @@ -51,13 +51,13 @@ Imported from: AT-AT CI - New Portfolio Imported from: AT-AT CI - login--> waitForElementPresent -css=.about-cloud > h1 +css=.home__content > h1 assertText -css=.about-cloud > h1 -About Cloud Services +css=.home__content > h1 +JEDI Cloud Services waitForPageToLoad diff --git a/uitests/New_App_Step_3.html b/uitests/New_App_Step_3.html index 4794e5d1..f9bcbfba 100644 --- a/uitests/New_App_Step_3.html +++ b/uitests/New_App_Step_3.html @@ -110,13 +110,13 @@ Imported from: AT-AT CI - New Portfolio Imported from: AT-AT CI - login--> waitForElementPresent -css=.about-cloud > h1 +css=.home__content > h1 assertText -css=.about-cloud > h1 -About Cloud Services +css=.home__content > h1 +JEDI Cloud Services waitForPageToLoad diff --git a/uitests/New_Portfolio.html b/uitests/New_Portfolio.html index 5495828f..7b3cd75c 100644 --- a/uitests/New_Portfolio.html +++ b/uitests/New_Portfolio.html @@ -45,13 +45,13 @@ waitForElementPresent -css=.about-cloud > h1 +css=.home__content > h1 assertText -css=.about-cloud > h1 -About Cloud Services +css=.home__content > h1 +JEDI Cloud Services waitForPageToLoad diff --git a/uitests/New_Portfolio_Member.html b/uitests/New_Portfolio_Member.html index cb960f1c..1026a81c 100644 --- a/uitests/New_Portfolio_Member.html +++ b/uitests/New_Portfolio_Member.html @@ -108,13 +108,13 @@ Imported from: AT-AT CI - New Portfolio Imported from: AT-AT CI - login--> waitForElementPresent -css=.about-cloud > h1 +css=.home__content > h1 assertText -css=.about-cloud > h1 -About Cloud Services +css=.home__content > h1 +JEDI Cloud Services waitForPageToLoad diff --git a/uitests/Portfolio_Settings.html b/uitests/Portfolio_Settings.html index 02424caf..fcf2686d 100644 --- a/uitests/Portfolio_Settings.html +++ b/uitests/Portfolio_Settings.html @@ -47,13 +47,13 @@ Imported from: AT-AT CI - login--> Imported from: AT-AT CI - login--> waitForElementPresent -css=.about-cloud > h1 +css=.home__content > h1 assertText -css=.about-cloud > h1 -About Cloud Services +css=.home__content > h1 +JEDI Cloud Services waitForPageToLoad diff --git a/uitests/Remove_Portfolio_Member.html b/uitests/Remove_Portfolio_Member.html index fc1844e2..41a1186e 100644 --- a/uitests/Remove_Portfolio_Member.html +++ b/uitests/Remove_Portfolio_Member.html @@ -114,13 +114,13 @@ Imported from: AT-AT CI - New Portfolio Imported from: AT-AT CI - login--> waitForElementPresent -css=.about-cloud > h1 +css=.home__content > h1 assertText -css=.about-cloud > h1 -About Cloud Services +css=.home__content > h1 +JEDI Cloud Services waitForPageToLoad diff --git a/uitests/Reports_-_Basics.html b/uitests/Reports_-_Basics.html index 5f1d9eda..1449bf1b 100644 --- a/uitests/Reports_-_Basics.html +++ b/uitests/Reports_-_Basics.html @@ -49,13 +49,13 @@ Imported from: AT-AT CI - New Portfolio Imported from: AT-AT CI - login--> waitForElementPresent -css=.about-cloud > h1 +css=.home__content > h1 assertText -css=.about-cloud > h1 -About Cloud Services +css=.home__content > h1 +JEDI Cloud Services waitForPageToLoad @@ -516,12 +516,28 @@ Ghost Inspector flow control because button tends to take a little while to beco waitForElementPresent -css=fieldset.usa-input__choices > legend > label +css=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label - + click -css=fieldset.usa-input__choices > legend > label +css=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label + + + +waitForPageToLoad + + + + + +waitForElementPresent +css=.task-order__confirmation > div:nth-of-type(2) > .usa-input > fieldset.usa-input__choices > legend > label + + + +click +css=.task-order__confirmation > div:nth-of-type(2) > .usa-input > fieldset.usa-input__choices > legend > label diff --git a/uitests/Reports_-_Empty_State.html b/uitests/Reports_-_Empty_State.html index 602407d8..84bff58d 100644 --- a/uitests/Reports_-_Empty_State.html +++ b/uitests/Reports_-_Empty_State.html @@ -47,13 +47,13 @@ Imported from: AT-AT CI - login--> Imported from: AT-AT CI - login--> waitForElementPresent -css=.about-cloud > h1 +css=.home__content > h1 assertText -css=.about-cloud > h1 -About Cloud Services +css=.home__content > h1 +JEDI Cloud Services waitForPageToLoad diff --git a/uitests/Reports_-_Follow_Add_App_Button.html b/uitests/Reports_-_Follow_Add_App_Button.html index abe9c94f..fc423c69 100644 --- a/uitests/Reports_-_Follow_Add_App_Button.html +++ b/uitests/Reports_-_Follow_Add_App_Button.html @@ -51,13 +51,13 @@ Imported from: AT-AT CI - New Portfolio Imported from: AT-AT CI - login--> waitForElementPresent -css=.about-cloud > h1 +css=.home__content > h1 assertText -css=.about-cloud > h1 -About Cloud Services +css=.home__content > h1 +JEDI Cloud Services waitForPageToLoad @@ -547,12 +547,29 @@ Imported from: AT-AT CI - Create New TO--> Imported from: AT-AT CI - Create New TO--> waitForElementPresent -css=fieldset.usa-input__choices > legend > label +css=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label - + click -css=fieldset.usa-input__choices > legend > label +css=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label + + + +waitForPageToLoad + + + + + +waitForElementPresent +css=.task-order__confirmation > div:nth-of-type(2) > .usa-input > fieldset.usa-input__choices > legend > label + + + +click +css=.task-order__confirmation > div:nth-of-type(2) > .usa-input > fieldset.usa-input__choices > legend > label diff --git a/uitests/Reports_-_Follow_TO_link.html b/uitests/Reports_-_Follow_TO_link.html index 8af494c1..6e653c9f 100644 --- a/uitests/Reports_-_Follow_TO_link.html +++ b/uitests/Reports_-_Follow_TO_link.html @@ -51,13 +51,13 @@ Imported from: AT-AT CI - New Portfolio Imported from: AT-AT CI - login--> waitForElementPresent -css=.about-cloud > h1 +css=.home__content > h1 assertText -css=.about-cloud > h1 -About Cloud Services +css=.home__content > h1 +JEDI Cloud Services waitForPageToLoad @@ -547,12 +547,29 @@ Imported from: AT-AT CI - Create New TO--> Imported from: AT-AT CI - Create New TO--> waitForElementPresent -css=fieldset.usa-input__choices > legend > label +css=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label - + click -css=fieldset.usa-input__choices > legend > label +css=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label + + + +waitForPageToLoad + + + + + +waitForElementPresent +css=.task-order__confirmation > div:nth-of-type(2) > .usa-input > fieldset.usa-input__choices > legend > label + + + +click +css=.task-order__confirmation > div:nth-of-type(2) > .usa-input > fieldset.usa-input__choices > legend > label diff --git a/uitests/Reports_-_with_TO,_App,_and_Environments.html b/uitests/Reports_-_with_TO,_App,_and_Environments.html index 5fa2f879..cbeb4c5f 100644 --- a/uitests/Reports_-_with_TO,_App,_and_Environments.html +++ b/uitests/Reports_-_with_TO,_App,_and_Environments.html @@ -112,13 +112,13 @@ Imported from: AT-AT CI - New Portfolio Imported from: AT-AT CI - login--> waitForElementPresent -css=.about-cloud > h1 +css=.home__content > h1 assertText -css=.about-cloud > h1 -About Cloud Services +css=.home__content > h1 +JEDI Cloud Services waitForPageToLoad @@ -564,22 +564,6 @@ Imported from: AT-AT CI - New Portfolio--> - - -waitForElementPresent -css=#delete-application - - - -assertText -css=#delete-application -*Delete application* - - -waitForPageToLoad - - - waitForElementPresent @@ -915,12 +899,28 @@ Ghost Inspector flow control because button tends to take a little while to beco waitForElementPresent -css=fieldset.usa-input__choices > legend > label +css=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label - + click -css=fieldset.usa-input__choices > legend > label +css=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label + + + +waitForPageToLoad + + + + + +waitForElementPresent +css=.task-order__confirmation > div:nth-of-type(2) > .usa-input > fieldset.usa-input__choices > legend > label + + + +click +css=.task-order__confirmation > div:nth-of-type(2) > .usa-input > fieldset.usa-input__choices > legend > label diff --git a/uitests/Reports_-_with_expired_TO.html b/uitests/Reports_-_with_expired_TO.html index 34eff04b..6bfc1c09 100644 --- a/uitests/Reports_-_with_expired_TO.html +++ b/uitests/Reports_-_with_expired_TO.html @@ -112,13 +112,13 @@ Imported from: AT-AT CI - New Portfolio Imported from: AT-AT CI - login--> waitForElementPresent -css=.about-cloud > h1 +css=.home__content > h1 assertText -css=.about-cloud > h1 -About Cloud Services +css=.home__content > h1 +JEDI Cloud Services waitForPageToLoad @@ -564,22 +564,6 @@ Imported from: AT-AT CI - New Portfolio--> - - -waitForElementPresent -css=#delete-application - - - -assertText -css=#delete-application -*Delete application* - - -waitForPageToLoad - - - waitForElementPresent @@ -915,12 +899,28 @@ Ghost Inspector flow control because button tends to take a little while to beco waitForElementPresent -css=fieldset.usa-input__choices > legend > label +css=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label - + click -css=fieldset.usa-input__choices > legend > label +css=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label + + + +waitForPageToLoad + + + + + +waitForElementPresent +css=.task-order__confirmation > div:nth-of-type(2) > .usa-input > fieldset.usa-input__choices > legend > label + + + +click +css=.task-order__confirmation > div:nth-of-type(2) > .usa-input > fieldset.usa-input__choices > legend > label @@ -1279,12 +1279,28 @@ Ghost Inspector flow control because button tends to take a little while to beco waitForElementPresent -css=fieldset.usa-input__choices > legend > label +css=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label - + click -css=fieldset.usa-input__choices > legend > label +css=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label + + + +waitForPageToLoad + + + + + +waitForElementPresent +css=.task-order__confirmation > div:nth-of-type(2) > .usa-input > fieldset.usa-input__choices > legend > label + + + +click +css=.task-order__confirmation > div:nth-of-type(2) > .usa-input > fieldset.usa-input__choices > legend > label diff --git a/uitests/Resend_App_Member_Invite.html b/uitests/Resend_App_Member_Invite.html index e7f8afdf..7ade41f8 100644 --- a/uitests/Resend_App_Member_Invite.html +++ b/uitests/Resend_App_Member_Invite.html @@ -112,13 +112,13 @@ Imported from: AT-AT CI - New Portfolio Imported from: AT-AT CI - login--> waitForElementPresent -css=.about-cloud > h1 +css=.home__content > h1 assertText -css=.about-cloud > h1 -About Cloud Services +css=.home__content > h1 +JEDI Cloud Services waitForPageToLoad @@ -564,22 +564,6 @@ Imported from: AT-AT CI - New Portfolio--> - - -waitForElementPresent -css=#delete-application - - - -assertText -css=#delete-application -*Delete application* - - -waitForPageToLoad - - - waitForElementPresent css=svg.svg-inline--fa.fa-ellipsis-h diff --git a/uitests/Revoke_App_Member_Invite.html b/uitests/Revoke_App_Member_Invite.html index 771cd4a0..3f4ab7bb 100644 --- a/uitests/Revoke_App_Member_Invite.html +++ b/uitests/Revoke_App_Member_Invite.html @@ -112,13 +112,13 @@ Imported from: AT-AT CI - New Portfolio Imported from: AT-AT CI - login--> waitForElementPresent -css=.about-cloud > h1 +css=.home__content > h1 assertText -css=.about-cloud > h1 -About Cloud Services +css=.home__content > h1 +JEDI Cloud Services waitForPageToLoad @@ -564,22 +564,6 @@ Imported from: AT-AT CI - New Portfolio--> - - -waitForElementPresent -css=#delete-application - - - -assertText -css=#delete-application -*Delete application* - - -waitForPageToLoad - - - waitForElementPresent css=svg.svg-inline--fa.fa-ellipsis-h diff --git a/uitests/Revoke_Environment_Access.html b/uitests/Revoke_Environment_Access.html index 56bc1bdb..dcee46b9 100644 --- a/uitests/Revoke_Environment_Access.html +++ b/uitests/Revoke_Environment_Access.html @@ -112,13 +112,13 @@ Imported from: AT-AT CI - New Portfolio Imported from: AT-AT CI - login--> waitForElementPresent -css=.about-cloud > h1 +css=.home__content > h1 assertText -css=.about-cloud > h1 -About Cloud Services +css=.home__content > h1 +JEDI Cloud Services waitForPageToLoad @@ -564,22 +564,6 @@ Imported from: AT-AT CI - New Portfolio--> - - -waitForElementPresent -css=#delete-application - - - -assertText -css=#delete-application -*Delete application* - - -waitForPageToLoad - - - waitForElementPresent css=svg.svg-inline--fa.fa-ellipsis-h.fa-w-16 diff --git a/uitests/TO_Index_(Landing)_Page_-_Empty_State.html b/uitests/TO_Index_(Landing)_Page_-_Empty_State.html index 70d615fc..a1ba32b6 100644 --- a/uitests/TO_Index_(Landing)_Page_-_Empty_State.html +++ b/uitests/TO_Index_(Landing)_Page_-_Empty_State.html @@ -47,13 +47,13 @@ Imported from: AT-AT CI - login--> Imported from: AT-AT CI - login--> waitForElementPresent -css=.about-cloud > h1 +css=.home__content > h1 assertText -css=.about-cloud > h1 -About Cloud Services +css=.home__content > h1 +JEDI Cloud Services waitForPageToLoad diff --git a/uitests/TO_Index_with_Draft_TO.html b/uitests/TO_Index_with_Draft_TO.html index 1769434e..48a09943 100644 --- a/uitests/TO_Index_with_Draft_TO.html +++ b/uitests/TO_Index_with_Draft_TO.html @@ -49,13 +49,13 @@ Imported from: AT-AT CI - New Portfolio Imported from: AT-AT CI - login--> waitForElementPresent -css=.about-cloud > h1 +css=.home__content > h1 assertText -css=.about-cloud > h1 -About Cloud Services +css=.home__content > h1 +JEDI Cloud Services waitForPageToLoad @@ -516,12 +516,28 @@ Ghost Inspector flow control because button tends to take a little while to beco waitForElementPresent -css=fieldset.usa-input__choices > legend > label +css=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label - + click -css=fieldset.usa-input__choices > legend > label +css=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label + + + +waitForPageToLoad + + + + + +waitForElementPresent +css=.task-order__confirmation > div:nth-of-type(2) > .usa-input > fieldset.usa-input__choices > legend > label + + + +click +css=.task-order__confirmation > div:nth-of-type(2) > .usa-input > fieldset.usa-input__choices > legend > label diff --git a/uitests/TO_Index_with_TO.html b/uitests/TO_Index_with_TO.html index a96d033c..5be5805d 100644 --- a/uitests/TO_Index_with_TO.html +++ b/uitests/TO_Index_with_TO.html @@ -49,13 +49,13 @@ Imported from: AT-AT CI - New Portfolio Imported from: AT-AT CI - login--> waitForElementPresent -css=.about-cloud > h1 +css=.home__content > h1 assertText -css=.about-cloud > h1 -About Cloud Services +css=.home__content > h1 +JEDI Cloud Services waitForPageToLoad @@ -516,12 +516,28 @@ Ghost Inspector flow control because button tends to take a little while to beco waitForElementPresent -css=fieldset.usa-input__choices > legend > label +css=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label - + click -css=fieldset.usa-input__choices > legend > label +css=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label + + + +waitForPageToLoad + + + + + +waitForElementPresent +css=.task-order__confirmation > div:nth-of-type(2) > .usa-input > fieldset.usa-input__choices > legend > label + + + +click +css=.task-order__confirmation > div:nth-of-type(2) > .usa-input > fieldset.usa-input__choices > legend > label diff --git a/uitests/TO_Index_with_Unsigned_TO.html b/uitests/TO_Index_with_Unsigned_TO.html index 86897b35..107b652a 100644 --- a/uitests/TO_Index_with_Unsigned_TO.html +++ b/uitests/TO_Index_with_Unsigned_TO.html @@ -49,13 +49,13 @@ Imported from: AT-AT CI - New Portfolio Imported from: AT-AT CI - login--> waitForElementPresent -css=.about-cloud > h1 +css=.home__content > h1 assertText -css=.about-cloud > h1 -About Cloud Services +css=.home__content > h1 +JEDI Cloud Services waitForPageToLoad @@ -516,12 +516,28 @@ Ghost Inspector flow control because button tends to take a little while to beco waitForElementPresent -css=fieldset.usa-input__choices > legend > label +css=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label - + click -css=fieldset.usa-input__choices > legend > label +css=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label + + + +waitForPageToLoad + + + + + +waitForElementPresent +css=.task-order__confirmation > div:nth-of-type(2) > .usa-input > fieldset.usa-input__choices > legend > label + + + +click +css=.task-order__confirmation > div:nth-of-type(2) > .usa-input > fieldset.usa-input__choices > legend > label diff --git a/uitests/TO_Index_with_expired_TO.html b/uitests/TO_Index_with_expired_TO.html index 401645e6..0059a503 100644 --- a/uitests/TO_Index_with_expired_TO.html +++ b/uitests/TO_Index_with_expired_TO.html @@ -49,13 +49,13 @@ Imported from: AT-AT CI - New Portfolio Imported from: AT-AT CI - login--> waitForElementPresent -css=.about-cloud > h1 +css=.home__content > h1 assertText -css=.about-cloud > h1 -About Cloud Services +css=.home__content > h1 +JEDI Cloud Services waitForPageToLoad @@ -516,12 +516,28 @@ Ghost Inspector flow control because button tends to take a little while to beco waitForElementPresent -css=fieldset.usa-input__choices > legend > label +css=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label - + click -css=fieldset.usa-input__choices > legend > label +css=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label + + + +waitForPageToLoad + + + + + +waitForElementPresent +css=.task-order__confirmation > div:nth-of-type(2) > .usa-input > fieldset.usa-input__choices > legend > label + + + +click +css=.task-order__confirmation > div:nth-of-type(2) > .usa-input > fieldset.usa-input__choices > legend > label @@ -880,12 +896,28 @@ Ghost Inspector flow control because button tends to take a little while to beco waitForElementPresent -css=fieldset.usa-input__choices > legend > label +css=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label - + click -css=fieldset.usa-input__choices > legend > label +css=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label + + + +waitForPageToLoad + + + + + +waitForElementPresent +css=.task-order__confirmation > div:nth-of-type(2) > .usa-input > fieldset.usa-input__choices > legend > label + + + +click +css=.task-order__confirmation > div:nth-of-type(2) > .usa-input > fieldset.usa-input__choices > legend > label diff --git a/uitests/TO_Index_with_future_TO.html b/uitests/TO_Index_with_future_TO.html index ff3ddb1a..d8a6a527 100644 --- a/uitests/TO_Index_with_future_TO.html +++ b/uitests/TO_Index_with_future_TO.html @@ -49,13 +49,13 @@ Imported from: AT-AT CI - New Portfolio Imported from: AT-AT CI - login--> waitForElementPresent -css=.about-cloud > h1 +css=.home__content > h1 assertText -css=.about-cloud > h1 -About Cloud Services +css=.home__content > h1 +JEDI Cloud Services waitForPageToLoad @@ -516,12 +516,28 @@ Ghost Inspector flow control because button tends to take a little while to beco waitForElementPresent -css=fieldset.usa-input__choices > legend > label +css=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label - + click -css=fieldset.usa-input__choices > legend > label +css=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label + + + +waitForPageToLoad + + + + + +waitForElementPresent +css=.task-order__confirmation > div:nth-of-type(2) > .usa-input > fieldset.usa-input__choices > legend > label + + + +click +css=.task-order__confirmation > div:nth-of-type(2) > .usa-input > fieldset.usa-input__choices > legend > label @@ -880,12 +896,28 @@ Ghost Inspector flow control because button tends to take a little while to beco waitForElementPresent -css=fieldset.usa-input__choices > legend > label +css=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label - + click -css=fieldset.usa-input__choices > legend > label +css=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label + + + +waitForPageToLoad + + + + + +waitForElementPresent +css=.task-order__confirmation > div:nth-of-type(2) > .usa-input > fieldset.usa-input__choices > legend > label + + + +click +css=.task-order__confirmation > div:nth-of-type(2) > .usa-input > fieldset.usa-input__choices > legend > label diff --git a/uitests/TO_Step_1.html b/uitests/TO_Step_1.html index 217798ca..93ad1360 100644 --- a/uitests/TO_Step_1.html +++ b/uitests/TO_Step_1.html @@ -47,13 +47,13 @@ Imported from: AT-AT CI - login--> Imported from: AT-AT CI - login--> waitForElementPresent -css=.about-cloud > h1 +css=.home__content > h1 assertText -css=.about-cloud > h1 -About Cloud Services +css=.home__content > h1 +JEDI Cloud Services waitForPageToLoad diff --git a/uitests/TO_Step_2.html b/uitests/TO_Step_2.html index 980b2628..1624476c 100644 --- a/uitests/TO_Step_2.html +++ b/uitests/TO_Step_2.html @@ -49,13 +49,13 @@ Imported from: AT-AT CI - New Portfolio Imported from: AT-AT CI - login--> waitForElementPresent -css=.about-cloud > h1 +css=.home__content > h1 assertText -css=.about-cloud > h1 -About Cloud Services +css=.home__content > h1 +JEDI Cloud Services waitForPageToLoad diff --git a/uitests/TO_Step_3.html b/uitests/TO_Step_3.html index 6467b614..1e7453d4 100644 --- a/uitests/TO_Step_3.html +++ b/uitests/TO_Step_3.html @@ -51,13 +51,13 @@ Imported from: AT-AT CI - New Portfolio Imported from: AT-AT CI - login--> waitForElementPresent -css=.about-cloud > h1 +css=.home__content > h1 assertText -css=.about-cloud > h1 -About Cloud Services +css=.home__content > h1 +JEDI Cloud Services waitForPageToLoad diff --git a/uitests/TO_Step_3_-_Add_CLIN.html b/uitests/TO_Step_3_-_Add_CLIN.html index e385a3a8..df70e88b 100644 --- a/uitests/TO_Step_3_-_Add_CLIN.html +++ b/uitests/TO_Step_3_-_Add_CLIN.html @@ -53,13 +53,13 @@ Imported from: AT-AT CI - New Portfolio Imported from: AT-AT CI - login--> waitForElementPresent -css=.about-cloud > h1 +css=.home__content > h1 assertText -css=.about-cloud > h1 -About Cloud Services +css=.home__content > h1 +JEDI Cloud Services waitForPageToLoad diff --git a/uitests/TO_Step_4.html b/uitests/TO_Step_4.html index bf7ecb81..6beec61f 100644 --- a/uitests/TO_Step_4.html +++ b/uitests/TO_Step_4.html @@ -53,13 +53,13 @@ Imported from: AT-AT CI - New Portfolio Imported from: AT-AT CI - login--> waitForElementPresent -css=.about-cloud > h1 +css=.home__content > h1 assertText -css=.about-cloud > h1 -About Cloud Services +css=.home__content > h1 +JEDI Cloud Services waitForPageToLoad diff --git a/uitests/TO_Step_5.html b/uitests/TO_Step_5.html index 7f56ad80..4382e8eb 100644 --- a/uitests/TO_Step_5.html +++ b/uitests/TO_Step_5.html @@ -55,13 +55,13 @@ Imported from: AT-AT CI - New Portfolio Imported from: AT-AT CI - login--> waitForElementPresent -css=.about-cloud > h1 +css=.home__content > h1 assertText -css=.about-cloud > h1 -About Cloud Services +css=.home__content > h1 +JEDI Cloud Services waitForPageToLoad @@ -847,13 +847,13 @@ Imported from: AT-AT CI - TO Step 3--> waitForElementPresent -css=.h2 +css=span.sticky-cta-context assertText -css=.h2 -*Confirm Signature* +css=span.sticky-cta-context +*Step 5 of 5* waitForPageToLoad @@ -862,12 +862,97 @@ Imported from: AT-AT CI - TO Step 3--> waitForElementPresent -css=fieldset.usa-input__choices > legend > label +css=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label + + + +click +css=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label +waitForPageToLoad + + + + +waitForElementPresent +css=input[type="submit"][disabled="disabled"] + + + +assertElementPresent +css=input[type="submit"][disabled="disabled"] + + + +waitForPageToLoad + + + + +waitForElementPresent +css=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label + + + click -css=fieldset.usa-input__choices > legend > label +css=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label + + + +waitForPageToLoad + + + + +waitForElementPresent +css=.task-order__confirmation > div:nth-of-type(2) > .usa-input > fieldset.usa-input__choices > legend > label + + + +click +css=.task-order__confirmation > div:nth-of-type(2) > .usa-input > fieldset.usa-input__choices > legend > label + + + +waitForPageToLoad + + + + +waitForElementPresent +css=input[type="submit"][disabled="disabled"] + + + +assertElementPresent +css=input[type="submit"][disabled="disabled"] + + + +waitForPageToLoad + + + + +waitForElementPresent +css=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label + + + +click +css=.task-order__confirmation > div:nth-of-type(1) > .usa-input > fieldset.usa-input__choices > legend > label + + + +waitForPageToLoad + + + + +assertElementNotPresent +css=input[type="submit"][disabled="disabled"] diff --git a/uitests/login.html b/uitests/login.html index 764b248f..c5228cdf 100644 --- a/uitests/login.html +++ b/uitests/login.html @@ -43,13 +43,13 @@ waitForElementPresent -css=.about-cloud > h1 +css=.home__content > h1 assertText -css=.about-cloud > h1 -About Cloud Services +css=.home__content > h1 +JEDI Cloud Services From d81b82956b2b57e5cbb08f5cd75e5f07fb21cf60 Mon Sep 17 00:00:00 2001 From: graham-dds Date: Fri, 20 Dec 2019 11:02:21 -0600 Subject: [PATCH 055/114] Remove old kwargs from SideNavItem --- templates/help/index.html | 2 -- 1 file changed, 2 deletions(-) diff --git a/templates/help/index.html b/templates/help/index.html index de8e9b97..89a25dd5 100644 --- a/templates/help/index.html +++ b/templates/help/index.html @@ -12,7 +12,6 @@ {{ SidenavItem("JEDI Cloud Help", href = url_for("atst.helpdocs"), active = not doc, - icon='help' )}} {% for doc_item in docs %} @@ -21,7 +20,6 @@ {{ SidenavItem(doc_item | title, href = url_for("atst.helpdocs", doc=doc_item), active = active, - subnav = subnav or None )}} {% endfor %} From a660f4117140ca7c772bc7e089c4325708419c3e Mon Sep 17 00:00:00 2001 From: dandds Date: Fri, 20 Dec 2019 14:25:41 -0500 Subject: [PATCH 056/114] Do not catch errors in CI. This removes all error-catching from the test scripts. If unit tests fail, the script will exit immediately. The error catching functionality was not working correctly using the sh shell in Alpine inside the containers, and so CI was allowed to continue after test failures. --- script/include/run_test | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/script/include/run_test b/script/include/run_test index 2da77654..7b696dfe 100644 --- a/script/include/run_test +++ b/script/include/run_test @@ -26,28 +26,16 @@ fi ## Main if [ "${RUN_PYTHON_TESTS}" = "true" ]; then - python_test_status=0 - set +e output_divider "Lint Python files" run_python_lint "${PYTHON_FILES}" - ((python_test_status+=$?)) output_divider "Perform static analysis on Python files" run_python_static_analysis "${PYTHON_FILES}" - ((python_test_status+=$?)) output_divider "Perform type checking on Python files" run_python_typecheck - ((python_test_status+=$?)) output_divider "Run Python unit test suite" run_python_unit_tests "${PYTHON_FILES}" - ((python_test_status+=$?)) - if [ "${python_test_status}" != "0" ]; then - warning "Failed to pass one or more Python checks" - exit ${python_test_status} - fi - - set -e fi if [ "${RUN_JS_TESTS}" = "true" ]; then From ec5c3e0ce07a519a5f7272f3459cdb6f01e78543 Mon Sep 17 00:00:00 2001 From: Rob Gil Date: Fri, 20 Dec 2019 15:10:57 -0500 Subject: [PATCH 057/114] 169163334 - Adds more configuration elements per call with Dan This adds the start of the identity module but also cleans up a bunch of things like the LBs. Originally I was managing the LBs, but k8s manages this for us so I disabled the LBs for now. --- terraform/modules/keyvault/main.tf | 2 +- terraform/modules/lb/main.tf | 5 ++++ terraform/modules/managed_identity/main.tf | 11 +++++++++ terraform/modules/managed_identity/outputs.tf | 0 .../modules/managed_identity/variables.tf | 24 +++++++++++++++++++ terraform/modules/postgres/variables.tf | 6 ++--- terraform/providers/dev/identities.tf | 8 +++++++ terraform/providers/dev/k8s.tf | 22 +++++++++++------ terraform/providers/dev/secrets-tool.log | 0 9 files changed, 66 insertions(+), 12 deletions(-) create mode 100644 terraform/modules/managed_identity/main.tf create mode 100644 terraform/modules/managed_identity/outputs.tf create mode 100644 terraform/modules/managed_identity/variables.tf create mode 100644 terraform/providers/dev/identities.tf create mode 100644 terraform/providers/dev/secrets-tool.log diff --git a/terraform/modules/keyvault/main.tf b/terraform/modules/keyvault/main.tf index d4208e36..5df79ab3 100644 --- a/terraform/modules/keyvault/main.tf +++ b/terraform/modules/keyvault/main.tf @@ -1,7 +1,7 @@ data "azurerm_client_config" "current" {} resource "azurerm_resource_group" "keyvault" { - name = "${var.name}-${var.environment}-rg" + name = "${var.name}-${var.environment}-keyvault" location = var.region } diff --git a/terraform/modules/lb/main.tf b/terraform/modules/lb/main.tf index 1c9acace..4e22e48d 100644 --- a/terraform/modules/lb/main.tf +++ b/terraform/modules/lb/main.tf @@ -19,4 +19,9 @@ resource "azurerm_lb" "lb" { name = "${var.name}-${var.environment}-ip" public_ip_address_id = azurerm_public_ip.lb.id } + + tags = { + owner = var.owner + environment = var.environment + } } diff --git a/terraform/modules/managed_identity/main.tf b/terraform/modules/managed_identity/main.tf new file mode 100644 index 00000000..84e186ce --- /dev/null +++ b/terraform/modules/managed_identity/main.tf @@ -0,0 +1,11 @@ +resource "azurerm_resource_group" "identity" { + name = "${var.name}-${var.environment}-${var.identity}" + location = var.region +} + +resource "azurerm_user_assigned_identity" "identity" { + resource_group_name = azurerm_resource_group.identity.name + location = azurerm_resource_group.identity.location + + name = "${var.name}-${var.environment}-${var.identity}" +} \ No newline at end of file diff --git a/terraform/modules/managed_identity/outputs.tf b/terraform/modules/managed_identity/outputs.tf new file mode 100644 index 00000000..e69de29b diff --git a/terraform/modules/managed_identity/variables.tf b/terraform/modules/managed_identity/variables.tf new file mode 100644 index 00000000..f2a1a758 --- /dev/null +++ b/terraform/modules/managed_identity/variables.tf @@ -0,0 +1,24 @@ +variable "region" { + type = string + description = "Region this module and resources will be created in" +} + +variable "name" { + type = string + description = "Unique name for the services in this module" +} + +variable "environment" { + type = string + description = "Environment these resources reside (prod, dev, staging, etc)" +} + +variable "owner" { + type = string + description = "Owner of the environment and resources created in this module" +} + +variable "identity" { + type = string + description = "Name of the managed identity to create" +} diff --git a/terraform/modules/postgres/variables.tf b/terraform/modules/postgres/variables.tf index 3346ff8f..3dc19af2 100644 --- a/terraform/modules/postgres/variables.tf +++ b/terraform/modules/postgres/variables.tf @@ -54,7 +54,6 @@ variable "storage_mb" { default = "5120" } - variable "storage_backup_retention_days" { type = string description = "Storage backup retention (days)" @@ -76,7 +75,7 @@ variable "storage_auto_grow" { variable "administrator_login" { type = string description = "Administrator login" - default = "sqladmindude" # FIXME - Remove with wrapper using KeyVault + default = "atat_master" # FIXME - Remove with wrapper using KeyVault } variable "administrator_login_password" { @@ -85,11 +84,10 @@ variable "administrator_login_password" { default = "eI0l7yswwtuhHpwzoVjwRKdAcuGNsg" # FIXME - Remove with wrapper using KeyVault } - variable "postgres_version" { type = string description = "Postgres version to use" - default = "11" + default = "10" } variable "ssl_enforcement" { diff --git a/terraform/providers/dev/identities.tf b/terraform/providers/dev/identities.tf new file mode 100644 index 00000000..0def7ce6 --- /dev/null +++ b/terraform/providers/dev/identities.tf @@ -0,0 +1,8 @@ +module "keyvault_reader_identity" { + source = "../../modules/managed_identity" + name = var.name + owner = var.owner + environment = var.environment + region = var.region + identity = "${var.name}-${var.environment}-vault-reader" +} diff --git a/terraform/providers/dev/k8s.tf b/terraform/providers/dev/k8s.tf index 22120c93..4515f35f 100644 --- a/terraform/providers/dev/k8s.tf +++ b/terraform/providers/dev/k8s.tf @@ -9,10 +9,18 @@ module "k8s" { vnet_subnet_id = module.vpc.subnets #FIXME - output from module.vpc.subnets should be map } -module "lb" { - source = "../../modules/lb" - region = var.region - name = var.name - environment = var.environment - owner = var.owner -} +#module "main_lb" { +# source = "../../modules/lb" +# region = var.region +# name = "main-${var.name}" +# environment = var.environment +# owner = var.owner +#} + +#module "auth_lb" { +# source = "../../modules/lb" +# region = var.region +# name = "auth-${var.name}" +# environment = var.environment +# owner = var.owner +#} diff --git a/terraform/providers/dev/secrets-tool.log b/terraform/providers/dev/secrets-tool.log new file mode 100644 index 00000000..e69de29b From 8ec23b54a87306c967fc6bd67f5d88195c184c1b Mon Sep 17 00:00:00 2001 From: dandds Date: Fri, 20 Dec 2019 15:04:58 -0500 Subject: [PATCH 058/114] WIP: k8s config for cloud-zero --- deploy/overlays/cloudzero-dev/envvars.yml | 22 +++++++ deploy/overlays/cloudzero-dev/flex_vol.yml | 62 +++++++++++++++++++ deploy/overlays/cloudzero-dev/json_ports.yml | 12 ++++ .../overlays/cloudzero-dev/kustomization.yaml | 18 ++++++ deploy/overlays/cloudzero-dev/namespace.yml | 4 ++ deploy/overlays/cloudzero-dev/ports.yml | 28 +++++++++ .../overlays/cloudzero-dev/replica_count.yml | 14 +++++ .../overlays/cloudzero-dev/reset-cron-job.yml | 46 ++++++++++++++ 8 files changed, 206 insertions(+) create mode 100644 deploy/overlays/cloudzero-dev/envvars.yml create mode 100644 deploy/overlays/cloudzero-dev/flex_vol.yml create mode 100644 deploy/overlays/cloudzero-dev/json_ports.yml create mode 100644 deploy/overlays/cloudzero-dev/kustomization.yaml create mode 100644 deploy/overlays/cloudzero-dev/namespace.yml create mode 100644 deploy/overlays/cloudzero-dev/ports.yml create mode 100644 deploy/overlays/cloudzero-dev/replica_count.yml create mode 100644 deploy/overlays/cloudzero-dev/reset-cron-job.yml diff --git a/deploy/overlays/cloudzero-dev/envvars.yml b/deploy/overlays/cloudzero-dev/envvars.yml new file mode 100644 index 00000000..179811ed --- /dev/null +++ b/deploy/overlays/cloudzero-dev/envvars.yml @@ -0,0 +1,22 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: atst-worker-envvars +data: + CELERY_DEFAULT_QUEUE: celery-staging + SERVER_NAME: staging.atat.code.mil + FLASK_ENV: staging +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: atst-envvars +data: + ASSETS_URL: https://atat-cdn-staging.azureedge.net/ + CDN_ORIGIN: https://staging.atat.code.mil + CELERY_DEFAULT_QUEUE: celery-staging + FLASK_ENV: staging + STATIC_URL: https://atat-cdn-staging.azureedge.net/static/ + PGHOST: cloudzero-dev-sql.postgres.database.azure.com + REDIS_HOST: cloudzero-dev-redis.redis.cache.windows.net:6380 diff --git a/deploy/overlays/cloudzero-dev/flex_vol.yml b/deploy/overlays/cloudzero-dev/flex_vol.yml new file mode 100644 index 00000000..1da24f7a --- /dev/null +++ b/deploy/overlays/cloudzero-dev/flex_vol.yml @@ -0,0 +1,62 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: atst +spec: + template: + spec: + volumes: + - name: nginx-secret + flexVolume: + options: + keyvaultname: "atat-vault-test" + keyvaultobjectnames: "dhparam4096;cert;cert" + - name: flask-secret + flexVolume: + options: + keyvaultname: "atat-vault-test" + keyvaultobjectnames: "AZURE-STORAGE-KEY;MAIL-PASSWORD;PGPASSWORD;REDIS-PASSWORD;SECRET-KEY" +--- +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: atst-worker +spec: + template: + spec: + volumes: + - name: flask-secret + flexVolume: + options: + keyvaultname: "atat-vault-test" + keyvaultobjectnames: "AZURE-STORAGE-KEY;MAIL-PASSWORD;PGPASSWORD;REDIS-PASSWORD;SECRET-KEY" +--- +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: atst-beat +spec: + template: + spec: + volumes: + - name: flask-secret + flexVolume: + options: + keyvaultname: "atat-vault-test" + keyvaultobjectnames: "AZURE-STORAGE-KEY;MAIL-PASSWORD;PGPASSWORD;REDIS-PASSWORD;SECRET-KEY" +--- +apiVersion: batch/v1beta1 +kind: CronJob +metadata: + name: crls +spec: + jobTemplate: + spec: + template: + spec: + volumes: + - name: flask-secret + flexVolume: + options: + keyvaultname: "atat-vault-test" + keyvaultobjectnames: "AZURE-STORAGE-KEY;MAIL-PASSWORD;PGPASSWORD;REDIS-PASSWORD;SECRET-KEY" diff --git a/deploy/overlays/cloudzero-dev/json_ports.yml b/deploy/overlays/cloudzero-dev/json_ports.yml new file mode 100644 index 00000000..0e8de3b3 --- /dev/null +++ b/deploy/overlays/cloudzero-dev/json_ports.yml @@ -0,0 +1,12 @@ +- op: replace + path: /spec/template/spec/containers/1/ports/0/containerPort + value: 9342 +- op: replace + path: /spec/template/spec/containers/1/ports/1/containerPort + value: 9442 +- op: replace + path: /spec/template/spec/containers/1/ports/2/containerPort + value: 9343 +- op: replace + path: /spec/template/spec/containers/1/ports/3/containerPort + value: 9443 diff --git a/deploy/overlays/cloudzero-dev/kustomization.yaml b/deploy/overlays/cloudzero-dev/kustomization.yaml new file mode 100644 index 00000000..ee6f3a0c --- /dev/null +++ b/deploy/overlays/cloudzero-dev/kustomization.yaml @@ -0,0 +1,18 @@ +namespace: staging +bases: + - ../../azure/ +resources: + - namespace.yml + - reset-cron-job.yml +patchesStrategicMerge: + - replica_count.yml + - ports.yml + - envvars.yml + - flex_vol.yml +patchesJson6902: + - target: + group: extensions + version: v1beta1 + kind: Deployment + name: atst + path: json_ports.yml diff --git a/deploy/overlays/cloudzero-dev/namespace.yml b/deploy/overlays/cloudzero-dev/namespace.yml new file mode 100644 index 00000000..ee38adfb --- /dev/null +++ b/deploy/overlays/cloudzero-dev/namespace.yml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: staging diff --git a/deploy/overlays/cloudzero-dev/ports.yml b/deploy/overlays/cloudzero-dev/ports.yml new file mode 100644 index 00000000..8f4ff72c --- /dev/null +++ b/deploy/overlays/cloudzero-dev/ports.yml @@ -0,0 +1,28 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: atst-main +spec: + loadBalancerIP: "" + ports: + - port: 80 + targetPort: 9342 + name: http + - port: 443 + targetPort: 9442 + name: https +--- +apiVersion: v1 +kind: Service +metadata: + name: atst-auth +spec: + loadBalancerIP: "" + ports: + - port: 80 + targetPort: 9343 + name: http + - port: 443 + targetPort: 9443 + name: https diff --git a/deploy/overlays/cloudzero-dev/replica_count.yml b/deploy/overlays/cloudzero-dev/replica_count.yml new file mode 100644 index 00000000..272286f7 --- /dev/null +++ b/deploy/overlays/cloudzero-dev/replica_count.yml @@ -0,0 +1,14 @@ +--- +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: atst +spec: + replicas: 2 +--- +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: atst-worker +spec: + replicas: 1 diff --git a/deploy/overlays/cloudzero-dev/reset-cron-job.yml b/deploy/overlays/cloudzero-dev/reset-cron-job.yml new file mode 100644 index 00000000..b4792e5d --- /dev/null +++ b/deploy/overlays/cloudzero-dev/reset-cron-job.yml @@ -0,0 +1,46 @@ +apiVersion: batch/v1beta1 +kind: CronJob +metadata: + name: reset-db + namespace: atat +spec: + schedule: "0 4 * * *" + concurrencyPolicy: Replace + successfulJobsHistoryLimit: 1 + jobTemplate: + spec: + template: + metadata: + labels: + app: atst + role: reset-db + aadpodidbinding: atat-kv-id-binding + spec: + restartPolicy: OnFailure + containers: + - name: reset + image: $CONTAINER_IMAGE + command: [ + "/bin/sh", "-c" + ] + args: [ + "/opt/atat/atst/.venv/bin/python", + "/opt/atat/atst/script/reset_database.py" + ] + envFrom: + - configMapRef: + name: atst-worker-envvars + volumeMounts: + - name: flask-secret + mountPath: "/config" + volumes: + - name: flask-secret + flexVolume: + driver: "azure/kv" + options: + usepodidentity: "true" + keyvaultname: "atat-vault-test" + keyvaultobjectnames: "staging-AZURE-STORAGE-KEY;staging-MAIL-PASSWORD;staging-PGPASSWORD;staging-REDIS-PASSWORD;staging-SECRET-KEY" + keyvaultobjectaliases: "AZURE_STORAGE_KEY;MAIL_PASSWORD;PGPASSWORD;REDIS_PASSWORD;SECRET_KEY" + keyvaultobjecttypes: "secret;secret;secret;secret;key" + tenantid: $TENANT_ID From b98bc5953f1841a295d8946cae7bf176a07eee9e Mon Sep 17 00:00:00 2001 From: Rob Gil Date: Mon, 23 Dec 2019 18:13:43 -0500 Subject: [PATCH 059/114] 169163334 - Adds public ips to k8s nodes for internet access Temporary fix. This should be replaced with a NAT GW (which I need MSFT to enable or fix the registry registration) --- terraform/modules/k8s/main.tf | 11 ++++++----- terraform/providers/dev/variables.tf | 5 +++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/terraform/modules/k8s/main.tf b/terraform/modules/k8s/main.tf index 93e84141..862966c8 100644 --- a/terraform/modules/k8s/main.tf +++ b/terraform/modules/k8s/main.tf @@ -15,11 +15,12 @@ resource "azurerm_kubernetes_cluster" "k8s" { } default_node_pool { - name = "default" - vm_size = "Standard_D1_v2" - os_disk_size_gb = 30 - vnet_subnet_id = var.vnet_subnet_id - node_count = 1 + name = "default" + vm_size = "Standard_D1_v2" + os_disk_size_gb = 30 + vnet_subnet_id = var.vnet_subnet_id + node_count = 1 + enable_node_public_ip = true # Nodes need a public IP for external resources. FIXME: Switch to NAT Gateway if its available in our subscription } lifecycle { diff --git a/terraform/providers/dev/variables.tf b/terraform/providers/dev/variables.tf index 3de51546..7fcb6ee0 100644 --- a/terraform/providers/dev/variables.tf +++ b/terraform/providers/dev/variables.tf @@ -47,13 +47,14 @@ variable "route_tables" { type = map default = { public = "Internet" - private = "VnetLocal" + private = "Internet" + #private = "VnetLocal" } } variable "dns_servers" { type = list - default = ["10.1.2.4", "10.1.2.5"] + default = [] } variable "k8s_node_size" { From 5eeb5f976af29a0a447445ccdbc22258d1313473 Mon Sep 17 00:00:00 2001 From: Rob Gil Date: Thu, 26 Dec 2019 09:10:48 -0500 Subject: [PATCH 060/114] 169163334 - Adds autoscaling to k8s This adds node autoscaling the k8s. Pod autoscaling needs to be configured in the kubectl config. --- terraform/modules/k8s/main.tf | 3 +++ terraform/modules/k8s/variables.tf | 19 +++++++++++++++++++ terraform/providers/dev/k8s.tf | 19 +++++++++++-------- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/terraform/modules/k8s/main.tf b/terraform/modules/k8s/main.tf index 862966c8..82ad1755 100644 --- a/terraform/modules/k8s/main.tf +++ b/terraform/modules/k8s/main.tf @@ -21,6 +21,9 @@ resource "azurerm_kubernetes_cluster" "k8s" { vnet_subnet_id = var.vnet_subnet_id node_count = 1 enable_node_public_ip = true # Nodes need a public IP for external resources. FIXME: Switch to NAT Gateway if its available in our subscription + enable_auto_scaling = var.enable_auto_scaling + max_count = var.max_count # FIXME: if auto_scaling disabled, set to 0 + min_count = var.min_count # FIXME: if auto_scaling disabled, set to 0 } lifecycle { diff --git a/terraform/modules/k8s/variables.tf b/terraform/modules/k8s/variables.tf index 7a3663ce..28677ec2 100644 --- a/terraform/modules/k8s/variables.tf +++ b/terraform/modules/k8s/variables.tf @@ -33,3 +33,22 @@ variable "vnet_subnet_id" { description = "Subnet to use for the default k8s pool" type = string } + +variable "enable_auto_scaling" { + default = false + type = string + description = "Enable or disable autoscaling (Default: false)" +} + +variable "max_count" { + default = 1 + type = string + description = "Maximum number of nodes to use in autoscaling. This requires `enable_auto_scaling` to be set to true" + +} + +variable "min_count" { + default = 1 + type = string + description = "Minimum number of nodes to use in autoscaling. This requires `enable_auto_scaling` to be set to true" +} diff --git a/terraform/providers/dev/k8s.tf b/terraform/providers/dev/k8s.tf index 4515f35f..8ea9696b 100644 --- a/terraform/providers/dev/k8s.tf +++ b/terraform/providers/dev/k8s.tf @@ -1,12 +1,15 @@ module "k8s" { - source = "../../modules/k8s" - region = var.region - name = var.name - environment = var.environment - owner = var.owner - k8s_dns_prefix = var.k8s_dns_prefix - k8s_node_size = var.k8s_node_size - vnet_subnet_id = module.vpc.subnets #FIXME - output from module.vpc.subnets should be map + source = "../../modules/k8s" + region = var.region + name = var.name + environment = var.environment + owner = var.owner + k8s_dns_prefix = var.k8s_dns_prefix + k8s_node_size = var.k8s_node_size + vnet_subnet_id = module.vpc.subnets #FIXME - output from module.vpc.subnets should be map + enable_auto_scaling = true + max_count = 5 + min_count = 2 } #module "main_lb" { From 4532b64a6500816a60dbe09dd98ce21759ede678 Mon Sep 17 00:00:00 2001 From: graham-dds Date: Thu, 19 Dec 2019 10:57:09 -0500 Subject: [PATCH 061/114] Remove "get help" link from footer --- styles/components/_footer.scss | 17 ++--------------- templates/footer.html | 8 +------- translations.yaml | 1 - 3 files changed, 3 insertions(+), 23 deletions(-) diff --git a/styles/components/_footer.scss b/styles/components/_footer.scss index 2b7fc552..bb248e4d 100644 --- a/styles/components/_footer.scss +++ b/styles/components/_footer.scss @@ -3,8 +3,7 @@ background-color: $color-white; border-top: 1px solid $color-gray-lightest; display: flex; - flex-direction: row; - justify-content: space-between; + flex-direction: row-reverse; align-items: center; padding: $gap * 1.5; position: fixed; @@ -15,19 +14,7 @@ color: $color-gray-dark; font-size: 1.5rem; - &__info { - flex-grow: 1; + &__login { padding-left: 0.8rem; - - &__link { - margin: (-$gap * 2) (-$gap); - font-weight: normal; - - .icon--footer { - @include icon-size(16); - - margin: 0rem 0.8rem 0rem 0rem; - } - } } } diff --git a/templates/footer.html b/templates/footer.html index 4e07c0a7..be67bf8b 100644 --- a/templates/footer.html +++ b/templates/footer.html @@ -1,14 +1,8 @@ {% from "components/icon.html" import Icon %}