import { mockClient, promise } from "@xmpp/test";
import parse from "@xmpp/xml/lib/parse.js";
const username = "foo";
const password = "bar";
const credentials = { username, password };
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 });
entity.restart = () => {
entity.emit("open");
return Promise.resolve();
};
entity.mockInput(
PLAIN
,
);
expect(await promise(entity, "send")).toEqual(
AGZvbwBiYXI=
,
);
entity.mockInput();
});
test("with function credentials", async () => {
expect.assertions(2);
const mech = "PLAIN";
let promise_authenticate;
async function onAuthenticate(authenticate, mechanisms) {
expect(mechanisms).toEqual([mech]);
await authenticate(credentials, mech);
}
const { entity } = mockClient({ credentials: onAuthenticate });
entity.restart = () => {
entity.emit("open");
return Promise.resolve();
};
entity.mockInput(
{mech}
,
);
expect(await promise(entity, "send")).toEqual(
AGZvbwBiYXI=
,
);
entity.mockInput();
await promise_authenticate;
});
test("Mechanism not found", async () => {
const { entity } = mockClient({
async credentials(authenticate, _mechanisms) {
await authenticate({ username, password }, "foo");
},
});
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 function credentials that rejects", (done) => {
expect.assertions(1);
const mech = "PLAIN";
const error = {};
async function onAuthenticate() {
throw error;
}
const { entity } = mockClient({ credentials: onAuthenticate });
entity.entity.mockInput(
{mech}
,
);
entity.on("error", (err) => {
expect(err).toBe(error);
done();
});
});
test("failure", async () => {
const { entity } = mockClient({ credentials });
entity.mockInput(
PLAIN
,
);
expect(await promise(entity, "send")).toEqual(
AGZvbwBiYXI=
,
);
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(
PLAIN
SCRAM-SHA-1
ANONYMOUS
,
);
const result = await promise(entity, "send");
expect(result.attrs.mechanism).toEqual("ANONYMOUS");
});
test("with whitespaces", async () => {
const { entity } = mockClient();
entity.mockInput(
parse(
`
ANONYMOUS
PLAIN
SCRAM-SHA-1
`.trim(),
),
);
const result = await promise(entity, "send");
expect(result.attrs.mechanism).toEqual("ANONYMOUS");
});