| @@ -21,6 +21,7 @@ The `tests/` IIS application assumes the repository layout keeps `tests/`, `publ | |||||
| | Create | `tests/sync-webconfigs.vbs` | Utility script to mirror `tests/web.config` into nested test folders | | | Create | `tests/sync-webconfigs.vbs` | Utility script to mirror `tests/web.config` into nested test folders | | ||||
| | Create | `tests/bootstrap.asp` | Shared test bootstrap and runtime reset helpers | | | Create | `tests/bootstrap.asp` | Shared test bootstrap and runtime reset helpers | | ||||
| | Create | `tests/PlainRunnerTheme.asp` | Local runner theme that removes CDN dependence from the test UI | | | Create | `tests/PlainRunnerTheme.asp` | Local runner theme that removes CDN dependence from the test UI | | ||||
| | Create | `tests/support/HttpCaptureHelpers.asp` | Shared HTTP capture helpers for rendered-page assertions | | |||||
| | Create | `tests/test-manifest.asp` | Single source of truth for registered test pages | | | Create | `tests/test-manifest.asp` | Single source of truth for registered test pages | | ||||
| | Create | `tests/run-all.asp` | Browser runner that aggregates all test pages | | | Create | `tests/run-all.asp` | Browser runner that aggregates all test pages | | ||||
| | Vendor | `tests/aspunit/Lib/*` | Upstream aspunit framework files | | | Vendor | `tests/aspunit/Lib/*` | Upstream aspunit framework files | | ||||
| @@ -29,6 +30,9 @@ The `tests/` IIS application assumes the repository layout keeps `tests/`, `publ | |||||
| | Create | `tests/unit/TestControllerRegistry.asp` | Controller whitelist/format unit tests | | | Create | `tests/unit/TestControllerRegistry.asp` | Controller whitelist/format unit tests | | ||||
| | Create | `tests/component/TestHomeController.asp` | Controlled component-level controller test | | | Create | `tests/component/TestHomeController.asp` | Controlled component-level controller test | | ||||
| | Create | `tests/integration/TestMvcDispatch.asp` | Narrow router/dispatch smoke test | | | Create | `tests/integration/TestMvcDispatch.asp` | Narrow router/dispatch smoke test | | ||||
| | Create | `tests/integration/TestRoutes.asp` | Route-helper/config integration coverage | | |||||
| | Create | `tests/integration/TestConfigSettings.asp` | Nested config and fallback behavior coverage | | |||||
| | Create | `tests/integration/TestRenderedOutput.asp` | Production-page output assertions through safe HTTP capture | | |||||
| | Reference | `public/web.config` | Source of mirrored config keys for the test app | | | Reference | `public/web.config` | Source of mirrored config keys for the test app | | ||||
| | Reference | `core/helpers.asp` | Helper functions and config-loading behavior under test | | | Reference | `core/helpers.asp` | Helper functions and config-loading behavior under test | | ||||
| | Reference | `core/mvc.asp` | Dispatcher behavior used by the smoke test | | | Reference | `core/mvc.asp` | Dispatcher behavior used by the smoke test | | ||||
| @@ -43,6 +47,8 @@ The `tests/` IIS application assumes the repository layout keeps `tests/`, `publ | |||||
| 4. Ensure parent paths are allowed for the `tests/` app. This repo ships `tests/web.config` with `enableParentPaths="true"` because the bootstrap and integration pages include sibling files from `../core/` and `../app/`. | 4. Ensure parent paths are allowed for the `tests/` app. This repo ships `tests/web.config` with `enableParentPaths="true"` because the bootstrap and integration pages include sibling files from `../core/` and `../app/`. | ||||
| 5. Browse to the `tests/` app root or directly to `run-all.asp`. | 5. Browse to the `tests/` app root or directly to `run-all.asp`. | ||||
| 6. If you change `tests/web.config`, run `cscript //nologo tests\sync-webconfigs.vbs` to refresh the nested copies used by the unit, component, and integration pages. | 6. If you change `tests/web.config`, run `cscript //nologo tests\sync-webconfigs.vbs` to refresh the nested copies used by the unit, component, and integration pages. | ||||
| 7. If your production app is not served from the same host root as the `tests/` app, set `ProductionAppBaseUrl` in `tests/web.config` and re-run the sync script so rendered-output tests know where to send HTTP requests. | |||||
| Example: `http://localhost/` for a root site, or `http://localhost/MyClassicApp/` for a virtual-directory app. | |||||
| Example layout: | Example layout: | ||||
| @@ -58,6 +64,7 @@ Example layout: | |||||
| - helper/config access | - helper/config access | ||||
| - controller registry access | - controller registry access | ||||
| - router reset | - router reset | ||||
| - `tests/support/HttpCaptureHelpers.asp` provides safe HTTP-based page capture for rendered output assertions against the production app. | |||||
| The integration test page includes `core/mvc.asp` directly because that is the only first-wave test that needs dispatcher behavior. | The integration test page includes `core/mvc.asp` directly because that is the only first-wave test that needs dispatcher behavior. | ||||
| @@ -82,7 +89,7 @@ aspunit renders a UI in runner mode and loads each registered page with `?task=t | |||||
| 1. Choose the right folder: | 1. Choose the right folder: | ||||
| - `tests/unit/` for deterministic helper or registry tests | - `tests/unit/` for deterministic helper or registry tests | ||||
| - `tests/component/` for direct controller/object tests with controlled setup | - `tests/component/` for direct controller/object tests with controlled setup | ||||
| - `tests/integration/` for narrow runtime smoke coverage | |||||
| - `tests/integration/` for narrow runtime smoke coverage, config behavior, or rendered-page capture | |||||
| 2. Create a new `.asp` file that: | 2. Create a new `.asp` file that: | ||||
| - includes `../aspunit/Lib/ASPUnit.asp` | - includes `../aspunit/Lib/ASPUnit.asp` | ||||
| - includes `../bootstrap.asp` | - includes `../bootstrap.asp` | ||||
| @@ -111,6 +118,8 @@ aspunit renders a UI in runner mode and loads each registered page with `?task=t | |||||
| - `run-all.asp` loads in the separate `tests/` IIS app. | - `run-all.asp` loads in the separate `tests/` IIS app. | ||||
| - All manifest pages appear in the runner. | - All manifest pages appear in the runner. | ||||
| - Helper, registry, component, and integration suites all execute. | - Helper, registry, component, and integration suites all execute. | ||||
| - Route-helper/config integration assertions execute from the same isolated IIS app. | |||||
| - Rendered-page capture assertions can verify production HTML and status codes without polluting aspunit JSON responses. | |||||
| - Re-running the suite produces stable results. | - Re-running the suite produces stable results. | ||||
| - The production site under `public/` still exposes no test runner pages or test routes. | - The production site under `public/` still exposes no test runner pages or test routes. | ||||
| @@ -2,9 +2,11 @@ | |||||
| <configuration> | <configuration> | ||||
| <appSettings> | <appSettings> | ||||
| <add key="Environment" value="Development" /> | <add key="Environment" value="Development" /> | ||||
| <add key="Error404RedirectSeconds" value="5" /> | |||||
| <add key="CacheExpirationYear" value="2030" /> | <add key="CacheExpirationYear" value="2030" /> | ||||
| <add key="EnableCacheBusting" value="false" /> | <add key="EnableCacheBusting" value="false" /> | ||||
| <add key="CacheBustParamName" value="v" /> | <add key="CacheBustParamName" value="v" /> | ||||
| <add key="ProductionAppBaseUrl" value="http://localhost:8081/" /> | |||||
| </appSettings> | </appSettings> | ||||
| <system.webServer> | <system.webServer> | ||||
| @@ -0,0 +1,41 @@ | |||||
| <!-- #include file="../aspunit/Lib/ASPUnit.asp" --> | |||||
| <!-- #include file="../bootstrap.asp" --> | |||||
| <% | |||||
| Call ASPUnit.AddModule( _ | |||||
| ASPUnit.CreateModule( _ | |||||
| "Config Integration Tests", _ | |||||
| Array( _ | |||||
| ASPUnit.CreateTest("NestedTestPageReadsMirroredConfigValue"), _ | |||||
| ASPUnit.CreateTest("MissingConfigKeyReturnsNothingSentinel"), _ | |||||
| ASPUnit.CreateTest("ProductionAppBaseUrlSupportsBlankOrConfiguredValue") _ | |||||
| ), _ | |||||
| ASPUnit.CreateLifeCycle("SetupConfigIntegration", "TeardownConfigIntegration") _ | |||||
| ) _ | |||||
| ) | |||||
| Call ASPUnit.Run() | |||||
| Sub SetupConfigIntegration() | |||||
| Call ResetTestRuntime() | |||||
| End Sub | |||||
| Sub TeardownConfigIntegration() | |||||
| Call ResetTestRuntime() | |||||
| End Sub | |||||
| Function NestedTestPageReadsMirroredConfigValue() | |||||
| Call ASPUnit.Equal(GetAppSetting("Error404RedirectSeconds"), "5", "Nested integration pages should read mirrored config values from their local web.config") | |||||
| End Function | |||||
| Function MissingConfigKeyReturnsNothingSentinel() | |||||
| Call ASPUnit.Equal(GetAppSetting("DefinitelyMissingSetting"), "nothing", "Missing config keys should return the existing nothing sentinel") | |||||
| End Function | |||||
| Function ProductionAppBaseUrlSupportsBlankOrConfiguredValue() | |||||
| Dim configuredUrl | |||||
| configuredUrl = GetAppSetting("ProductionAppBaseUrl") | |||||
| Call ASPUnit.Ok((configuredUrl = "" Or configuredUrl = "nothing" Or InStr(configuredUrl, "http://") = 1 Or InStr(configuredUrl, "https://") = 1), "ProductionAppBaseUrl should be either blank for host fallback or an explicit absolute URL") | |||||
| End Function | |||||
| %> | |||||
| @@ -0,0 +1,52 @@ | |||||
| <!-- #include file="../aspunit/Lib/ASPUnit.asp" --> | |||||
| <!-- #include file="../bootstrap.asp" --> | |||||
| <!-- #include file="../support/HttpCaptureHelpers.asp" --> | |||||
| <% | |||||
| Call ASPUnit.AddModule( _ | |||||
| ASPUnit.CreateModule( _ | |||||
| "Rendered Output Capture Tests", _ | |||||
| Array( _ | |||||
| ASPUnit.CreateTest("HomePageReturnsWelcomeMarkup"), _ | |||||
| ASPUnit.CreateTest("NotFoundPageReturns404Markup") _ | |||||
| ), _ | |||||
| ASPUnit.CreateLifeCycle("SetupRenderedOutput", "TeardownRenderedOutput") _ | |||||
| ) _ | |||||
| ) | |||||
| Call ASPUnit.Run() | |||||
| Sub SetupRenderedOutput() | |||||
| Call ResetTestRuntime() | |||||
| End Sub | |||||
| Sub TeardownRenderedOutput() | |||||
| Call ResetTestRuntime() | |||||
| End Sub | |||||
| Function HomePageReturnsWelcomeMarkup() | |||||
| Dim responseData | |||||
| Dim bodyContains, message | |||||
| Set responseData = FetchPage("/") | |||||
| bodyContains = (InStr(responseData.Item("body"), "Welcome to RouteKit Classic ASP") > 0) | |||||
| message = "Home page request should return welcome markup. URL=" & responseData.Item("url") & "; Status=" & responseData.Item("status") & "; Snippet=" & Left(CStr(responseData.Item("body")), 160) | |||||
| Call ASPUnit.Ok((responseData.Item("status") = 200 And bodyContains), message) | |||||
| Set responseData = Nothing | |||||
| End Function | |||||
| Function NotFoundPageReturns404Markup() | |||||
| Dim responseData | |||||
| Dim bodyContains, message | |||||
| Set responseData = FetchPage("/404") | |||||
| bodyContains = (InStr(responseData.Item("body"), "404 - Page Not Found") > 0) | |||||
| message = "404 request should return not-found markup. URL=" & responseData.Item("url") & "; Status=" & responseData.Item("status") & "; Snippet=" & Left(CStr(responseData.Item("body")), 160) | |||||
| Call ASPUnit.Ok((responseData.Item("status") = 404 And bodyContains), message) | |||||
| Set responseData = Nothing | |||||
| End Function | |||||
| %> | |||||
| @@ -0,0 +1,51 @@ | |||||
| <!-- #include file="../aspunit/Lib/ASPUnit.asp" --> | |||||
| <!-- #include file="../bootstrap.asp" --> | |||||
| <!-- #include file="../../core/lib.Routes.asp" --> | |||||
| <% | |||||
| Call ASPUnit.AddModule( _ | |||||
| ASPUnit.CreateModule( _ | |||||
| "Route Helper Integration Tests", _ | |||||
| Array( _ | |||||
| ASPUnit.CreateTest("RouteHelperReadsCacheBustingSettingFromConfig"), _ | |||||
| ASPUnit.CreateTest("UrlToBuildsLowercaseControllerActionPath"), _ | |||||
| ASPUnit.CreateTest("AssetUrlCanOverrideCacheBustingPerCall") _ | |||||
| ), _ | |||||
| ASPUnit.CreateLifeCycle("SetupRouteHelper", "TeardownRouteHelper") _ | |||||
| ) _ | |||||
| ) | |||||
| Call ASPUnit.Run() | |||||
| Sub SetupRouteHelper() | |||||
| Call ResetTestRuntime() | |||||
| On Error Resume Next | |||||
| Set Route_Helper__Singleton = Nothing | |||||
| On Error GoTo 0 | |||||
| End Sub | |||||
| Sub TeardownRouteHelper() | |||||
| On Error Resume Next | |||||
| Set Route_Helper__Singleton = Nothing | |||||
| On Error GoTo 0 | |||||
| Call ResetTestRuntime() | |||||
| End Sub | |||||
| Function RouteHelperReadsCacheBustingSettingFromConfig() | |||||
| Call ASPUnit.Ok((Not Routes().CacheBustingEnabled), "Routes helper should read disabled cache-busting from tests/web.config") | |||||
| End Function | |||||
| Function UrlToBuildsLowercaseControllerActionPath() | |||||
| Dim url | |||||
| url = Routes().UrlTo("HomeController", "Index", Array("id", "7")) | |||||
| Call ASPUnit.Ok((InStr(LCase(url), "/homecontroller/index?id=7") > 0), "UrlTo should build a lowercase controller/action path with query parameters") | |||||
| End Function | |||||
| Function AssetUrlCanOverrideCacheBustingPerCall() | |||||
| Dim url | |||||
| url = Routes().AssetUrl("css/site.css", True) | |||||
| Call ASPUnit.Ok((InStr(url, "css/site.css?v=") > 0), "AssetUrl should append the configured cache-bust parameter when override is true") | |||||
| End Function | |||||
| %> | |||||
| @@ -2,9 +2,11 @@ | |||||
| <configuration> | <configuration> | ||||
| <appSettings> | <appSettings> | ||||
| <add key="Environment" value="Development" /> | <add key="Environment" value="Development" /> | ||||
| <add key="Error404RedirectSeconds" value="5" /> | |||||
| <add key="CacheExpirationYear" value="2030" /> | <add key="CacheExpirationYear" value="2030" /> | ||||
| <add key="EnableCacheBusting" value="false" /> | <add key="EnableCacheBusting" value="false" /> | ||||
| <add key="CacheBustParamName" value="v" /> | <add key="CacheBustParamName" value="v" /> | ||||
| <add key="ProductionAppBaseUrl" value="http://localhost:8081/" /> | |||||
| </appSettings> | </appSettings> | ||||
| <system.webServer> | <system.webServer> | ||||
| @@ -0,0 +1,48 @@ | |||||
| <% | |||||
| Function BuildRequestOrigin() | |||||
| Dim protocol | |||||
| protocol = "http://" | |||||
| If LCase(Request.ServerVariables("HTTPS")) = "on" Then | |||||
| protocol = "https://" | |||||
| End If | |||||
| BuildRequestOrigin = protocol & Request.ServerVariables("HTTP_HOST") | |||||
| End Function | |||||
| Function GetProductionBaseUrl() | |||||
| Dim configuredUrl | |||||
| configuredUrl = GetAppSetting("ProductionAppBaseUrl") | |||||
| If configuredUrl = "nothing" Or Len(Trim(configuredUrl)) = 0 Then | |||||
| GetProductionBaseUrl = BuildRequestOrigin() & "/" | |||||
| Else | |||||
| If Right(configuredUrl, 1) <> "/" Then | |||||
| configuredUrl = configuredUrl & "/" | |||||
| End If | |||||
| GetProductionBaseUrl = configuredUrl | |||||
| End If | |||||
| End Function | |||||
| Function FetchPage(path) | |||||
| Dim http, result, targetUrl | |||||
| targetUrl = GetProductionBaseUrl() | |||||
| If Left(path, 1) = "/" Then | |||||
| path = Mid(path, 2) | |||||
| End If | |||||
| targetUrl = targetUrl & path | |||||
| Set http = Server.CreateObject("MSXML2.ServerXMLHTTP.6.0") | |||||
| http.Open "GET", targetUrl, False | |||||
| http.Send | |||||
| Set result = Server.CreateObject("Scripting.Dictionary") | |||||
| result.Add "url", targetUrl | |||||
| result.Add "status", http.Status | |||||
| result.Add "body", http.responseText | |||||
| Set FetchPage = result | |||||
| Set http = Nothing | |||||
| End Function | |||||
| %> | |||||
| @@ -4,7 +4,10 @@ Sub RegisterTestPages() | |||||
| "unit/TestHelpers.asp", _ | "unit/TestHelpers.asp", _ | ||||
| "unit/TestControllerRegistry.asp", _ | "unit/TestControllerRegistry.asp", _ | ||||
| "component/TestHomeController.asp", _ | "component/TestHomeController.asp", _ | ||||
| "integration/TestMvcDispatch.asp" _ | |||||
| "integration/TestMvcDispatch.asp", _ | |||||
| "integration/TestRoutes.asp", _ | |||||
| "integration/TestConfigSettings.asp", _ | |||||
| "integration/TestRenderedOutput.asp" _ | |||||
| )) | )) | ||||
| End Sub | End Sub | ||||
| %> | %> | ||||
| @@ -2,9 +2,11 @@ | |||||
| <configuration> | <configuration> | ||||
| <appSettings> | <appSettings> | ||||
| <add key="Environment" value="Development" /> | <add key="Environment" value="Development" /> | ||||
| <add key="Error404RedirectSeconds" value="5" /> | |||||
| <add key="CacheExpirationYear" value="2030" /> | <add key="CacheExpirationYear" value="2030" /> | ||||
| <add key="EnableCacheBusting" value="false" /> | <add key="EnableCacheBusting" value="false" /> | ||||
| <add key="CacheBustParamName" value="v" /> | <add key="CacheBustParamName" value="v" /> | ||||
| <add key="ProductionAppBaseUrl" value="http://localhost:8081/" /> | |||||
| </appSettings> | </appSettings> | ||||
| <system.webServer> | <system.webServer> | ||||
| @@ -2,9 +2,11 @@ | |||||
| <configuration> | <configuration> | ||||
| <appSettings> | <appSettings> | ||||
| <add key="Environment" value="Development" /> | <add key="Environment" value="Development" /> | ||||
| <add key="Error404RedirectSeconds" value="5" /> | |||||
| <add key="CacheExpirationYear" value="2030" /> | <add key="CacheExpirationYear" value="2030" /> | ||||
| <add key="EnableCacheBusting" value="false" /> | <add key="EnableCacheBusting" value="false" /> | ||||
| <add key="CacheBustParamName" value="v" /> | <add key="CacheBustParamName" value="v" /> | ||||
| <add key="ProductionAppBaseUrl" value="http://localhost:8081/" /> | |||||
| </appSettings> | </appSettings> | ||||
| <system.webServer> | <system.webServer> | ||||
Powered by TurnKey Linux.