mirror of
https://github.com/alexhopeoconnor/WiFiManager.git
synced 2026-10-04 02:48:13 +10:00
WiFiManager: stream info and wifi pages through DFTE.
Harden the root placeholder path, add direct render-isolation coverage, move simple status pages and /info onto request-scoped streamed templates, and switch /wifi to a streamed shell while keeping scan/form sections string-built for now.
This commit is contained in:
@@ -32,6 +32,7 @@ TestCase tests[] = {
|
||||
TEST_ENTRY(test_get_config_portal_ssid),
|
||||
TEST_ENTRY(test_root_render_menu_state_transitions),
|
||||
TEST_ENTRY(test_root_render_snapshot_consistency),
|
||||
TEST_ENTRY(test_root_render_interleaved_context_isolation),
|
||||
|
||||
// Non-blocking tests
|
||||
TEST_ENTRY(test_nonblocking_process),
|
||||
|
||||
@@ -42,6 +42,7 @@ void test_config_portal_already_active();
|
||||
void test_get_config_portal_ssid();
|
||||
void test_root_render_menu_state_transitions();
|
||||
void test_root_render_snapshot_consistency();
|
||||
void test_root_render_interleaved_context_isolation();
|
||||
|
||||
// Non-blocking tests
|
||||
void test_nonblocking_process();
|
||||
|
||||
@@ -2,6 +2,59 @@
|
||||
#include <Arduino.h>
|
||||
#include <WiFiManager.h>
|
||||
#include <WiFiManagerHandlers.h>
|
||||
#include <TemplateEngine.h>
|
||||
#include "templates/RootSelector.h"
|
||||
|
||||
namespace {
|
||||
|
||||
const char kEmptyTemplateChunk[] PROGMEM = "";
|
||||
const char kTestTitle[] PROGMEM = "WiFiManager";
|
||||
const char kTestSubtitle[] PROGMEM = "Root Test";
|
||||
|
||||
const char* dynamicStringGetter(void* userData) {
|
||||
const auto* value = static_cast<const String*>(userData);
|
||||
return value ? value->c_str() : "";
|
||||
}
|
||||
|
||||
size_t dynamicStringLengthGetter(const char* data, void* /*userData*/) {
|
||||
return data ? strlen(data) : 0;
|
||||
}
|
||||
|
||||
void configureDescriptor(DynamicTemplateDescriptor& descriptor, String& value) {
|
||||
descriptor.getter = &dynamicStringGetter;
|
||||
descriptor.getLength = &dynamicStringLengthGetter;
|
||||
descriptor.userData = &value;
|
||||
}
|
||||
|
||||
void renderContextsInterleaved(TemplateContext& first, String& firstOutput,
|
||||
TemplateContext& second, String& secondOutput) {
|
||||
uint8_t firstBuffer[31];
|
||||
uint8_t secondBuffer[31];
|
||||
bool firstDone = false;
|
||||
bool secondDone = false;
|
||||
|
||||
while (!firstDone || !secondDone) {
|
||||
if (!firstDone) {
|
||||
size_t written = TemplateRenderer::renderNextChunk(first, firstBuffer, sizeof(firstBuffer));
|
||||
if (written == 0) {
|
||||
firstDone = true;
|
||||
} else {
|
||||
firstOutput.concat(reinterpret_cast<const char*>(firstBuffer), written);
|
||||
}
|
||||
}
|
||||
|
||||
if (!secondDone) {
|
||||
size_t written = TemplateRenderer::renderNextChunk(second, secondBuffer, sizeof(secondBuffer));
|
||||
if (written == 0) {
|
||||
secondDone = true;
|
||||
} else {
|
||||
secondOutput.concat(reinterpret_cast<const char*>(secondBuffer), written);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void test_root_render_menu_state_transitions() {
|
||||
Serial.println("[TEST] Testing root menu state transitions...");
|
||||
@@ -62,3 +115,68 @@ void test_root_render_snapshot_consistency() {
|
||||
|
||||
Serial.println("[TEST] Root render snapshot consistency test completed successfully");
|
||||
}
|
||||
|
||||
void test_root_render_interleaved_context_isolation() {
|
||||
Serial.println("[TEST] Testing root render interleaved context isolation...");
|
||||
|
||||
PlaceholderRegistry registryA(8);
|
||||
PlaceholderRegistry registryB(8);
|
||||
|
||||
registryA.registerProgmemData("%SCRIPTS%", kEmptyTemplateChunk);
|
||||
registryA.registerProgmemData("%STYLES%", kEmptyTemplateChunk);
|
||||
registryA.registerProgmemData("%PAGE_TITLE%", kTestTitle);
|
||||
registryA.registerProgmemData("%SUBTITLE%", kTestSubtitle);
|
||||
|
||||
registryB.registerProgmemData("%SCRIPTS%", kEmptyTemplateChunk);
|
||||
registryB.registerProgmemData("%STYLES%", kEmptyTemplateChunk);
|
||||
registryB.registerProgmemData("%PAGE_TITLE%", kTestTitle);
|
||||
registryB.registerProgmemData("%SUBTITLE%", kTestSubtitle);
|
||||
|
||||
String menuA = F("<div>Menu A</div>");
|
||||
String statusA = F("<div>Status A</div>");
|
||||
String menuB = F("<div>Menu B</div>");
|
||||
String statusB = F("<div>Status B</div>");
|
||||
|
||||
DynamicTemplateDescriptor menuDescriptorA{};
|
||||
DynamicTemplateDescriptor statusDescriptorA{};
|
||||
DynamicTemplateDescriptor menuDescriptorB{};
|
||||
DynamicTemplateDescriptor statusDescriptorB{};
|
||||
|
||||
configureDescriptor(menuDescriptorA, menuA);
|
||||
configureDescriptor(statusDescriptorA, statusA);
|
||||
configureDescriptor(menuDescriptorB, menuB);
|
||||
configureDescriptor(statusDescriptorB, statusB);
|
||||
|
||||
TEST_ASSERT_TRUE_MESSAGE(registryA.registerDynamicTemplate("%MENU%", &menuDescriptorA),
|
||||
"Registry A menu placeholder should register");
|
||||
TEST_ASSERT_TRUE_MESSAGE(registryA.registerDynamicTemplate("%STATUS%", &statusDescriptorA),
|
||||
"Registry A status placeholder should register");
|
||||
TEST_ASSERT_TRUE_MESSAGE(registryB.registerDynamicTemplate("%MENU%", &menuDescriptorB),
|
||||
"Registry B menu placeholder should register");
|
||||
TEST_ASSERT_TRUE_MESSAGE(registryB.registerDynamicTemplate("%STATUS%", &statusDescriptorB),
|
||||
"Registry B status placeholder should register");
|
||||
|
||||
TemplateContext contextA;
|
||||
TemplateContext contextB;
|
||||
contextA.setRegistry(®istryA);
|
||||
contextB.setRegistry(®istryB);
|
||||
|
||||
TemplateRenderer::initializeContext(contextA, WM_ROOT_TEMPLATE);
|
||||
TemplateRenderer::initializeContext(contextB, WM_ROOT_TEMPLATE);
|
||||
|
||||
String outputA;
|
||||
String outputB;
|
||||
renderContextsInterleaved(contextA, outputA, contextB, outputB);
|
||||
|
||||
TEST_ASSERT_NOT_EQUAL(-1, outputA.indexOf("Menu A"));
|
||||
TEST_ASSERT_NOT_EQUAL(-1, outputA.indexOf("Status A"));
|
||||
TEST_ASSERT_EQUAL(-1, outputA.indexOf("Menu B"));
|
||||
TEST_ASSERT_EQUAL(-1, outputA.indexOf("Status B"));
|
||||
|
||||
TEST_ASSERT_NOT_EQUAL(-1, outputB.indexOf("Menu B"));
|
||||
TEST_ASSERT_NOT_EQUAL(-1, outputB.indexOf("Status B"));
|
||||
TEST_ASSERT_EQUAL(-1, outputB.indexOf("Menu A"));
|
||||
TEST_ASSERT_EQUAL(-1, outputB.indexOf("Status A"));
|
||||
|
||||
Serial.println("[TEST] Root render interleaved context isolation test completed successfully");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user