Files
nostr-connect/extension/common.test.js
2026-04-08 11:54:00 +07:00

254 lines
7.6 KiB
JavaScript

import { describe, it, expect, beforeEach, vi } from 'vitest'
import './test-utils'
import {
NO_PERMISSIONS_REQUIRED,
PERMISSION_NAMES,
getPermissionStatus,
updatePermission,
removePermissions,
showNotification,
getPosition
} from './common'
describe('common.js', () => {
beforeEach(() => {
browser.storage.local._reset()
browser.notifications._reset()
vi.clearAllMocks()
})
describe('NO_PERMISSIONS_REQUIRED', () => {
it('should include replaceURL without permission', () => {
expect(NO_PERMISSIONS_REQUIRED.replaceURL).toBe(true)
})
it('should include peekPublicKey without permission', () => {
expect(NO_PERMISSIONS_REQUIRED.peekPublicKey).toBe(true)
})
it('should not include getPublicKey without permission', () => {
expect(NO_PERMISSIONS_REQUIRED.getPublicKey).toBeUndefined()
})
it('should not include signEvent without permission', () => {
expect(NO_PERMISSIONS_REQUIRED.signEvent).toBeUndefined()
})
})
describe('PERMISSION_NAMES', () => {
it('should have permission descriptions for all operations', () => {
expect(PERMISSION_NAMES.getPublicKey).toBe('read your public key')
expect(PERMISSION_NAMES.signEvent).toBe(
'sign events using your private key'
)
expect(PERMISSION_NAMES['nip04.encrypt']).toBe(
'encrypt messages to peers'
)
expect(PERMISSION_NAMES['nip04.decrypt']).toBe(
'decrypt messages from peers'
)
expect(PERMISSION_NAMES['nip44.encrypt']).toBe(
'encrypt messages to peers'
)
expect(PERMISSION_NAMES['nip44.decrypt']).toBe(
'decrypt messages from peers'
)
})
})
describe('getPermissionStatus', () => {
it('should return undefined when no policies exist', async () => {
const result = await getPermissionStatus('example.com', 'getPublicKey')
expect(result).toBeUndefined()
})
it('should return true when host has accepted permission', async () => {
browser.storage.local.set({
policies: {
'example.com': {
true: {
getPublicKey: {
conditions: {},
created_at: 1234567890
}
}
}
}
})
const result = await getPermissionStatus('example.com', 'getPublicKey')
expect(result).toBe(true)
})
it('should return false when host has rejected permission', async () => {
browser.storage.local.set({
policies: {
'example.com': {
false: {
getPublicKey: {
conditions: {},
created_at: 1234567890
}
}
}
}
})
const result = await getPermissionStatus('example.com', 'getPublicKey')
expect(result).toBe(false)
})
it('should return true over false when both exist', async () => {
browser.storage.local.set({
policies: {
'example.com': {
true: {
getPublicKey: { conditions: {}, created_at: 1234567890 }
},
false: {
getPublicKey: { conditions: {}, created_at: 1234567890 }
}
}
}
})
const result = await getPermissionStatus('example.com', 'getPublicKey')
expect(result).toBe(true)
})
it('should check kind conditions for signEvent', async () => {
browser.storage.local.set({
policies: {
'example.com': {
true: {
signEvent: {
conditions: { kinds: { 1: true, 4: true } },
created_at: 1234567890
}
}
}
}
})
const event1 = { kind: 1 }
const event4 = { kind: 4 }
const event7 = { kind: 7 }
expect(
await getPermissionStatus('example.com', 'signEvent', event1)
).toBe(true)
expect(
await getPermissionStatus('example.com', 'signEvent', event4)
).toBe(true)
expect(
await getPermissionStatus('example.com', 'signEvent', event7)
).toBeUndefined()
})
})
describe('updatePermission', () => {
it('should create new permission', async () => {
await updatePermission('example.com', 'getPublicKey', true, {})
const { policies } = await browser.storage.local.get('policies')
expect(policies['example.com'].true.getPublicKey).toBeDefined()
expect(policies['example.com'].true.getPublicKey.conditions).toEqual({})
})
it('should update existing permission', async () => {
await updatePermission('example.com', 'getPublicKey', true, {})
await updatePermission('example.com', 'getPublicKey', true, {})
const { policies } = await browser.storage.local.get('policies')
expect(policies['example.com'].true.getPublicKey).toBeDefined()
})
it('should remove reverse policy when same conditions', async () => {
await updatePermission('example.com', 'getPublicKey', false, {})
await updatePermission('example.com', 'getPublicKey', true, {})
const { policies } = await browser.storage.local.get('policies')
expect(policies['example.com']?.false?.getPublicKey).toBeUndefined()
expect(policies['example.com'].true.getPublicKey).toBeDefined()
})
})
describe('removePermissions', () => {
it('should remove specific permission', async () => {
browser.storage.local.set({
policies: {
'example.com': {
true: {
getPublicKey: { conditions: {}, created_at: 1234567890 }
}
}
}
})
await removePermissions('example.com', true, 'getPublicKey')
const { policies } = await browser.storage.local.get('policies')
expect(policies['example.com'].true.getPublicKey).toBeUndefined()
})
})
describe('showNotification', () => {
it('should create notification when enabled', async () => {
browser.storage.local.set({ notifications: true })
await showNotification('example.com', true, 'getPublicKey', {})
expect(browser.notifications.create).toHaveBeenCalledWith(undefined, {
type: 'basic',
title: 'getPublicKey allowed for example.com',
message: expect.any(String),
iconUrl: 'icons/48x48.png'
})
})
it('should not create notification when disabled', async () => {
browser.storage.local.set({ notifications: false })
await showNotification('example.com', true, 'getPublicKey', {})
expect(browser.notifications.create).not.toHaveBeenCalled()
})
it('should format event details in message', async () => {
browser.storage.local.set({ notifications: true })
await showNotification('example.com', true, 'signEvent', {
event: { kind: 1, content: 'Hello', tags: [] }
})
expect(browser.notifications.create).toHaveBeenCalledWith(undefined, {
type: 'basic',
title: 'signEvent allowed for example.com',
message: expect.stringContaining('1'),
iconUrl: 'icons/48x48.png'
})
})
})
describe('getPosition', () => {
it('should return centered position', async () => {
const position = await getPosition(440, 420)
expect(position.top).toBe(430) // Math.round(100 + (1080 - 420) / 2)
expect(position.left).toBe(840) // Math.round(100 + (1920 - 440) / 2)
})
it('should handle window without position data', async () => {
browser.windows.getLastFocused.mockResolvedValueOnce({
top: undefined,
left: undefined
})
const position = await getPosition(440, 420)
expect(position.top).toBe(0)
expect(position.left).toBe(0)
})
})
})