@nostr-dev-kit/ndk
Version:
NDK - Nostr Development Kit
243 lines (204 loc) • 8.94 kB
text/typescript
import { EventGenerator } from "../../test";
import { beforeEach, describe, expect, it, vi } from "vitest";
import type { NDKEvent } from "../events/index.js";
import { NDK } from "../ndk/index.js";
import { NDKSubscription } from "../subscription/index.js";
import { NDKUser, type NDKUserParams, type ProfilePointer } from "./index.js";
import * as Nip05 from "./nip05.js";
describe("NDKUser", () => {
let ndk: NDK;
beforeEach(() => {
vi.clearAllMocks();
ndk = new NDK();
EventGenerator.setNDK(ndk);
});
describe("constructor", () => {
it("sets npub from provided npub", () => {
const opts: NDKUserParams = {
npub: "npub1l2vyh47mk2p0qlsku7hg0vn29faehy9hy34ygaclpn66ukqp3afqutajft",
};
const user = new NDKUser(opts);
expect(user.npub).toEqual("npub1l2vyh47mk2p0qlsku7hg0vn29faehy9hy34ygaclpn66ukqp3afqutajft");
});
it("sets npub from provided hexpubkey", () => {
const opts: NDKUserParams = {
pubkey: "fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52",
};
const user = new NDKUser(opts);
expect(user.npub).toEqual("npub1l2vyh47mk2p0qlsku7hg0vn29faehy9hy34ygaclpn66ukqp3afqutajft");
});
it("sets relayUrls from provided relayUrls", () => {
const opts: NDKUserParams = {
relayUrls: ["url1", "url2"],
};
const user = new NDKUser(opts);
expect(user.relayUrls).toEqual(["url1", "url2"]);
});
it("sets pubkey and relayUrls from provided nprofile", () => {
const opts: NDKUserParams = {
nprofile:
"nprofile1qqs04xzt6ldm9qhs0ctw0t58kf4z57umjzmjg6jywu0seadwtqqc75spr9mhxue69uhhq7tjv9kkjepwve5kzar2v9nzucm0d5qscamnwvaz7tmxxaazu6t0f6uyq5",
};
const user = new NDKUser(opts);
expect(user.pubkey).toEqual("fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52");
expect(user.relayUrls).toEqual(["wss://pyramid.fiatjaf.com", "wss://f7z.io"]);
});
});
describe("pubkey", () => {
it("returns the decoded pubkey", () => {
const user = new NDKUser({
npub: "npub1l2vyh47mk2p0qlsku7hg0vn29faehy9hy34ygaclpn66ukqp3afqutajft",
});
const pubkey = user.pubkey;
expect(pubkey).toEqual("fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52");
});
});
describe("fetchProfile", () => {
let newEvent: NDKEvent;
let oldEvent: NDKEvent;
let user: NDKUser;
let pubkey: string;
beforeEach(() => {
user = new NDKUser({
npub: "npub1l2vyh47mk2p0qlsku7hg0vn29faehy9hy34ygaclpn66ukqp3afqutajft",
});
user.ndk = ndk;
pubkey = user.pubkey;
});
it("Returns updated fields", async () => {
// Use EventGenerator to create profile events
newEvent = EventGenerator.createEvent(
0,
JSON.stringify({
displayName: "JeffG",
name: "Jeff",
image: "https://image.url",
banner: "https://banner.url",
bio: "Some bio info",
nip05: "_@jeffg.fyi",
lud06: "lud06value",
lud16: "lud16value",
about: "About jeff",
}),
pubkey,
);
newEvent.created_at = Math.floor(Date.now() / 1000) - 3600;
oldEvent = EventGenerator.createEvent(
0,
JSON.stringify({
displayName: "JeffG_OLD",
name: "Jeff_OLD",
image: "https://image.url.old",
banner: "https://banner.url.old",
bio: "Some OLD bio info",
nip05: "OLD@jeffg.fyi",
lud06: "lud06value OLD",
lud16: "lud16value OLD",
about: "About jeff OLD",
}),
pubkey,
);
oldEvent.created_at = Math.floor(Date.now() / 1000) - 7200;
ndk.fetchEvent = vi.fn().mockResolvedValue(newEvent);
await user.fetchProfile();
expect(user.profile?.displayName).toEqual("JeffG");
expect(user.profile?.name).toEqual("Jeff");
expect(user.profile?.image).toEqual("https://image.url");
expect(user.profile?.banner).toEqual("https://banner.url");
expect(user.profile?.bio).toEqual("Some bio info");
expect(user.profile?.nip05).toEqual("_@jeffg.fyi");
expect(user.profile?.lud06).toEqual("lud06value");
expect(user.profile?.lud16).toEqual("lud16value");
expect(user.profile?.about).toEqual("About jeff");
});
// "displayName" is ignored, we only look at the "display_name" field in the user profile
it("Display name is set properly", async () => {
newEvent = EventGenerator.createEvent(
0,
JSON.stringify({
displayName: "JeffG",
display_name: "James",
}),
pubkey,
);
newEvent.created_at = Math.floor(Date.now() / 1000) - 3600;
oldEvent = EventGenerator.createEvent(
0,
JSON.stringify({
displayName: "Bob",
}),
pubkey,
);
oldEvent.created_at = Math.floor(Date.now() / 1000) - 7200;
ndk.fetchEvent = vi.fn().mockResolvedValue(newEvent);
await user.fetchProfile();
expect(user.profile?.displayName).toEqual("James");
});
// Both "image" and "picture" are set to the "image" field in the user profile
it("Image is set properly", async () => {
newEvent = EventGenerator.createEvent(
0,
JSON.stringify({
picture: "https://set-from-picture-field.url",
}),
pubkey,
);
newEvent.created_at = Math.floor(Date.now() / 1000) - 3600;
oldEvent = EventGenerator.createEvent(
0,
JSON.stringify({
image: "https://set-from-image-field.url",
}),
pubkey,
);
oldEvent.created_at = Math.floor(Date.now() / 1000) - 7200;
ndk.fetchEvent = vi.fn().mockResolvedValue(newEvent);
await user.fetchProfile();
expect(user.profile?.image).toEqual("https://set-from-picture-field.url");
});
it("Allows for arbitrary values to be set on user profiles", async () => {
newEvent = EventGenerator.createEvent(
0,
JSON.stringify({
customField: "custom NEW",
}),
pubkey,
);
newEvent.created_at = Math.floor(Date.now() / 1000) - 3600;
oldEvent = EventGenerator.createEvent(
0,
JSON.stringify({
customField: "custom OLD",
}),
pubkey,
);
oldEvent.created_at = Math.floor(Date.now() / 1000) - 7200;
ndk.fetchEvent = vi.fn().mockResolvedValue(newEvent);
await user.fetchProfile();
expect(user.profile?.customField).toEqual("custom NEW");
});
});
describe("validateNip05", () => {
it("validates the NIP-05 for users", async () => {
const user = ndk.getUser({
pubkey: "1739d937dc8c0c7370aa27585938c119e25c41f6c441a5d34c6d38503e3136ef",
});
// Valid NIP-05
const validNip05 = "_@jeffg.fyi";
vi.spyOn(Nip05, "getNip05For").mockResolvedValue({
pubkey: "1739d937dc8c0c7370aa27585938c119e25c41f6c441a5d34c6d38503e3136ef",
} as ProfilePointer);
expect(await user.validateNip05(validNip05)).toEqual(true);
// Invalid NIP-05
const invalidNip05 = "_@f7z.io";
vi.spyOn(Nip05, "getNip05For").mockResolvedValue({
pubkey: "fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52",
} as ProfilePointer);
expect(await user.validateNip05(invalidNip05)).toEqual(false);
// Random NIP-05
const randomNip05 = "bobby@globalhypermeganet.com";
vi.spyOn(Nip05, "getNip05For").mockResolvedValue(null);
expect(await user.validateNip05(randomNip05)).toEqual(null);
});
});
});