OverviewFilesCommitsIssuesDocsReleasesPeers

pearbrowser-desktop / test / pear-plugins.test.js

113 lines · javascript ref:
import test from 'node:test'
import assert from 'node:assert/strict'
import { createRequire } from 'node:module'

const require = createRequire(import.meta.url)
const { ContentShield } = require('../backend/content-shield.cjs')
const {
  PearPluginRegistry,
  parsePluginManifest,
  PLUGIN_CAPABILITIES
} = require('../backend/pear-plugins.cjs')

const FIXTURE_MANIFEST = {
  name: 'fixture-blocker',
  version: '1.0.0',
  pear: {
    plugin: true,
    capabilities: ['pear.net.filter', 'pear.content.styles', 'pear.content.scripts']
  },
  content: {
    filters: '||plugin-tracker.example^\n##.plugin-ad',
    styles: { matches: ['*'], css: '.plugin-banner { opacity: 0; }' },
    scripts: { matches: ['news.example'], js: 'window.__fixturePlugin = true' }
  }
}

test('parsePluginManifest is fail-closed without pear.plugin', () => {
  assert.equal(parsePluginManifest(null).ok, false)
  assert.equal(parsePluginManifest({ name: 'x' }).ok, false)
  assert.equal(parsePluginManifest({ pear: { plugin: false } }).ok, false)
  const ok = parsePluginManifest(FIXTURE_MANIFEST)
  assert.equal(ok.ok, true)
  assert.equal(ok.name, 'fixture-blocker')
  assert.ok(ok.capabilities.includes('pear.net.filter'))
  assert.ok(PLUGIN_CAPABILITIES.includes('pear.net.filter'))
})

test('registry register + kill-switch drives ContentShield contributions', () => {
  const shield = new ContentShield({ builtinList: false })
  const reg = new PearPluginRegistry({ shield })

  const bad = reg.register({ id: 'not-plugin', manifest: { name: 'nope' } })
  assert.equal(bad.ok, false)
  assert.equal(bad.reason, 'not-a-plugin')

  const result = reg.register({
    id: 'fixture-blocker',
    manifest: FIXTURE_MANIFEST
  })
  assert.equal(result.ok, true)
  assert.equal(result.enabled, true)
  assert.equal(result.applied.filters, true)
  assert.equal(result.applied.styles, true)
  assert.equal(result.applied.scripts, true)

  assert.equal(shield.shouldBlockUrl('https://plugin-tracker.example/pixel').blocked, true)
  assert.match(shield.cosmeticCssFor('x'), /\.plugin-ad/)
  assert.match(shield.pluginStylesFor('x'), /\.plugin-banner/)
  assert.equal(shield.pluginScriptsFor('news.example').length, 1)

  // Kill switch without uninstall
  const killed = reg.setEnabled('fixture-blocker', false)
  assert.equal(killed.ok, true)
  assert.equal(killed.enabled, false)
  assert.equal(shield.shouldBlockUrl('https://plugin-tracker.example/pixel').blocked, false)
  assert.equal(shield.pluginStylesFor('x'), '')
  assert.deepEqual(shield.pluginScriptsFor('news.example'), [])

  // Plugin still listed
  const listed = reg.list()
  assert.equal(listed.length, 1)
  assert.equal(listed[0].enabled, false)

  // Re-enable restores contributions
  reg.setEnabled('fixture-blocker', true)
  assert.equal(shield.shouldBlockUrl('https://plugin-tracker.example/pixel').blocked, true)
  assert.match(shield.pluginStylesFor('x'), /\.plugin-banner/)
})

test('missing capability means contribution has no effect even if payload present', () => {
  const shield = new ContentShield({ builtinList: false })
  const reg = new PearPluginRegistry({ shield })
  const result = reg.register({
    id: 'styles-only',
    manifest: {
      name: 'styles-only',
      pear: { plugin: true, capabilities: ['pear.content.styles'] }
    },
    contribution: {
      filters: '||should-not-block.example^',
      styles: '.ok { color: red }',
      scripts: 'window.x=1'
    }
  })
  assert.equal(result.ok, true)
  assert.equal(result.applied.filters, false)
  assert.equal(result.applied.styles, true)
  assert.equal(result.applied.scripts, false)
  assert.equal(shield.shouldBlockUrl('https://should-not-block.example/').blocked, false)
  assert.match(shield.pluginStylesFor('x'), /\.ok/)
  assert.deepEqual(shield.pluginScriptsFor('x'), [])
})

test('unregister removes plugin and its rules', () => {
  const shield = new ContentShield({ builtinList: false })
  const reg = new PearPluginRegistry({ shield })
  reg.register({ id: 'tmp', manifest: FIXTURE_MANIFEST })
  assert.equal(shield.shouldBlockUrl('https://plugin-tracker.example/x').blocked, true)
  assert.equal(reg.unregister('tmp'), true)
  assert.equal(reg.get('tmp'), null)
  assert.equal(shield.shouldBlockUrl('https://plugin-tracker.example/x').blocked, false)
})