buddy btn sprint: banner-anchor + window.Brief fix lands the last red FT — 16/16 buddy + 12 share/jasmine/my_notes + 818 IT regression — TDD
Two small fixes close out the OK→banner gap:
1. Anchor over h2: base.html drops <div id="id_brief_banner_anchor"></div> right before {% block content %} (after the messages block). note.js's showBanner now prefers the explicit anchor over the first <h2> — keeps the banner in the visible content flow on pages where the first h2 is position:absolute (post.html's rotated navbar header was the immediate motivator; sky.html's rotated h2 is the same shape, so this catches that pre-emptively too).
2. window.Brief explicit assignment: const Brief = (...) at script-tag scope is reachable as a bare name but does NOT auto-attach to window. The buddy panel's OK handler gates banner reveal on `if (window.Brief && data.brief)` — that gate was always false, so Brief.showBanner never fired on share-OK even though the chip + Line append in DOM proved the fetch.then() was running. Explicit window.Brief = Brief; window.Note = Note; in note.js (post-IIFE) closes the gap.
Also picks up the deferred page-object update — functional_tests.post_page.PostPage.share_post_with() now drives the buddy-btn flow (click #id_buddy_btn → type → click #id_buddy_panel .btn.btn-confirm → wait for recipient chip), so legacy SharingTest exercises the new pipeline end-to-end.
NoteSpec.js T10 split into T10a/T10b: a covers the anchor-preferred path, b covers the <h2> fallback.
16/16 buddy FTs green (previously 15/16). 12/12 sharing + Jasmine + my_notes FTs green. 818-test IT sweep green.
Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -44,9 +44,15 @@ const Brief = (() => {
|
|||||||
banner.remove();
|
banner.remove();
|
||||||
});
|
});
|
||||||
|
|
||||||
var h2 = document.querySelector('h2');
|
// Prefer the explicit anchor (set in base.html under the messages
|
||||||
if (h2 && h2.parentNode) {
|
// block, before {% block content %}) — keeps the banner in the
|
||||||
h2.parentNode.insertBefore(banner, h2.nextSibling);
|
// visible content flow on pages where the first <h2> is
|
||||||
|
// position:absolute (e.g. post.html's rotated navbar header).
|
||||||
|
// Falls back to <h2> for pages that pre-date the anchor.
|
||||||
|
var anchor = document.getElementById('id_brief_banner_anchor')
|
||||||
|
|| document.querySelector('h2');
|
||||||
|
if (anchor && anchor.parentNode) {
|
||||||
|
anchor.parentNode.insertBefore(banner, anchor.nextSibling);
|
||||||
} else {
|
} else {
|
||||||
document.body.insertBefore(banner, document.body.firstChild);
|
document.body.insertBefore(banner, document.body.firstChild);
|
||||||
}
|
}
|
||||||
@@ -67,3 +73,9 @@ const Brief = (() => {
|
|||||||
|
|
||||||
// Backwards-compat shim — to be removed once the codebase uniformly uses Brief.
|
// Backwards-compat shim — to be removed once the codebase uniformly uses Brief.
|
||||||
const Note = Brief;
|
const Note = Brief;
|
||||||
|
|
||||||
|
// `const Brief = (...)` at script-tag scope is reachable as a bare name but
|
||||||
|
// is NOT auto-attached to window — explicit assignment so callers that gate
|
||||||
|
// on `if (window.Brief)` (e.g. _buddy_panel.html's OK handler) succeed.
|
||||||
|
window.Brief = Brief;
|
||||||
|
window.Note = Note;
|
||||||
|
|||||||
@@ -40,8 +40,19 @@ class PostPage:
|
|||||||
)
|
)
|
||||||
|
|
||||||
def share_post_with(self, email):
|
def share_post_with(self, email):
|
||||||
self.get_share_box().send_keys(email)
|
# Buddy-btn flow (post-Brief sprint): click bottom-left handshake,
|
||||||
self.get_share_box().send_keys(Keys.ENTER)
|
# type the email in the slide-out, click the .btn-confirm OK, wait
|
||||||
|
# for the recipient chip.
|
||||||
|
buddy_btn = self.test.browser.find_element(By.ID, "id_buddy_btn")
|
||||||
|
buddy_btn.click()
|
||||||
|
recipient = self.test.wait_for(
|
||||||
|
lambda: self.test.browser.find_element(By.ID, "id_recipient")
|
||||||
|
)
|
||||||
|
recipient.send_keys(email)
|
||||||
|
ok = self.test.browser.find_element(
|
||||||
|
By.CSS_SELECTOR, "#id_buddy_panel .btn.btn-confirm"
|
||||||
|
)
|
||||||
|
ok.click()
|
||||||
self.test.wait_for(
|
self.test.wait_for(
|
||||||
lambda: self.test.assertIn(
|
lambda: self.test.assertIn(
|
||||||
email, [item.text for item in self.get_shared_with_list()]
|
email, [item.text for item in self.get_shared_with_list()]
|
||||||
|
|||||||
@@ -118,9 +118,17 @@ describe('Brief.showBanner', () => {
|
|||||||
expect(document.querySelector('.note-banner')).toBeNull();
|
expect(document.querySelector('.note-banner')).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
// ── T10 ── placement after h2 ─────────────────────────────────────────────
|
// ── T10 ── placement: anchor preferred over h2 ───────────────────────────
|
||||||
|
|
||||||
it('T10: banner is inserted immediately after the first h2 in the document', () => {
|
it('T10a: banner is inserted as nextSibling of #id_brief_banner_anchor when present', () => {
|
||||||
|
const anchor = document.createElement('div');
|
||||||
|
anchor.id = 'id_brief_banner_anchor';
|
||||||
|
fixture.appendChild(anchor);
|
||||||
|
Brief.showBanner(SAMPLE_BRIEF);
|
||||||
|
expect(anchor.nextElementSibling.classList.contains('note-banner')).toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('T10b: falls back to inserting after the first h2 when anchor is absent', () => {
|
||||||
Brief.showBanner(SAMPLE_BRIEF);
|
Brief.showBanner(SAMPLE_BRIEF);
|
||||||
const h2 = fixture.querySelector('h2');
|
const h2 = fixture.querySelector('h2');
|
||||||
expect(h2.nextElementSibling.classList.contains('note-banner')).toBeTrue();
|
expect(h2.nextElementSibling.classList.contains('note-banner')).toBeTrue();
|
||||||
|
|||||||
@@ -118,9 +118,17 @@ describe('Brief.showBanner', () => {
|
|||||||
expect(document.querySelector('.note-banner')).toBeNull();
|
expect(document.querySelector('.note-banner')).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
// ── T10 ── placement after h2 ─────────────────────────────────────────────
|
// ── T10 ── placement: anchor preferred over h2 ───────────────────────────
|
||||||
|
|
||||||
it('T10: banner is inserted immediately after the first h2 in the document', () => {
|
it('T10a: banner is inserted as nextSibling of #id_brief_banner_anchor when present', () => {
|
||||||
|
const anchor = document.createElement('div');
|
||||||
|
anchor.id = 'id_brief_banner_anchor';
|
||||||
|
fixture.appendChild(anchor);
|
||||||
|
Brief.showBanner(SAMPLE_BRIEF);
|
||||||
|
expect(anchor.nextElementSibling.classList.contains('note-banner')).toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('T10b: falls back to inserting after the first h2 when anchor is absent', () => {
|
||||||
Brief.showBanner(SAMPLE_BRIEF);
|
Brief.showBanner(SAMPLE_BRIEF);
|
||||||
const h2 = fixture.querySelector('h2');
|
const h2 = fixture.querySelector('h2');
|
||||||
expect(h2.nextElementSibling.classList.contains('note-banner')).toBeTrue();
|
expect(h2.nextElementSibling.classList.contains('note-banner')).toBeTrue();
|
||||||
|
|||||||
@@ -44,6 +44,11 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{# Anchor for Brief.showBanner — banner inserts as nextSibling so #}
|
||||||
|
{# it lands at the top of page content on every base.html-extending #}
|
||||||
|
{# page, regardless of where (or whether) <h2> is positioned. #}
|
||||||
|
<div id="id_brief_banner_anchor"></div>
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user