If you "convert" your code from async/await syntax to Promise syntax, it will look more clear to explain:
describe("current unit", () => {
describe("fetch data", () => {
it("is 5==5", () => { chai.expect(5).to.equal(5); });
getUserData("UserName")
.then(UserData => {
it("email", () => { UserData.email.should.equal("example@g.com"); });
it("phone", () => { UserData.phone.should.equal("+1 (800) 123 4567"); });
});
});
});
As you can see, "fetch data" just includes is 5==5, and email, phone specs are in another scope (in this case the scope is free describe) then these specs will be appear on the top.
getUserData just "waits" 1ms, then you can see email, phone spec, if you increase the value to 100ms (or higher) you will not these specs, because getUserData().then is a synchronous block.
Never call async action in body of describe directly, let use beforeEach, or write it in the body of it.
Use beforeEach:
describe("current unit", () => { // remove async keyword, it does not make sense
let UserData; // define variable
beforeEach(async () => { // async
UserData = await getUserData("UserName"); // init
});
describe("fetch data", () => { // remove async keyword
it("is 5==5", () => { chai.expect(5).to.equal(5); });
it("email", () => { UserData.email.should.equal("example@g.com"); });
it("phone", () => { UserData.phone.should.equal("+1 (800) 123 4567"); });
});
});
current unit
fetch data
✓ is 5==5
✓ email
✓ phone
3 passing (357ms)
Write in it block:
describe("current unit", () => { // remove async keyword, it does not make sense
describe("fetch data", () => { // remove async keyword
it("is 5==5", () => { chai.expect(5).to.equal(5); });
it("should return correct email and phone", async () => { // compile into 1 spec
const UserData = await getUserData("UserName");
UserData.email.should.equal("example@g.com");
UserData.phone.should.equal("+1 (800) 123 4567");
});
});
});
current unit
fetch data
✓ is 5==5
✓ should return correct email and phone (108ms)
2 passing (149ms)