From 3ffe4d5b19dd3a1be9c458bd62cb1a4f8e5f8b10 Mon Sep 17 00:00:00 2001 From: ennmichael Date: Sun, 9 Apr 2023 19:12:49 +0200 Subject: [PATCH] tests --- packages/nostr/package.json | 5 +- packages/nostr/src/event/index.ts | 14 ++++- packages/nostr/src/nostr-object.ts | 1 + packages/nostr/test/browser/index.html | 16 +++++ packages/nostr/test/browser/server.ts | 2 +- packages/nostr/test/setup.ts | 63 +++++++++++++++++-- .../{test.dm.ts => test.direct-message.ts} | 2 +- 7 files changed, 94 insertions(+), 9 deletions(-) rename packages/nostr/test/{test.dm.ts => test.direct-message.ts} (99%) diff --git a/packages/nostr/package.json b/packages/nostr/package.json index fa27def8..e31e2d21 100644 --- a/packages/nostr/package.json +++ b/packages/nostr/package.json @@ -4,8 +4,9 @@ "main": "dist/lib.js", "types": "dist/src/index.d.ts", "scripts": { - "build": "webpack", - "watch": "webpack -w", + "build": "rm -rf dist && webpack", + "watch": "rm -rf dist && webpack -w", + "clean": "rm -rf dist", "test": "ts-mocha --type-check -j 1 --timeout 5s test/test.*.ts", "test-browser": "ts-node test/browser/server.ts", "lint": "eslint ." diff --git a/packages/nostr/src/event/index.ts b/packages/nostr/src/event/index.ts index cb0aa5d4..8a3d853f 100644 --- a/packages/nostr/src/event/index.ts +++ b/packages/nostr/src/event/index.ts @@ -139,7 +139,19 @@ export async function signEvent( if (typeof window === "undefined" || window.nostr === undefined) { throw new NostrError("no private key provided") } - return await window.nostr.signEvent(event) + // Extensions like nos2x expect to receive only the event data, without any of the methods. + const methods: { [key: string]: unknown } = {} + for (const [key, value] of Object.entries(event)) { + if (typeof value === "function") { + methods[key] = value + delete event[key] + } + } + const signed = await window.nostr.signEvent(event) + return { + ...signed, + ...methods, + } } } diff --git a/packages/nostr/src/nostr-object.ts b/packages/nostr/src/nostr-object.ts index 3f837f70..96818d86 100644 --- a/packages/nostr/src/nostr-object.ts +++ b/packages/nostr/src/nostr-object.ts @@ -7,6 +7,7 @@ declare global { getPublicKey: () => Promise signEvent: (event: Unsigned) => Promise + // TODO It's unclear to me if I should use this anywhere. getRelays?: () => Promise<{ [url: string]: { read: boolean; write: boolean } }> diff --git a/packages/nostr/test/browser/index.html b/packages/nostr/test/browser/index.html index 3df15a3d..2a2700c1 100644 --- a/packages/nostr/test/browser/index.html +++ b/packages/nostr/test/browser/index.html @@ -7,6 +7,21 @@ +
+ +
+ + +
@@ -15,6 +30,7 @@ mocha.setup({ ui: "bdd", timeout: "5s", + global: ["nostr"], }) mocha.checkLeaks() diff --git a/packages/nostr/test/browser/server.ts b/packages/nostr/test/browser/server.ts index b4607a1d..a0bfdab6 100644 --- a/packages/nostr/test/browser/server.ts +++ b/packages/nostr/test/browser/server.ts @@ -10,7 +10,7 @@ const port = 33543 const app = express() app.use("/", (req: express.Request, res: express.Response) => { - if (req.path === "/") { + if (req.path === "/" || req.path === "/nostr-object") { const index = fs.readFileSync(path.join(__dirname, "index.html"), { encoding: "utf8", }) diff --git a/packages/nostr/test/setup.ts b/packages/nostr/test/setup.ts index d34324d2..95542319 100644 --- a/packages/nostr/test/setup.ts +++ b/packages/nostr/test/setup.ts @@ -1,11 +1,21 @@ +import "../src/nostr-object" import { Nostr } from "../src/client" import { Timestamp, unixTimestamp } from "../src/common" +import { + aesDecryptBase64, + aesEncryptBase64, + parsePrivateKey, + parsePublicKey, + PublicKey, +} from "../src/crypto" +import { RawEvent } from "../src" +import { signEvent, Unsigned } from "../src/event" export const relayUrl = new URL("ws://localhost:12648") export interface Setup { publisher: Nostr - publisherSecret: string + publisherSecret?: string publisherPubkey: string subscriber: Nostr subscriberSecret: string @@ -25,6 +35,50 @@ export async function setup( ) { try { await restartRelay() + + const publisherPubkey = + "npub1he978sxy7tgc7yfp2zra05v045kfuqnfl3gwr82jd00mzxjj9fjqzw2dg7" + const publisherSecret = + "nsec15fnff4uxlgyu79ua3l7327w0wstrd6x565cx6zze78zgkktmr8vs90j363" + + // Set up the global window.nostr object for the publisher. + if (typeof window !== "undefined") { + if (window.location.pathname === "/nostr-object") { + window.nostr = { + getPublicKey: () => Promise.resolve(parsePublicKey(publisherPubkey)), + signEvent: (event: Unsigned) => + signEvent(event, publisherSecret), + + getRelays: () => Promise.resolve({}), + + nip04: { + encrypt: async (pubkey: PublicKey, plaintext: string) => { + const { data, iv } = await aesEncryptBase64( + parsePrivateKey(publisherSecret), + pubkey, + plaintext + ) + return `${data}?iv=${iv}` + }, + decrypt: async (pubkey: PublicKey, ciphertext: string) => { + const [data, iv] = ciphertext.split("?iv=") + return await aesDecryptBase64( + pubkey, + parsePrivateKey(publisherSecret), + { + data, + iv, + } + ) + }, + }, + } + } else { + // Otherwise, disable the user's nostr extension if they have one. + window.nostr = undefined + } + } + const publisher = new Nostr() const subscriber = new Nostr() @@ -44,9 +98,10 @@ export async function setup( const result = test({ publisher, publisherSecret: - "nsec15fnff4uxlgyu79ua3l7327w0wstrd6x565cx6zze78zgkktmr8vs90j363", - publisherPubkey: - "npub1he978sxy7tgc7yfp2zra05v045kfuqnfl3gwr82jd00mzxjj9fjqzw2dg7", + typeof window === "undefined" || window.nostr === undefined + ? publisherSecret + : undefined, + publisherPubkey, subscriber, subscriberSecret: "nsec1fxvlyqn3rugvxwaz6dr5h8jcfn0fe0lxyp7pl4mgntxfzqr7dmgst7z9ps", diff --git a/packages/nostr/test/test.dm.ts b/packages/nostr/test/test.direct-message.ts similarity index 99% rename from packages/nostr/test/test.dm.ts rename to packages/nostr/test/test.direct-message.ts index 14c69fd5..de1c85ad 100644 --- a/packages/nostr/test/test.dm.ts +++ b/packages/nostr/test/test.direct-message.ts @@ -4,7 +4,7 @@ import { parsePublicKey } from "../src/crypto" import { setup } from "./setup" import { createDirectMessage } from "../src/event/direct-message" -describe("dm", () => { +describe("direct-message", () => { const message = "for your eyes only" // Test that the intended recipient can receive and decrypt the direct message.