fix(provisioning): stop redrawing the QR on every poll, add WiFi-fail retry screen
Two related fixes that together let the post-WiFi-setup window be quiet: 1. operation.h 204/404: skip the panel redraw entirely. The panel already holds the right thing — setup QR if no image has ever been painted (img_id == -1), or a real photo if img_id >= 0. Redrawing the QR every 15s during the bootstrap claim window put the e-ink into a perpetual ~20s mid-refresh loop and risked ghosting. Tests updated to assert no redraw on either sub-case. 2. main.cpp WiFi-fail path: drop the epd_fill(RED) + 3s delay + AP re-redraw sequence (~43s of e-ink work that destroyed the QR mid-flow) and replace with a single repaint of a new "Connection Failed — try again" Step 1/2 screen with red accents. gen_screens.py grows a gen_ap_retry() variant that recolors yellow → red and swaps the header/QR labels; the result is shipped as ap_bg_retry.bin alongside ap_bg.bin in LittleFS. epd.h exposes epd_draw_ap_screen_retry().
This commit is contained in:
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
+31
-12
@@ -146,15 +146,20 @@ def orientation_diagrams(draw, accent, show_active_ls=True):
|
|||||||
|
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════════════════════════
|
# ═══════════════════════════════════════════════════════════════════════════════
|
||||||
# AP SCREEN — yellow accent, WiFi credentials
|
# AP SCREEN — accent-colored, WiFi credentials
|
||||||
|
# Pass accent=YL/header="SETUP MODE — STEP 1 OF 2"/qr_label="SCAN TO CONNECT"
|
||||||
|
# for the normal first-attempt screen, or accent=RD/header="CONNECTION FAILED
|
||||||
|
# — TRY AGAIN"/qr_label="Connection Failed — try again" for the post-WiFi-fail
|
||||||
|
# retry screen. Same layout either way so the panel diff is just color +
|
||||||
|
# header/label text.
|
||||||
# ═══════════════════════════════════════════════════════════════════════════════
|
# ═══════════════════════════════════════════════════════════════════════════════
|
||||||
def gen_ap():
|
def gen_ap(accent=YL, header="SETUP MODE — STEP 1 OF 2", qr_label="SCAN TO CONNECT"):
|
||||||
img = Image.new("RGB", (W, H), WH)
|
img = Image.new("RGB", (W, H), WH)
|
||||||
draw = ImageDraw.Draw(img)
|
draw = ImageDraw.Draw(img)
|
||||||
|
|
||||||
# ── Status bar ────────────────────────────────────────────────
|
# ── Status bar ────────────────────────────────────────────────
|
||||||
draw.rectangle([0, 0, W-1, BAR_H-1], fill=YL)
|
draw.rectangle([0, 0, W-1, BAR_H-1], fill=accent)
|
||||||
draw.text((24, 18), "SETUP MODE — STEP 1 OF 2", font=F_BAR, fill=BK)
|
draw.text((24, 18), header, font=F_BAR, fill=BK)
|
||||||
|
|
||||||
# Right chip: black box with device SSID
|
# Right chip: black box with device SSID
|
||||||
chip_x, chip_y = 498, 11
|
chip_x, chip_y = 498, 11
|
||||||
@@ -163,7 +168,7 @@ def gen_ap():
|
|||||||
chip_w = bb[2]-bb[0] + 22
|
chip_w = bb[2]-bb[0] + 22
|
||||||
chip_x2 = chip_x + chip_w
|
chip_x2 = chip_x + chip_w
|
||||||
draw.rectangle([chip_x, chip_y, chip_x2, BAR_H-12], fill=BK)
|
draw.rectangle([chip_x, chip_y, chip_x2, BAR_H-12], fill=BK)
|
||||||
draw.text((chip_x+11, chip_y+7), chip_text, font=F_CHIP, fill=YL)
|
draw.text((chip_x+11, chip_y+7), chip_text, font=F_CHIP, fill=accent)
|
||||||
|
|
||||||
# ── Panel dividers ────────────────────────────────────────────
|
# ── Panel dividers ────────────────────────────────────────────
|
||||||
draw.rectangle([DIV1_X, BODY_Y, DIV1_X+1, H-1], fill=BK)
|
draw.rectangle([DIV1_X, BODY_Y, DIV1_X+1, H-1], fill=BK)
|
||||||
@@ -174,7 +179,7 @@ def gen_ap():
|
|||||||
draw.text((28, BODY_Y+20), "Connect to", font=F_HEAD, fill=BK)
|
draw.text((28, BODY_Y+20), "Connect to", font=F_HEAD, fill=BK)
|
||||||
draw.text((28, BODY_Y+52), "WiFi", font=F_HEAD, fill=BK)
|
draw.text((28, BODY_Y+52), "WiFi", font=F_HEAD, fill=BK)
|
||||||
bb = draw.textbbox((0,0), "WiFi", font=F_HEAD)
|
bb = draw.textbbox((0,0), "WiFi", font=F_HEAD)
|
||||||
draw.rectangle([28, BODY_Y+82, 28+bb[2]+2, BODY_Y+85], fill=YL)
|
draw.rectangle([28, BODY_Y+82, 28+bb[2]+2, BODY_Y+85], fill=accent)
|
||||||
|
|
||||||
# Steps
|
# Steps
|
||||||
steps = [
|
steps = [
|
||||||
@@ -186,7 +191,7 @@ def gen_ap():
|
|||||||
for i, (l1, l2) in enumerate(steps):
|
for i, (l1, l2) in enumerate(steps):
|
||||||
bx, by = 28, sy + i*46
|
bx, by = 28, sy + i*46
|
||||||
draw.rectangle([bx, by, bx+24, by+24], fill=BK)
|
draw.rectangle([bx, by, bx+24, by+24], fill=BK)
|
||||||
text_center(draw, bx+12, by+6, str(i+1), F_STEPN, YL)
|
text_center(draw, bx+12, by+6, str(i+1), F_STEPN, accent)
|
||||||
draw.text((62, by+3), l1, font=F_STEP, fill=BK)
|
draw.text((62, by+3), l1, font=F_STEP, fill=BK)
|
||||||
draw.text((62, by+17), l2, font=F_STEP, fill=BK)
|
draw.text((62, by+17), l2, font=F_STEP, fill=BK)
|
||||||
|
|
||||||
@@ -196,17 +201,18 @@ def gen_ap():
|
|||||||
draw.text((28, BODY_Y+276), "Go to 192.168.4.1", font=F_FOOT, fill=BK)
|
draw.text((28, BODY_Y+276), "Go to 192.168.4.1", font=F_FOOT, fill=BK)
|
||||||
|
|
||||||
# ── Centre panel ─────────────────────────────────────────────
|
# ── Centre panel ─────────────────────────────────────────────
|
||||||
orientation_diagrams(draw, YL, show_active_ls=True)
|
orientation_diagrams(draw, accent, show_active_ls=True)
|
||||||
|
|
||||||
# ── Right panel ──────────────────────────────────────────────
|
# ── Right panel ──────────────────────────────────────────────
|
||||||
cx = RIGHT_CX
|
cx = RIGHT_CX
|
||||||
|
|
||||||
# "SCAN TO CONNECT" label
|
# QR label — accent-colored on retry so the failure is unmistakable.
|
||||||
text_center(draw, cx, AP_QR_Y - 26, "SCAN TO CONNECT", F_BIG, BK)
|
label_color = accent if accent != YL else BK
|
||||||
|
text_center(draw, cx, AP_QR_Y - 26, qr_label, F_BIG, label_color)
|
||||||
|
|
||||||
# QR border: yellow outer, black inner
|
# QR border: accent outer, black inner
|
||||||
qx, qy, qp = AP_QR_X, AP_QR_Y, AP_QR_PX
|
qx, qy, qp = AP_QR_X, AP_QR_Y, AP_QR_PX
|
||||||
draw.rectangle([qx-6, qy-6, qx+qp+5, qy+qp+5], outline=YL, width=3)
|
draw.rectangle([qx-6, qy-6, qx+qp+5, qy+qp+5], outline=accent, width=3)
|
||||||
draw.rectangle([qx-3, qy-3, qx+qp+2, qy+qp+2], outline=BK, width=3)
|
draw.rectangle([qx-3, qy-3, qx+qp+2, qy+qp+2], outline=BK, width=3)
|
||||||
|
|
||||||
# Leave QR area white for firmware overlay
|
# Leave QR area white for firmware overlay
|
||||||
@@ -218,6 +224,16 @@ def gen_ap():
|
|||||||
return img
|
return img
|
||||||
|
|
||||||
|
|
||||||
|
def gen_ap_retry():
|
||||||
|
"""Step 1/2 with red accents + 'Connection Failed — try again' label,
|
||||||
|
served after a failed WiFi connection attempt."""
|
||||||
|
return gen_ap(
|
||||||
|
accent=RD,
|
||||||
|
header="CONNECTION FAILED — TRY AGAIN",
|
||||||
|
qr_label="Connection Failed — try again",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════════════════════════
|
# ═══════════════════════════════════════════════════════════════════════════════
|
||||||
# SETUP SCREEN — green accent, account link
|
# SETUP SCREEN — green accent, account link
|
||||||
# ═══════════════════════════════════════════════════════════════════════════════
|
# ═══════════════════════════════════════════════════════════════════════════════
|
||||||
@@ -342,6 +358,9 @@ if __name__ == "__main__":
|
|||||||
print(f"Generating AP screen for {panel}…")
|
print(f"Generating AP screen for {panel}…")
|
||||||
save_bin(gen_ap(), f"{out_dir}/ap_bg.bin", f"{out_dir}/ap_bg_preview.png")
|
save_bin(gen_ap(), f"{out_dir}/ap_bg.bin", f"{out_dir}/ap_bg_preview.png")
|
||||||
print()
|
print()
|
||||||
|
print(f"Generating AP retry screen for {panel}…")
|
||||||
|
save_bin(gen_ap_retry(), f"{out_dir}/ap_bg_retry.bin", f"{out_dir}/ap_bg_retry_preview.png")
|
||||||
|
print()
|
||||||
print(f"Generating setup screen for {panel}…")
|
print(f"Generating setup screen for {panel}…")
|
||||||
save_bin(gen_setup(), f"{out_dir}/setup_bg.bin", f"{out_dir}/setup_bg_preview.png")
|
save_bin(gen_setup(), f"{out_dir}/setup_bg.bin", f"{out_dir}/setup_bg_preview.png")
|
||||||
print()
|
print()
|
||||||
|
|||||||
@@ -20,4 +20,7 @@ void epd_draw_qr(QRCode* qr, uint8_t cellPx, uint8_t bg, uint8_t fg);
|
|||||||
|
|
||||||
// Draw the setup screen: pre-rendered background from LittleFS with QR overlaid.
|
// Draw the setup screen: pre-rendered background from LittleFS with QR overlaid.
|
||||||
void epd_draw_ap_screen(QRCode* qr);
|
void epd_draw_ap_screen(QRCode* qr);
|
||||||
|
// Same layout as ap_screen but with red accents and a "Connection Failed —
|
||||||
|
// try again" label, served after a failed WiFi join attempt.
|
||||||
|
void epd_draw_ap_screen_retry(QRCode* qr);
|
||||||
void epd_draw_setup_screen(QRCode* qr);
|
void epd_draw_setup_screen(QRCode* qr);
|
||||||
|
|||||||
+17
-12
@@ -25,14 +25,18 @@ static String g_req_pass;
|
|||||||
|
|
||||||
// ── QR helpers ───────────────────────────────────────────────────────────────
|
// ── QR helpers ───────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
static void show_ap_qr(const String& apSsid) {
|
static void show_ap_qr(const String& apSsid, bool retry = false) {
|
||||||
String content = "WIFI:S:" + apSsid + ";T:nopass;;";
|
String content = "WIFI:S:" + apSsid + ";T:nopass;;";
|
||||||
|
|
||||||
QRCode qr;
|
QRCode qr;
|
||||||
uint8_t buf[qrcode_getBufferSize(5)];
|
uint8_t buf[qrcode_getBufferSize(5)];
|
||||||
qrcode_initText(&qr, buf, 5, ECC_LOW, content.c_str());
|
qrcode_initText(&qr, buf, 5, ECC_LOW, content.c_str());
|
||||||
|
if (retry) {
|
||||||
|
epd_draw_ap_screen_retry(&qr);
|
||||||
|
} else {
|
||||||
epd_draw_ap_screen(&qr);
|
epd_draw_ap_screen(&qr);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void show_setup_qr(const String& mac) {
|
static void show_setup_qr(const String& mac) {
|
||||||
String url = String(APP_BASE_URL) + "/setup/" + mac;
|
String url = String(APP_BASE_URL) + "/setup/" + mac;
|
||||||
@@ -116,7 +120,7 @@ static void handle_captive() {
|
|||||||
|
|
||||||
// ── WiFi provisioning ─────────────────────────────────────────────────────────
|
// ── WiFi provisioning ─────────────────────────────────────────────────────────
|
||||||
|
|
||||||
static void enter_provisioning(const String& mac) {
|
static void enter_provisioning(const String& mac, bool retry = false) {
|
||||||
// Derive AP name from last 4 hex chars of MAC (no colons)
|
// Derive AP name from last 4 hex chars of MAC (no colons)
|
||||||
String suffix = mac;
|
String suffix = mac;
|
||||||
suffix.replace(":", "");
|
suffix.replace(":", "");
|
||||||
@@ -124,7 +128,7 @@ static void enter_provisioning(const String& mac) {
|
|||||||
suffix.toUpperCase();
|
suffix.toUpperCase();
|
||||||
String apSsid = "PictureFrame-" + suffix;
|
String apSsid = "PictureFrame-" + suffix;
|
||||||
|
|
||||||
Serial.println("AP: " + apSsid);
|
Serial.println(retry ? "AP (retry): " + apSsid : "AP: " + apSsid);
|
||||||
|
|
||||||
WiFi.disconnect(true);
|
WiFi.disconnect(true);
|
||||||
WiFi.mode(WIFI_AP);
|
WiFi.mode(WIFI_AP);
|
||||||
@@ -143,8 +147,11 @@ static void enter_provisioning(const String& mac) {
|
|||||||
server.onNotFound(handle_root);
|
server.onNotFound(handle_root);
|
||||||
server.begin();
|
server.begin();
|
||||||
|
|
||||||
|
// On retry, repaint with red accents + "Connection Failed — try again"
|
||||||
|
// label so the user has a clear visual signal that their last credential
|
||||||
|
// entry didn't work. On first entry, paint the standard yellow Step 1/2.
|
||||||
epd_init();
|
epd_init();
|
||||||
show_ap_qr(apSsid);
|
show_ap_qr(apSsid, retry);
|
||||||
epd_sleep();
|
epd_sleep();
|
||||||
|
|
||||||
g_provisioning = true;
|
g_provisioning = true;
|
||||||
@@ -267,13 +274,11 @@ void loop() {
|
|||||||
// serves an image — no need for an artificial display delay here.
|
// serves an image — no need for an artificial display delay here.
|
||||||
normal_operation(mac);
|
normal_operation(mac);
|
||||||
} else {
|
} else {
|
||||||
// Connection failed — fill red, restart AP
|
// Connection failed — go back into AP mode with the red retry screen
|
||||||
epd_init();
|
// so the user sees "Connection Failed — try again" and can rescan.
|
||||||
epd_fill(COLOR_RED);
|
// No epd_fill(COLOR_RED) detour: that would obliterate the QR for
|
||||||
epd_sleep();
|
// ~20 s and force a second redraw to put it back. One repaint into
|
||||||
delay(3000);
|
// the retry screen is faster and clearer.
|
||||||
|
enter_provisioning(mac, /*retry=*/true);
|
||||||
// Re-enter provisioning to retry
|
|
||||||
enter_provisioning(mac);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-9
@@ -263,16 +263,21 @@ void normal_operation_impl(const String& mac, HTTP& http, const String& url, Pre
|
|||||||
Serial.println("[op] recovery aborted: /img.bin not in LittleFS");
|
Serial.println("[op] recovery aborted: /img.bin not in LittleFS");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (code == 204) {
|
} else if (code == 204 || code == 404) {
|
||||||
|
// No image to serve. Don't touch the panel — whatever's already
|
||||||
|
// displayed is the right thing:
|
||||||
|
// • currentImgId == -1 → the setup QR is up (painted by
|
||||||
|
// enter_provisioning after WiFi save). The 15s bootstrap poll
|
||||||
|
// hits this branch every cycle until the user claims via
|
||||||
|
// /setup/{mac}; redrawing the QR each time would put the panel
|
||||||
|
// in a perpetual ~20s e-ink redraw loop and risk ghosting.
|
||||||
|
// • currentImgId >= 0 → a real photo is up (server hiccup, asset
|
||||||
|
// missing, image deleted). Don't paint the setup QR over the
|
||||||
|
// user's photo; leave the last-good image alone.
|
||||||
|
// displayInitialized stays false → epd_sleep() at the bottom is
|
||||||
|
// also skipped, since the display was already in sleep from the
|
||||||
|
// previous cycle.
|
||||||
http.end();
|
http.end();
|
||||||
displayInitialized = true;
|
|
||||||
epd_init();
|
|
||||||
show_setup_qr(mac);
|
|
||||||
} else if (code == 404) {
|
|
||||||
http.end();
|
|
||||||
displayInitialized = true;
|
|
||||||
epd_init();
|
|
||||||
show_setup_qr(mac);
|
|
||||||
} else {
|
} else {
|
||||||
// Sync failed (5xx, timeout, malformed). Per FR38, the last-good image
|
// Sync failed (5xx, timeout, malformed). Per FR38, the last-good image
|
||||||
// must persist; only the border indicates the error. epd_draw_image_with_border
|
// must persist; only the border indicates the error. epd_draw_image_with_border
|
||||||
|
|||||||
@@ -179,6 +179,12 @@ void epd_draw_ap_screen(QRCode* qr) {
|
|||||||
draw_from_lfs("/ap_bg.bin", COLOR_YELLOW, qr, 563, 185, 5);
|
draw_from_lfs("/ap_bg.bin", COLOR_YELLOW, qr, 563, 185, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void epd_draw_ap_screen_retry(QRCode* qr) {
|
||||||
|
// Same QR coordinates — only the bg .bin differs (red accents,
|
||||||
|
// "Connection Failed — try again" label).
|
||||||
|
draw_from_lfs("/ap_bg_retry.bin", COLOR_RED, qr, 563, 185, 5);
|
||||||
|
}
|
||||||
|
|
||||||
void epd_draw_setup_screen(QRCode* qr) {
|
void epd_draw_setup_screen(QRCode* qr) {
|
||||||
// SETUP_QR_X=553, SETUP_QR_Y=175, SETUP_QR_CELL=5 (must match gen_screens.py)
|
// SETUP_QR_X=553, SETUP_QR_Y=175, SETUP_QR_CELL=5 (must match gen_screens.py)
|
||||||
draw_from_lfs("/setup_bg.bin", COLOR_GREEN, qr, 553, 175, 5);
|
draw_from_lfs("/setup_bg.bin", COLOR_GREEN, qr, 553, 175, 5);
|
||||||
|
|||||||
@@ -14,4 +14,5 @@ inline void epd_sleep() { g_epd_sleep_count++; }
|
|||||||
inline void epd_draw_image_from_file(File& f) { g_epd_draw_image_count++; }
|
inline void epd_draw_image_from_file(File& f) { g_epd_draw_image_count++; }
|
||||||
inline void epd_fill(int color) { g_epd_fill_count++; g_epd_fill_last_color = color; }
|
inline void epd_fill(int color) { g_epd_fill_count++; g_epd_fill_last_color = color; }
|
||||||
inline void epd_draw_ap_screen(void*) {}
|
inline void epd_draw_ap_screen(void*) {}
|
||||||
|
inline void epd_draw_ap_screen_retry(void*) {}
|
||||||
inline void epd_draw_setup_screen(void*) { g_epd_draw_setup_count++; }
|
inline void epd_draw_setup_screen(void*) { g_epd_draw_setup_count++; }
|
||||||
|
|||||||
@@ -130,20 +130,41 @@ void test_fw03_304_no_redraw() {
|
|||||||
TEST_ASSERT_EQUAL_UINT64(30000ULL * 1000ULL, g_sleep_us);
|
TEST_ASSERT_EQUAL_UINT64(30000ULL * 1000ULL, g_sleep_us);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FW-04: 204 — show_setup_qr called exactly once
|
// FW-04: 204 with no prior image — panel already shows the setup QR from
|
||||||
void test_fw04_204_shows_setup_qr() {
|
// provisioning; the firmware MUST NOT redraw it on every 15s bootstrap poll
|
||||||
|
// or the e-ink panel sits in a perpetual mid-refresh loop.
|
||||||
|
void test_fw04_204_no_prior_image_does_not_redraw() {
|
||||||
g_http_get_code = 204;
|
g_http_get_code = 204;
|
||||||
|
// currentImgId defaults to -1 from prefs.clear() in reset_state()
|
||||||
normal_operation_impl(String("mac"), http, String("url"), prefs);
|
normal_operation_impl(String("mac"), http, String("url"), prefs);
|
||||||
TEST_ASSERT_EQUAL(1, g_show_setup_qr_count);
|
TEST_ASSERT_EQUAL_MESSAGE(0, g_show_setup_qr_count,
|
||||||
|
"204 must not redraw the QR — panel already holds it from provisioning");
|
||||||
|
TEST_ASSERT_EQUAL(0, g_epd_init_count);
|
||||||
TEST_ASSERT_EQUAL(0, g_epd_draw_image_count);
|
TEST_ASSERT_EQUAL(0, g_epd_draw_image_count);
|
||||||
|
TEST_ASSERT_TRUE(g_deep_sleep_started);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FW-05: 404 — show_setup_qr called exactly once
|
// FW-04b: 204 after a real image was previously displayed — panel holds the
|
||||||
void test_fw05_404_shows_setup_qr() {
|
// photo; firmware MUST NOT paint the setup QR over it.
|
||||||
|
void test_fw04b_204_with_prior_image_does_not_redraw() {
|
||||||
|
g_http_get_code = 204;
|
||||||
|
prefs.ints[NVS_KEY_IMG_ID] = 7; // device has previously painted image #7
|
||||||
|
normal_operation_impl(String("mac"), http, String("url"), prefs);
|
||||||
|
TEST_ASSERT_EQUAL_MESSAGE(0, g_show_setup_qr_count,
|
||||||
|
"204 must not paint the setup QR over a real photo");
|
||||||
|
TEST_ASSERT_EQUAL(0, g_epd_init_count);
|
||||||
|
TEST_ASSERT_EQUAL(0, g_epd_draw_image_count);
|
||||||
|
TEST_ASSERT_EQUAL(0, g_epd_fill_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FW-05: 404 — same logic as 204; panel keeps whatever's there.
|
||||||
|
void test_fw05_404_does_not_redraw() {
|
||||||
g_http_get_code = 404;
|
g_http_get_code = 404;
|
||||||
normal_operation_impl(String("mac"), http, String("url"), prefs);
|
normal_operation_impl(String("mac"), http, String("url"), prefs);
|
||||||
TEST_ASSERT_EQUAL(1, g_show_setup_qr_count);
|
TEST_ASSERT_EQUAL(0, g_show_setup_qr_count);
|
||||||
|
TEST_ASSERT_EQUAL(0, g_epd_init_count);
|
||||||
TEST_ASSERT_EQUAL(0, g_epd_draw_image_count);
|
TEST_ASSERT_EQUAL(0, g_epd_draw_image_count);
|
||||||
|
TEST_ASSERT_TRUE(g_deep_sleep_started);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FW-06a: 5xx error WITH a cached image → preserve last image and overlay a
|
// FW-06a: 5xx error WITH a cached image → preserve last image and overlay a
|
||||||
@@ -517,8 +538,9 @@ int main(int argc, char** argv) {
|
|||||||
RUN_TEST(test_fw01_200_response_happy_path);
|
RUN_TEST(test_fw01_200_response_happy_path);
|
||||||
RUN_TEST(test_fw02_headers_read_before_end_regression);
|
RUN_TEST(test_fw02_headers_read_before_end_regression);
|
||||||
RUN_TEST(test_fw03_304_no_redraw);
|
RUN_TEST(test_fw03_304_no_redraw);
|
||||||
RUN_TEST(test_fw04_204_shows_setup_qr);
|
RUN_TEST(test_fw04_204_no_prior_image_does_not_redraw);
|
||||||
RUN_TEST(test_fw05_404_shows_setup_qr);
|
RUN_TEST(test_fw04b_204_with_prior_image_does_not_redraw);
|
||||||
|
RUN_TEST(test_fw05_404_does_not_redraw);
|
||||||
RUN_TEST(test_fw06a_error_with_cache_draws_border_not_fill);
|
RUN_TEST(test_fw06a_error_with_cache_draws_border_not_fill);
|
||||||
RUN_TEST(test_fw06b_error_without_cache_falls_back_to_fill);
|
RUN_TEST(test_fw06b_error_without_cache_falls_back_to_fill);
|
||||||
RUN_TEST(test_fw06c_304_after_error_repaints_clean);
|
RUN_TEST(test_fw06c_304_after_error_repaints_clean);
|
||||||
|
|||||||
Reference in New Issue
Block a user