diff --git a/Dockerfile b/Dockerfile index 1c701fdb..e843d3ad 100644 --- a/Dockerfile +++ b/Dockerfile @@ -43,6 +43,7 @@ ENV SSP_PATH /data/vendor/simplesamlphp/simplesamlphp # Copy modules into simplesamlphp COPY modules/ $SSP_PATH/modules +COPY behat.yml . # Copy in SSP override files RUN mv $SSP_PATH/www/index.php $SSP_PATH/www/ssp-index.php diff --git a/behat.yml b/behat.yml new file mode 100644 index 00000000..9c205e35 --- /dev/null +++ b/behat.yml @@ -0,0 +1,17 @@ +default: + suites: + dictionary_features: + paths: [ '%paths.base%//features//dictionary-overrides.feature' ] + contexts: [ 'FeatureContext' ] + expiry_features: + paths: [ '%paths.base%//features//expirychecker.feature' ] + contexts: [ 'ExpiryContext' ] + material_features: + paths: [ '%paths.base%//features//material.feature' ] + contexts: [ 'FeatureContext' ] + mfa_features: + paths: [ '%paths.base%//features//mfa.feature' ] + contexts: [ 'FeatureContext' ] + profilereview_features: + paths: [ '%paths.base%//features//profilereview.feature' ] + contexts: [ 'FeatureContext' ] diff --git a/development/idp-local/config/authsources.php b/development/idp-local/config/authsources.php index 3424be4b..c8b786ee 100644 --- a/development/idp-local/config/authsources.php +++ b/development/idp-local/config/authsources.php @@ -24,7 +24,7 @@ gmdate('YmdHis\Z', strtotime('+6 months')), // Distant future ], ], - 'near_future:a' => [ + 'near_future:b' => [ 'eduPersonPrincipalName' => ['NEAR_FUTURE@ssp-idp1.local'], 'sn' => ['Future'], 'givenName' => ['Near'], @@ -35,7 +35,7 @@ gmdate('YmdHis\Z', strtotime('+1 day')), // Very soon ], ], - 'already_past:a' => [ + 'already_past:c' => [ 'eduPersonPrincipalName' => ['ALREADY_PAST@ssp-idp1.local'], 'sn' => ['Past'], 'givenName' => ['Already'], @@ -46,5 +46,24 @@ gmdate('YmdHis\Z', strtotime('-1 day')), // In the past ], ], + 'missing_exp:d' => [ + 'eduPersonPrincipalName' => ['MISSING_EXP@ssp-idp-1.local'], + 'sn' => ['Expiration'], + 'givenName' => ['Missing'], + 'mail' => ['missing_exp@example.com'], + 'employeeNumber' => ['44444'], + 'cn' => ['MISSING_EXP'], + ], + 'invalid_exp:e' => [ + 'eduPersonPrincipalName' => ['INVALID_EXP@ssp-idp-1.local'], + 'sn' => ['Expiration'], + 'givenName' => ['Invalid'], + 'mail' => ['invalid_exp@example.com'], + 'employeeNumber' => ['55555'], + 'cn' => ['INVALID_EXP'], + 'schacExpiryDate' => [ + 'invalid' + ], + ], ], ]; diff --git a/docker-compose.yml b/docker-compose.yml index 2f0b2267..084d4391 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -49,6 +49,7 @@ services: - ./dockerbuild/run-tests.sh:/data/run-tests.sh - ./dockerbuild/apply-dictionaries-overrides.php:/data/apply-dictionaries-overrides.php - ./features:/data/features + - ./behat.yml:/data/behat.yml - ./tests:/data/tests - ./modules/expirychecker:/data/vendor/simplesamlphp/simplesamlphp/modules/expirychecker command: ["/data/run-tests.sh"] diff --git a/dockerbuild/run-integration-tests.sh b/dockerbuild/run-integration-tests.sh index d57f8b27..c46b02c5 100755 --- a/dockerbuild/run-integration-tests.sh +++ b/dockerbuild/run-integration-tests.sh @@ -11,8 +11,5 @@ whenavail "ssp-idp1.local" 80 10 echo IDP 1 ready whenavail "ssp-sp1.local" 80 10 echo SP 1 ready ./vendor/bin/behat \ - --append-snippets \ - --snippets-for=FeatureContext \ --no-interaction \ - --stop-on-failure #\ - #--strict + --stop-on-failure diff --git a/features/bootstrap/ExpiryContext.php b/features/bootstrap/ExpiryContext.php index 5017ba12..68bc5d79 100644 --- a/features/bootstrap/ExpiryContext.php +++ b/features/bootstrap/ExpiryContext.php @@ -1,8 +1,4 @@ session = new Session($driver); - $this->session->start(); - } - + + /** * Assert that the given page has a form that contains the given text. * @@ -58,7 +41,7 @@ protected function assertFormContains($text, $page) $page->getHtml() )); } - + /** * Assert that the given page does NOT have a form that contains the given * text. @@ -80,7 +63,7 @@ protected function assertFormNotContains($text, $page) } } } - + /** * Get the login button from the given page. * @@ -117,11 +100,9 @@ public function iProvideCredentialsThatWillExpireInTheDistantFuture() */ public function iLogin() { - $this->session->visit('http://sp/module.php/core/authenticate.php?as=ssp-hub-idp'); - $page = $this->session->getPage(); - $page->fillField('username', $this->username); - $page->fillField('password', $this->password); - $this->submitLoginForm($page); + $this->fillField('username', $this->username); + $this->fillField('password', $this->password); + $this->pressButton('Login'); } /** @@ -129,8 +110,7 @@ public function iLogin() */ public function iShouldEndUpAtMyIntendedDestination() { - $page = $this->session->getPage(); - Assert::assertContains('Your attributes', $page->getHtml()); + $this->assertPageBodyContainsText('Your attributes'); } /** @@ -151,7 +131,7 @@ public function iShouldSeeAWarningThatMyPasswordWillExpireSoon() $page = $this->session->getPage(); Assert::assertContains('will expire', $page->getHtml()); } - + /** * Submit the login form, including the secondary page's form (if * simpleSAMLphp shows another page because JavaScript isn't supported). @@ -162,13 +142,13 @@ protected function submitLoginForm($page) { $loginButton = $this->getLoginButton($page); $loginButton->click(); - + // SimpleSAMLphp 1.15 markup for secondary page: $postLoginSubmitButton = $page->findButton('postLoginSubmitButton'); if ($postLoginSubmitButton instanceof NodeElement) { $postLoginSubmitButton->click(); } else { - + // SimpleSAMLphp 1.14 markup for secondary page: $body = $page->find('css', 'body'); if ($body instanceof NodeElement) { diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index bc5d23ca..603cfc9e 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -14,10 +14,10 @@ class FeatureContext extends MinkContext private const HUB_BAD_AUTH_SOURCE_URL = 'http://ssp-hub.local/module.php/core/authenticate.php?as=wrong'; private const HUB_DISCO_URL = 'http://ssp-hub.local/module.php/core/authenticate.php?as=hub-discovery'; private const HUB_HOME_URL = 'http://ssp-hub.local'; - private const SP1_LOGIN_PAGE = 'http://ssp-sp1.local/module.php/core/authenticate.php?as=ssp-hub'; + protected const SP1_LOGIN_PAGE = 'http://ssp-sp1.local/module.php/core/authenticate.php?as=ssp-hub'; /** @var Session */ - private $session; + protected $session; public function __construct() { @@ -161,7 +161,7 @@ public function iShouldSeeAPageIndicatingThatISuccessfullyLoggedIn() $this->assertPageBodyContainsText('Your attributes'); } - private function assertPageBodyContainsText(string $expectedText) + protected function assertPageBodyContainsText(string $expectedText) { $page = $this->session->getPage(); $body = $page->find('css', 'body'); @@ -169,11 +169,11 @@ private function assertPageBodyContainsText(string $expectedText) } /** - * @When I log in as a user who's password is about to expire + * @When I log in as a user whose password is about to expire */ public function iLogInAsAUserWhosPasswordIsAboutToExpire() { - $this->logInAs('near_future', 'a'); + $this->logInAs('near_future', 'b'); } /** @@ -185,11 +185,11 @@ public function iShouldSeeAPageWarningMeThatMyPasswordIsAboutToExpire() } /** - * @When I log in as a user who's password has expired + * @When I log in as a user whose password has expired */ public function iLogInAsAUserWhosPasswordHasExpired() { - $this->logInAs('already_past', 'a'); + $this->logInAs('already_past', 'c'); } /** diff --git a/features/expirychecker.feature b/features/expirychecker.feature index 80a9d51c..503cb391 100644 --- a/features/expirychecker.feature +++ b/features/expirychecker.feature @@ -8,9 +8,38 @@ Feature: Expiry Checker module Then I should see a page indicating that I successfully logged in Scenario: Password is about to expire - When I log in as a user who's password is about to expire + When I log in as a user whose password is about to expire Then I should see a page warning me that my password is about to expire Scenario: Password has expired - When I log in as a user who's password has expired + When I log in as a user whose password has expired Then I should see a page telling me that my password has expired + + Scenario: Password will expire in the distant future + Given I provide credentials that will expire in the distant future + When I login + Then I should end up at my intended destination + + Scenario: Password will expire tomorrow + Given I provide credentials that will expire very soon + When I login + Then I should see a warning that my password will expire soon + And there should be a way to go change my password now + And there should be a way to continue without changing my password + + Scenario: Password has expired + Given I provide credentials that have expired + When I login + Then I should see a message that my password has expired + And there should be a way to go change my password now + But there should NOT be a way to continue without changing my password + + Scenario: Reject missing expiration date + Given I provide credentials that have no password expiration date + When I login + Then I should see an error message + + Scenario: Reject invalid expiration date + Given I provide credentials that have an invalid password expiration date + When I login + Then I should see an error message