Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion e2e/auto-lock.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
);
});
4 changes: 2 additions & 2 deletions e2e/tab-title.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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');

Expand All @@ -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');

Expand Down
7 changes: 4 additions & 3 deletions pages/shared/logic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 4 additions & 4 deletions pages/tests/0x67-page.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ test('0x67 app', async (t) => {

await waitFor(() => q('#master-password') !== null);
assert.equal(q<HTMLElement>('#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', () => {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -1636,7 +1636,7 @@ test('0x67 app', async (t) => {
assert.equal(lockDlg.open, false);
await waitFor(() => q('#master-password') !== null);
assert.equal(q<HTMLElement>('#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.
Expand Down Expand Up @@ -1889,7 +1889,7 @@ test('a tab left hidden locks itself, and coming back in time calls it off', asy
assert.equal(q<HTMLElement>('#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',
);

Expand Down
4 changes: 2 additions & 2 deletions pages/tests/cloud-google-drive-page.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 });
Expand Down
4 changes: 2 additions & 2 deletions pages/tests/local-page.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 });
Expand Down
20 changes: 12 additions & 8 deletions pages/tests/shared-logic.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand All @@ -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.
Expand All @@ -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);
});