diff --git a/e2e/auto-lock.test.ts b/e2e/auto-lock.test.ts index 2e49897..4b560f4 100644 --- a/e2e/auto-lock.test.ts +++ b/e2e/auto-lock.test.ts @@ -81,7 +81,7 @@ test('a tab left hidden locks the embedded database on its own', async () => { await otherTab.close(); assert.equal( await page.title(), - `🔒 ${basename(fixture.path)} - Locked - KeePass Web - Local file`, + `${basename(fixture.path)} - Locked - KeePass Web - Local file`, 'and the tab bar shows it locked, without being opened', ); }); diff --git a/e2e/tab-title.test.ts b/e2e/tab-title.test.ts index f97ab6c..62d1f4e 100644 --- a/e2e/tab-title.test.ts +++ b/e2e/tab-title.test.ts @@ -72,7 +72,7 @@ test('the tab names the open database and tracks its lock state', async () => { const iframeFrame = await iframeElement.contentFrame(); assert.ok(iframeFrame, 'the iframe has a content frame'); - await waitForTitle(`🔒 ${filename} - Locked - ${BASE_TITLE}`); + await waitForTitle(`${filename} - Locked - ${BASE_TITLE}`); const lockedIcon = await tabIcon(); assert.notEqual(lockedIcon, pageIcon, 'a held database is not the page at rest'); @@ -82,7 +82,7 @@ test('the tab names the open database and tracks its lock state', async () => { await iframeFrame.click('#unlock-btn'); await iframeFrame.waitForSelector('.entry-table'); - await waitForTitle(`🔓 ${filename} - Unlocked - ${BASE_TITLE}`); + await waitForTitle(`${filename} - Unlocked - ${BASE_TITLE}`); const unlockedIcon = await tabIcon(); assert.notEqual(unlockedIcon, lockedIcon, 'and the two states do not share an icon'); diff --git a/pages/shared/logic.ts b/pages/shared/logic.ts index 4ca216c..188a4ef 100644 --- a/pages/shared/logic.ts +++ b/pages/shared/logic.ts @@ -13,11 +13,12 @@ const LOCKED_ICON = const UNLOCKED_ICON = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Crect width='16' height='16' rx='3.4' fill='%238a5a1e'/%3E%3Crect x='3.7' y='4.4' width='8.6' height='1.9' rx='.95' fill='%23fff'/%3E%3Crect x='3.7' y='7.05' width='8.6' height='1.9' rx='.95' fill='%23fff'/%3E%3Crect x='3.7' y='9.7' width='8.6' height='1.9' rx='.95' fill='%23fff'/%3E%3C/svg%3E"; -/** The tab's name. It spells the state out as well as showing it, because 🔒 -and 🔓 are as hard to tell apart in a title as they are in a tab (#73). */ +/** The tab's name. The state is named in words and not repeated as a glyph: +the icon beside it already carries it as a picture, and the padlock emoji says +the same thing a second time in the form that reads least well (#73). */ export function tabTitle(baseTitle: string, filename: string, locked: boolean): string { if (!filename) return baseTitle; - return `${locked ? '🔒' : '🔓'} ${filename} - ${locked ? 'Locked' : 'Unlocked'} - ${baseTitle}`; + return `${filename} - ${locked ? 'Locked' : 'Unlocked'} - ${baseTitle}`; } /** Name the tab and mark it with the database's state; no filename means no diff --git a/pages/tests/0x67-page.test.ts b/pages/tests/0x67-page.test.ts index 11fd0f5..54f4e42 100644 --- a/pages/tests/0x67-page.test.ts +++ b/pages/tests/0x67-page.test.ts @@ -315,7 +315,7 @@ test('0x67 app', async (t) => { await waitFor(() => q('#master-password') !== null); assert.equal(q('#db-filename').textContent, 'dropped.kdbx'); - assert.equal(dom.window.document.title, '🔒 dropped.kdbx - Locked - KeePass Web'); + assert.equal(dom.window.document.title, 'dropped.kdbx - Locked - KeePass Web'); }); await t.test('unlock screen "back" returns to upload and clears the file', () => { @@ -439,7 +439,7 @@ test('0x67 app', async (t) => { await waitFor(() => dom.window.document.body.classList.contains('app-mode')); assert.ok(q('#group-tree').querySelector('.group-btn')); - assert.equal(dom.window.document.title, '🔓 real.kdbx - Unlocked - KeePass Web'); + assert.equal(dom.window.document.title, 'real.kdbx - Unlocked - KeePass Web'); // Table view is the default. assert.equal(root().querySelectorAll('.entry-table').length, 1); // Switch to tile view, which the rest of this suite's entry-list @@ -1636,7 +1636,7 @@ test('0x67 app', async (t) => { assert.equal(lockDlg.open, false); await waitFor(() => q('#master-password') !== null); assert.equal(q('#db-filename').textContent, 'real.kdbx'); - assert.equal(dom.window.document.title, '🔒 real.kdbx - Locked - KeePass Web'); + assert.equal(dom.window.document.title, 'real.kdbx - Locked - KeePass Web'); // A wrong password on the relocked (freshly re-encrypted) state is // still rejected — locking doesn't weaken the credential check. @@ -1889,7 +1889,7 @@ test('a tab left hidden locks itself, and coming back in time calls it off', asy assert.equal(q('#db-filename').textContent, 'auto-lock.kdbx'); assert.equal( dom.window.document.title, - '🔒 auto-lock.kdbx - Locked - KeePass Web', + 'auto-lock.kdbx - Locked - KeePass Web', 'the tab bar says so without being opened', ); diff --git a/pages/tests/cloud-google-drive-page.test.ts b/pages/tests/cloud-google-drive-page.test.ts index 539140e..d997ca6 100644 --- a/pages/tests/cloud-google-drive-page.test.ts +++ b/pages/tests/cloud-google-drive-page.test.ts @@ -392,10 +392,10 @@ test('Google Drive connector', async (t) => { await t.test('kw-title names the open database in the tab', () => { sendMessage({ type: 'kw-title', filename: 'vault.kdbx', locked: true }, { source: frameWin }); - assert.equal(doc.title, '🔒 vault.kdbx - Locked - KeePass Web - Google Drive'); + assert.equal(doc.title, 'vault.kdbx - Locked - KeePass Web - Google Drive'); sendMessage({ type: 'kw-title', filename: 'vault.kdbx', locked: false }, { source: frameWin }); - assert.equal(doc.title, '🔓 vault.kdbx - Unlocked - KeePass Web - Google Drive'); + assert.equal(doc.title, 'vault.kdbx - Unlocked - KeePass Web - Google Drive'); // An app with nothing open reports no filename, leaving this page's own title. sendMessage({ type: 'kw-title', filename: '', locked: true }, { source: frameWin }); diff --git a/pages/tests/local-page.test.ts b/pages/tests/local-page.test.ts index 7c2766a..c7e7f23 100644 --- a/pages/tests/local-page.test.ts +++ b/pages/tests/local-page.test.ts @@ -218,10 +218,10 @@ test('local file connector', async (t) => { await t.test('kw-title names the open database in the tab', () => { sendMessage({ type: 'kw-title', filename: 'vault.kdbx', locked: true }, { source: frameWin }); - assert.equal(doc.title, '🔒 vault.kdbx - Locked - KeePass Web - Local file'); + assert.equal(doc.title, 'vault.kdbx - Locked - KeePass Web - Local file'); sendMessage({ type: 'kw-title', filename: 'vault.kdbx', locked: false }, { source: frameWin }); - assert.equal(doc.title, '🔓 vault.kdbx - Unlocked - KeePass Web - Local file'); + assert.equal(doc.title, 'vault.kdbx - Unlocked - KeePass Web - Local file'); // An app with nothing open reports no filename, leaving this page's own title. sendMessage({ type: 'kw-title', filename: '', locked: true }, { source: frameWin }); diff --git a/pages/tests/shared-logic.test.ts b/pages/tests/shared-logic.test.ts index 56ffa8f..53ff2c0 100644 --- a/pages/tests/shared-logic.test.ts +++ b/pages/tests/shared-logic.test.ts @@ -24,11 +24,15 @@ const iconHref = (doc: Document): string => doc.querySelector('link[rel="icon"]')?.getAttribute('href') ?? ''; test('the title names the database and spells its state out', () => { - assert.equal(tabTitle('KeePass Web', 'vault.kdbx', true), '🔒 vault.kdbx - Locked - KeePass Web'); - assert.equal( - tabTitle('KeePass Web', 'vault.kdbx', false), - '🔓 vault.kdbx - Unlocked - KeePass Web', - ); + assert.equal(tabTitle('KeePass Web', 'vault.kdbx', true), 'vault.kdbx - Locked - KeePass Web'); + assert.equal(tabTitle('KeePass Web', 'vault.kdbx', false), 'vault.kdbx - Unlocked - KeePass Web'); +}); + +test('the title never repeats the state as a padlock glyph', () => { + for (const locked of [true, false]) { + const title = tabTitle('KeePass Web', 'vault.kdbx', locked); + assert.ok(!title.includes('\u{1F512}') && !title.includes('\u{1F513}'), title); + } }); test('no database means the page keeps its own name', () => { @@ -41,12 +45,12 @@ test('the icon tracks the lock state and hands the page its own back', () => { applyTabState(doc, 'Base', 'vault.kdbx', true); const locked = iconHref(doc); - assert.equal(doc.title, '🔒 vault.kdbx - Locked - Base'); + assert.equal(doc.title, 'vault.kdbx - Locked - Base'); assert.notEqual(locked, PAGE_ICON, 'a held database is not the page at rest'); applyTabState(doc, 'Base', 'vault.kdbx', false); const unlocked = iconHref(doc); - assert.equal(doc.title, '🔓 vault.kdbx - Unlocked - Base'); + assert.equal(doc.title, 'vault.kdbx - Unlocked - Base'); assert.notEqual(unlocked, locked, 'and the two states are not the same icon'); // Hue and glyph are what carry at 16px, so the two must differ in both. @@ -72,6 +76,6 @@ test('a page whose icon link carries no href still gets one back', () => { test('a page with no icon link is titled anyway, not crashed', () => { const doc = pageDocument(false); applyTabState(doc, 'Base', 'vault.kdbx', true); - assert.equal(doc.title, '🔒 vault.kdbx - Locked - Base'); + assert.equal(doc.title, 'vault.kdbx - Locked - Base'); assert.equal(doc.querySelector('link[rel="icon"]'), null); });