import { mockClient, promise } from "@xmpp/test"; const username = "foo"; const password = "bar"; const credentials = { username, password }; const userAgent = ( software device ); test("No compatible mechanism available", async () => { const { entity } = mockClient({ username, password }); entity.mockInput( FOO , ); const error = await promise(entity, "error"); expect(error instanceof Error).toBe(true); expect(error.message).toBe("SASL: No compatible mechanism available."); }); test("with object credentials", async () => { const { entity } = mockClient({ credentials, userAgent }); entity.mockInput( PLAIN , ); expect(await promise(entity, "send")).toEqual( AGZvbwBiYXI= {userAgent} , ); const jid = "username@localhost/example~Ln8YSSzsyK-b_3-vIFvOJNnE"; expect(entity.jid?.toString()).not.toBe(jid); entity.mockInput( {jid} , ); expect(entity.jid.toString()).toBe(jid); }); test("with function credentials", async () => { const mech = "PLAIN"; const userAgent = ( xmpp.js Sonny's Laptop ); function onAuthenticate(authenticate, mechanisms) { expect(mechanisms).toEqual([mech]); return authenticate(credentials, mech, userAgent); } const { entity } = mockClient({ credentials: onAuthenticate }); entity.mockInput( {mech} , ); expect(await promise(entity, "send")).toEqual( AGZvbwBiYXI= {userAgent} , ); const jid = "username@localhost/example~Ln8YSSzsyK-b_3-vIFvOJNnE"; expect(entity.jid?.toString()).not.toBe(jid); entity.mockInput( {jid} , ); expect(entity.jid.toString()).toBe(jid); }); // https://github.com/xmppjs/xmpp.js/pull/1045#discussion_r1904611099 test("with FAST token only", async () => { const mech = "HT-SHA-256-NONE"; function onAuthenticate(authenticate, mechanisms, fast) { expect(mechanisms).toEqual([]); expect(fast.mechanism).toEqual(mech); return authenticate( { token: { token: "hai", mechanism: fast.mechanism, }, }, null, userAgent, ); } const { entity } = mockClient({ credentials: onAuthenticate }); entity.mockInput( {mech} , ); expect(await promise(entity, "send")).toEqual( bnVsbACNMNimsTBnxS04m8x7wgKjBHdDUL/nXPU4J4vqxqjBIg== {userAgent} , ); const jid = "username@localhost/example~Ln8YSSzsyK-b_3-vIFvOJNnE"; expect(entity.jid?.toString()).not.toBe(jid); entity.mockInput( {jid} , ); expect(entity.jid.toString()).toBe(jid); }); test("failure", async () => { const { entity } = mockClient({ credentials, userAgent }); entity.mockInput( PLAIN , ); expect(await promise(entity, "send")).toEqual( AGZvbwBiYXI= {userAgent} , ); const failure = ( ); entity.mockInput(failure); const error = await promise(entity, "error"); expect(error instanceof Error).toBe(true); expect(error.name).toBe("SASLError"); expect(error.condition).toBe("some-condition"); expect(error.element).toBe(failure); }); test("prefers SCRAM-SHA-1", async () => { const { entity } = mockClient({ credentials }); entity.mockInput( ANONYMOUS SCRAM-SHA-1 PLAIN , ); const result = await promise(entity, "send"); expect(result.attrs.mechanism).toEqual("SCRAM-SHA-1"); }); test("use ANONYMOUS if username and password are not provided", async () => { const { entity } = mockClient(); entity.mockInput( ANONYMOUS PLAIN SCRAM-SHA-1 , ); const result = await promise(entity, "send"); expect(result.attrs.mechanism).toEqual("ANONYMOUS"); });