fix(ads): pulse a lone banner message through the fade cycle
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 9s
CI / integration (pull_request) Successful in 15s
CI / ui (pull_request) Successful in 49s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 57s
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 9s
CI / integration (pull_request) Successful in 15s
CI / ui (pull_request) Successful in 49s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 57s
A single campaign message (e.g. the default campaign's one message) faded in once on load and then sat frozen — the rotator only ran the fade/advance cycle when more than one message existed, so with one message there were no further fades. Drop the `total > 1` guards: every message now runs the full hold → fade-out → gap → fade-in cycle, so a lone message pulses (the same message fades back in) and a lone long message fades at each scroll-loop boundary. Multi-message rotation is unchanged. Verified by opacity sampling (single message pulses 1→0→gap→0→1 without navigation); the single-message test now asserts the pulse.
This commit is contained in:
@@ -122,14 +122,16 @@ describe('createBannerRotator', () => {
|
|||||||
r.stop();
|
r.stop();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('shows a single message once and never fades it out', () => {
|
it('pulses a lone message through the fade cycle (fades out, then back in)', () => {
|
||||||
vi.useFakeTimers();
|
vi.useFakeTimers();
|
||||||
const { host, calls, shown } = recordingHost(0);
|
const { host, calls, shown } = recordingHost(0);
|
||||||
const r = createBannerRotator([{ weight: 1, messages: ['solo'] }], host, cfg);
|
const r = createBannerRotator([{ weight: 1, messages: ['solo'] }], host, cfg);
|
||||||
r.start();
|
r.start();
|
||||||
vi.advanceTimersByTime(cfg.fadeInMs + cfg.holdMs * 5);
|
|
||||||
expect(shown).toEqual(['solo']);
|
expect(shown).toEqual(['solo']);
|
||||||
expect(calls).not.toContain('hide');
|
vi.advanceTimersByTime(cfg.fadeInMs + cfg.holdMs); // hold elapses -> fade out
|
||||||
|
expect(calls).toContain('hide');
|
||||||
|
vi.advanceTimersByTime(cfg.fadeOutMs + cfg.gapMs + 1); // -> the same message fades back in
|
||||||
|
expect(shown).toEqual(['solo', 'solo']);
|
||||||
r.stop();
|
r.stop();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -85,8 +85,8 @@ export interface Rotator {
|
|||||||
/**
|
/**
|
||||||
* createBannerRotator rotates the scheduled messages: each message fades in, holds
|
* createBannerRotator rotates the scheduled messages: each message fades in, holds
|
||||||
* `holdMs` (an overflowing one scrolls to its right edge and back while under holdMs),
|
* `holdMs` (an overflowing one scrolls to its right edge and back while under holdMs),
|
||||||
* then — when more than one message exists — fades out over `fadeOutMs`, waits `gapMs`,
|
* then fades out over `fadeOutMs`, waits `gapMs`, and fades the next one in. A lone
|
||||||
* and fades the next one in. A single message stays put (a long one keeps scrolling).
|
* message pulses (the same message fades back in) so the cycle keeps its rhythm.
|
||||||
* Reduce-motion is handled by the host: pass zeroed fade timings and an overflowPx that
|
* Reduce-motion is handled by the host: pass zeroed fade timings and an overflowPx that
|
||||||
* returns 0, and messages swap instantly without scrolling.
|
* returns 0, and messages swap instantly without scrolling.
|
||||||
*/
|
*/
|
||||||
@@ -125,8 +125,9 @@ export function createBannerRotator(
|
|||||||
scrollCycle(over);
|
scrollCycle(over);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (sched.total > 1) at(config.holdMs, advance);
|
// Hold, then run the fade cycle. A lone message pulses (fades out, then back in) rather than
|
||||||
// A single fitting message stays put.
|
// sitting frozen, so the banner keeps its rhythm even with a single campaign message.
|
||||||
|
at(config.holdMs, advance);
|
||||||
}
|
}
|
||||||
|
|
||||||
function scrollCycle(over: number) {
|
function scrollCycle(over: number) {
|
||||||
@@ -134,7 +135,7 @@ export function createBannerRotator(
|
|||||||
at(config.edgePauseMs, () => {
|
at(config.edgePauseMs, () => {
|
||||||
host.scrollTo(over, dur);
|
host.scrollTo(over, dur);
|
||||||
at(dur + config.edgePauseMs, () => {
|
at(dur + config.edgePauseMs, () => {
|
||||||
if (sched.total > 1 && Date.now() - cycleStart >= config.holdMs) {
|
if (Date.now() - cycleStart >= config.holdMs) {
|
||||||
advance();
|
advance();
|
||||||
} else {
|
} else {
|
||||||
host.resetScroll();
|
host.resetScroll();
|
||||||
|
|||||||
Reference in New Issue
Block a user