@@ -44,6 +44,16 @@ class InitializationFilterE2ETest {
4444
4545 private MockHttpServletResponse response ;
4646
47+ /**
48+ * Snapshot of {@link Context#getRuntimeProperties()} taken before each test so it can be restored
49+ * in {@link #cleanup()}. Without this restore step the empty {@code Properties} instance left
50+ * behind by {@code setup()} leaks into the next test class that triggers a Spring
51+ * {@code ApplicationContext} load, causing {@code SchedulerConfig} / {@code JobRunrConfig} to build
52+ * a {@code DataSource} with no URL or credentials and H2 to reject the connection with "Wrong user
53+ * name or password [28000-232]" (TRUNK-6637).
54+ */
55+ private Properties savedRuntimeProperties ;
56+
4757 /**
4858 * Testable subclass that overrides renderTemplate to capture which template was rendered instead of
4959 * actually invoking Velocity.
@@ -65,17 +75,24 @@ void setup() {
6575 filter .wizardModel = new InitializationWizardModel ();
6676 request = new MockHttpServletRequest ();
6777 response = new MockHttpServletResponse ();
68- // Clear runtime properties to avoid state leaking from other test classes
78+ // Save existing runtime properties, then install an empty Properties so
79+ // this test can assert behaviour when runtime properties are absent.
80+ // The saved value is restored in cleanup() to prevent the empty instance
81+ // from leaking into subsequent tests (TRUNK-6637).
82+ savedRuntimeProperties = Context .getRuntimeProperties ();
6983 Context .setRuntimeProperties (new Properties ());
7084 }
7185
7286 @ AfterEach
7387 void cleanup () {
7488 InitializationFilter .setInstallationStarted (false );
89+ // Restore the runtime properties that were in place before this test ran.
90+ // This is essential: an empty Properties leaks into any subsequent test
91+ // that loads a Spring ApplicationContext, breaking SchedulerConfig /
92+ // JobRunrConfig DataSource construction (TRUNK-6637).
93+ Context .setRuntimeProperties (savedRuntimeProperties );
7594 }
7695
77- // ========== Language Selection (chooselang.vm) ==========
78-
7996 @ Test
8097 void chooseLangPage_shouldRenderInstallMethodPageOnPost () throws Exception {
8198 request .setParameter ("page" , "chooselang.vm" );
@@ -96,8 +113,6 @@ void chooseLangPage_shouldStoreLocaleInSession() throws Exception {
96113 assertEquals ("fr" , request .getSession ().getAttribute ("locale" ));
97114 }
98115
99- // ========== Install Method Selection (installmethod.vm) ==========
100-
101116 @ Test
102117 void installMethodPage_shouldNavigateToSimpleSetupWhenSimpleSelected () throws Exception {
103118 request .setParameter ("page" , "installmethod.vm" );
@@ -144,8 +159,6 @@ void installMethodPage_shouldGoBackToChooseLangWhenBackClicked() throws Exceptio
144159 assertEquals ("chooselang.vm" , filter .lastRenderedTemplate );
145160 }
146161
147- // ========== Simple Setup (simplesetup.vm) ==========
148-
149162 @ Test
150163 void simpleSetup_shouldGoBackToInstallMethodWhenBackClicked () throws Exception {
151164 request .setParameter ("page" , "simplesetup.vm" );
@@ -197,8 +210,6 @@ void simpleSetup_shouldSetPostgresqlDefaultsWhenPostgresqlSelected() throws Exce
197210 assertEquals (InitializationWizardModel .DEFAULT_POSTGRESQL_CONNECTION , filter .wizardModel .databaseConnection );
198211 }
199212
200- // ========== Database Setup - Advanced (databasesetup.vm) ==========
201-
202213 @ ParameterizedTest
203214 @ CsvSource ({ "advanced, databasesetup.vm, installmethod.vm" , "testing, databasesetup.vm, remotedetails.vm" ,
204215 "simple, wizardcomplete.vm, simplesetup.vm" , "advanced, wizardcomplete.vm, implementationidsetup.vm" })
@@ -301,8 +312,6 @@ void databaseSetup_shouldSetStepNumber3ForTestingInstall() throws Exception {
301312 assertEquals (3 , filter .wizardModel .currentStepNumber );
302313 }
303314
304- // ========== Database Tables and User (databasetablesanduser.vm) ==========
305-
306315 @ Test
307316 void databaseTablesAndUser_shouldGoBackToDatabaseSetup () throws Exception {
308317 request .setParameter ("page" , "databasetablesanduser.vm" );
@@ -402,8 +411,6 @@ void databaseTablesAndUser_shouldNavigateToWizardCompleteForTestingInstall() thr
402411 assertEquals ("wizardcomplete.vm" , filter .lastRenderedTemplate );
403412 }
404413
405- // ========== Other Runtime Properties (otherruntimeproperties.vm) ==========
406-
407414 @ Test
408415 void otherRuntimeProps_shouldGoBackToDatabaseTablesAndUser () throws Exception {
409416 request .setParameter ("page" , "otherruntimeproperties.vm" );
@@ -464,8 +471,6 @@ void otherRuntimeProps_shouldSkipAdminSetupWhenNotCreatingTables() throws Except
464471 assertEquals ("implementationidsetup.vm" , filter .lastRenderedTemplate );
465472 }
466473
467- // ========== Admin User Setup (adminusersetup.vm) ==========
468-
469474 @ Test
470475 void adminUserSetup_shouldGoBackToOtherRuntimeProps () throws Exception {
471476 request .setParameter ("page" , "adminusersetup.vm" );
@@ -503,8 +508,6 @@ void adminUserSetup_shouldNavigateToImplementationIdSetupOnSuccess() throws Exce
503508 assertEquals ("implementationidsetup.vm" , filter .lastRenderedTemplate );
504509 }
505510
506- // ========== Implementation ID Setup (implementationidsetup.vm) ==========
507-
508511 @ Test
509512 void implementationIdSetup_shouldGoBackToAdminUserSetupWhenCreatingTables () throws Exception {
510513 filter .wizardModel .createTables = true ;
@@ -584,8 +587,6 @@ void implementationIdSetup_shouldAcceptEmptyImplementationId() throws Exception
584587 assertEquals ("wizardcomplete.vm" , filter .lastRenderedTemplate );
585588 }
586589
587- // ========== Wizard Complete (wizardcomplete.vm) ==========
588-
589590 @ Test
590591 void wizardComplete_shouldBuildCorrectTaskListForAdvancedWithNewDatabase () throws Exception {
591592 filter .wizardModel .installMethod = "advanced" ;
@@ -651,8 +652,6 @@ void wizardComplete_shouldRenderProgressPage() throws Exception {
651652 assertEquals ("progress.vm" , filter .lastRenderedTemplate );
652653 }
653654
654- // ========== Installation Already Started ==========
655-
656655 @ Test
657656 void doPost_shouldRenderProgressWhenInstallationAlreadyStarted () throws Exception {
658657 InitializationFilter .setInstallationStarted (true );
@@ -664,17 +663,13 @@ void doPost_shouldRenderProgressWhenInstallationAlreadyStarted() throws Exceptio
664663 assertEquals ("progress.vm" , filter .lastRenderedTemplate );
665664 }
666665
667- // ========== Full Flow: Advanced Installation Path ==========
668-
669666 @ Test
670667 void fullAdvancedFlow_shouldNavigateCorrectlyThroughAllSteps () throws Exception {
671- // Step 1: Choose Language -> Install Method
672668 request .setParameter ("page" , "chooselang.vm" );
673669 request .setParameter ("locale" , "en" );
674670 filter .doPost (request , response );
675671 assertEquals ("installmethod.vm" , filter .lastRenderedTemplate );
676672
677- // Step 2: Install Method (advanced) -> Database Setup
678673 resetRequest ();
679674 request .setParameter ("page" , "installmethod.vm" );
680675 request .setParameter ("install_method" , "advanced" );
@@ -684,7 +679,6 @@ void fullAdvancedFlow_shouldNavigateCorrectlyThroughAllSteps() throws Exception
684679 assertEquals (1 , filter .wizardModel .currentStepNumber );
685680 assertEquals (5 , filter .wizardModel .numberOfSteps );
686681
687- // Step 3: Database Setup -> Database Tables and User
688682 resetRequest ();
689683 request .setParameter ("page" , "databasesetup.vm" );
690684 request .setParameter ("database_connection" , "jdbc:h2:mem:test" );
@@ -695,7 +689,6 @@ void fullAdvancedFlow_shouldNavigateCorrectlyThroughAllSteps() throws Exception
695689 filter .doPost (request , response );
696690 assertEquals ("databasetablesanduser.vm" , filter .lastRenderedTemplate );
697691
698- // Step 4: Database Tables and User -> Other Runtime Props
699692 resetRequest ();
700693 request .setParameter ("page" , "databasetablesanduser.vm" );
701694 request .setParameter ("current_database_user" , "yes" );
@@ -705,7 +698,6 @@ void fullAdvancedFlow_shouldNavigateCorrectlyThroughAllSteps() throws Exception
705698 filter .doPost (request , response );
706699 assertEquals ("otherruntimeproperties.vm" , filter .lastRenderedTemplate );
707700
708- // Step 5: Other Runtime Props -> Admin User Setup
709701 resetRequest ();
710702 filter .wizardModel .createTables = true ;
711703 request .setParameter ("page" , "otherruntimeproperties.vm" );
@@ -715,7 +707,6 @@ void fullAdvancedFlow_shouldNavigateCorrectlyThroughAllSteps() throws Exception
715707 filter .doPost (request , response );
716708 assertEquals ("adminusersetup.vm" , filter .lastRenderedTemplate );
717709
718- // Step 6: Admin User Setup -> Implementation ID
719710 resetRequest ();
720711 request .setParameter ("page" , "adminusersetup.vm" );
721712 request .setParameter ("new_admin_password" , "Admin123" );
@@ -724,7 +715,6 @@ void fullAdvancedFlow_shouldNavigateCorrectlyThroughAllSteps() throws Exception
724715 filter .doPost (request , response );
725716 assertEquals ("implementationidsetup.vm" , filter .lastRenderedTemplate );
726717
727- // Step 7: Implementation ID -> Wizard Complete
728718 resetRequest ();
729719 request .setParameter ("page" , "implementationidsetup.vm" );
730720 request .setParameter ("implementation_name" , "" );
@@ -735,19 +725,15 @@ void fullAdvancedFlow_shouldNavigateCorrectlyThroughAllSteps() throws Exception
735725 filter .doPost (request , response );
736726 assertEquals ("wizardcomplete.vm" , filter .lastRenderedTemplate );
737727
738- // Step 8: Wizard Complete -> Progress (starts installation)
739728 resetRequest ();
740729 request .setParameter ("page" , "wizardcomplete.vm" );
741730 clearErrors ();
742731 filter .doPost (request , response );
743732 assertEquals ("progress.vm" , filter .lastRenderedTemplate );
744733 }
745734
746- // ========== Full Flow: Advanced with Back Navigation ==========
747-
748735 @ Test
749736 void fullAdvancedFlow_shouldSupportBackNavigationThroughSteps () throws Exception {
750- // Navigate forward: chooselang -> installmethod -> databasesetup
751737 request .setParameter ("page" , "chooselang.vm" );
752738 filter .doPost (request , response );
753739
@@ -757,15 +743,13 @@ void fullAdvancedFlow_shouldSupportBackNavigationThroughSteps() throws Exception
757743 clearErrors ();
758744 filter .doPost (request , response );
759745
760- // Now go back from databasesetup -> installmethod
761746 resetRequest ();
762747 request .setParameter ("page" , "databasesetup.vm" );
763748 request .setParameter ("back" , "Back" );
764749 clearErrors ();
765750 filter .doPost (request , response );
766751 assertEquals ("installmethod.vm" , filter .lastRenderedTemplate );
767752
768- // Go back from installmethod -> chooselang
769753 resetRequest ();
770754 request .setParameter ("page" , "installmethod.vm" );
771755 request .setParameter ("back" , "Back" );
@@ -774,8 +758,6 @@ void fullAdvancedFlow_shouldSupportBackNavigationThroughSteps() throws Exception
774758 assertEquals ("chooselang.vm" , filter .lastRenderedTemplate );
775759 }
776760
777- // ========== Full Flow: Advanced with Existing DB (no table creation) ==========
778-
779761 @ Test
780762 void advancedExistingDb_shouldSkipAdminSetupWhenNotCreatingTables () throws Exception {
781763 filter .wizardModel .installMethod = "advanced" ;
@@ -791,17 +773,13 @@ void advancedExistingDb_shouldSkipAdminSetupWhenNotCreatingTables() throws Excep
791773 assertEquals ("implementationidsetup.vm" , filter .lastRenderedTemplate );
792774 }
793775
794- // ========== Wizard Model State Preservation ==========
795-
796776 @ Test
797777 void wizardModel_shouldPreserveStateAcrossSteps () throws Exception {
798- // Step 1: Install method
799778 request .setParameter ("page" , "installmethod.vm" );
800779 request .setParameter ("install_method" , "advanced" );
801780 filter .doPost (request , response );
802781 assertEquals ("advanced" , filter .wizardModel .installMethod );
803782
804- // Step 2: Database setup
805783 resetRequest ();
806784 request .setParameter ("page" , "databasesetup.vm" );
807785 request .setParameter ("database_connection" , "jdbc:h2:mem:test" );
@@ -811,15 +789,12 @@ void wizardModel_shouldPreserveStateAcrossSteps() throws Exception {
811789 clearErrors ();
812790 filter .doPost (request , response );
813791
814- // Verify state from both steps
815792 assertEquals ("advanced" , filter .wizardModel .installMethod );
816793 assertEquals ("jdbc:h2:mem:test" , filter .wizardModel .databaseConnection );
817794 assertEquals ("my_openmrs" , filter .wizardModel .databaseName );
818795 assertTrue (filter .wizardModel .hasCurrentOpenmrsDatabase );
819796 }
820797
821- // ========== goBack via image click (back.x / back.y) ==========
822-
823798 @ Test
824799 void backNavigation_shouldWorkWithImageClickCoordinates () throws Exception {
825800 request .setParameter ("page" , "installmethod.vm" );
@@ -831,8 +806,6 @@ void backNavigation_shouldWorkWithImageClickCoordinates() throws Exception {
831806 assertEquals ("chooselang.vm" , filter .lastRenderedTemplate );
832807 }
833808
834- // ========== Database Tables and User - Create User Validation ==========
835-
836809 @ Test
837810 void databaseTablesAndUser_shouldRequireCreateUserUsernameWhenCreatingNewUser () throws Exception {
838811 filter .wizardModel .hasCurrentOpenmrsDatabase = true ;
@@ -859,8 +832,6 @@ void databaseTablesAndUser_shouldRequireCreateUserPasswordWhenCreatingNewUser()
859832 assertTrue (getErrors ().containsKey ("install.error.dbUserPswd" ));
860833 }
861834
862- // ========== Database Setup - Validation for Existing DB ==========
863-
864835 @ Test
865836 void databaseSetup_shouldRequireCurrentDatabaseNameWhenExistingSelected () throws Exception {
866837 request .setParameter ("page" , "databasesetup.vm" );
@@ -904,26 +875,17 @@ void databaseSetup_shouldRequireCreatePasswordWhenCreatingNewDb() throws Excepti
904875 assertTrue (getErrors ().containsKey ("install.error.dbUserPswd" ));
905876 }
906877
907- /**
908- * Access the errors map from the filter via reflection since it is protected in StartupFilter.
909- */
910878 @ SuppressWarnings ("unchecked" )
911879 private Map <String , Object []> getErrors () throws Exception {
912880 Field errorsField = StartupFilter .class .getDeclaredField ("errors" );
913881 errorsField .setAccessible (true );
914882 return (Map <String , Object []>) errorsField .get (filter );
915883 }
916884
917- /**
918- * Clear the errors map between steps in multi-step flow tests.
919- */
920885 private void clearErrors () throws Exception {
921886 getErrors ().clear ();
922887 }
923888
924- /**
925- * Reset request and response objects for the next step in a multi-step test.
926- */
927889 private void resetRequest () {
928890 request = new MockHttpServletRequest ();
929891 response = new MockHttpServletResponse ();
0 commit comments