Add onboarding integration test
cgen-6f556f4b240242eda148c08428d795c3
This commit is contained in:
parent
0956ddb03b
commit
bc3b8f9d20
1 changed files with 148 additions and 0 deletions
148
client/lib/onboarding.integration.spec.ts
Normal file
148
client/lib/onboarding.integration.spec.ts
Normal file
|
|
@ -0,0 +1,148 @@
|
||||||
|
import { describe, it, expect, beforeEach, vi } from "vitest";
|
||||||
|
|
||||||
|
const createStorage = () => {
|
||||||
|
const store = new Map<string, string>();
|
||||||
|
const storage: Storage = {
|
||||||
|
get length() {
|
||||||
|
return store.size;
|
||||||
|
},
|
||||||
|
clear: () => {
|
||||||
|
store.clear();
|
||||||
|
},
|
||||||
|
getItem: (key: string) => store.get(key) ?? null,
|
||||||
|
key: (index: number) => Array.from(store.keys())[index] ?? null,
|
||||||
|
removeItem: (key: string) => {
|
||||||
|
store.delete(key);
|
||||||
|
},
|
||||||
|
setItem: (key: string, value: string) => {
|
||||||
|
store.set(key, value);
|
||||||
|
},
|
||||||
|
} as Storage;
|
||||||
|
return storage;
|
||||||
|
};
|
||||||
|
|
||||||
|
vi.stubGlobal("localStorage", createStorage());
|
||||||
|
vi.stubGlobal(
|
||||||
|
"fetch",
|
||||||
|
vi.fn().mockResolvedValue({
|
||||||
|
ok: false,
|
||||||
|
status: 404,
|
||||||
|
text: async () => "",
|
||||||
|
json: async () => ({}),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
vi.mock("@/lib/supabase", () => {
|
||||||
|
const chain = () => ({
|
||||||
|
select: () => chain(),
|
||||||
|
insert: () => ({ data: null, error: null }),
|
||||||
|
update: () => ({ data: null, error: null }),
|
||||||
|
delete: () => ({ error: null }),
|
||||||
|
eq: () => chain(),
|
||||||
|
order: () => chain(),
|
||||||
|
limit: () => chain(),
|
||||||
|
single: () => ({ data: null, error: null }),
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
supabase: {
|
||||||
|
auth: {
|
||||||
|
signInWithPassword: vi.fn(),
|
||||||
|
signInWithOAuth: vi.fn(),
|
||||||
|
linkIdentity: vi.fn(),
|
||||||
|
unlinkIdentity: vi.fn(),
|
||||||
|
signOut: vi.fn(),
|
||||||
|
getUser: async () => ({ data: { user: null }, error: null }),
|
||||||
|
getSession: async () => ({ data: { session: null }, error: null }),
|
||||||
|
onAuthStateChange: () => ({
|
||||||
|
data: {
|
||||||
|
subscription: {
|
||||||
|
unsubscribe: () => {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
from: () => chain(),
|
||||||
|
channel: () => ({
|
||||||
|
on: () => ({}),
|
||||||
|
subscribe: () => ({ unsubscribe: () => {} }),
|
||||||
|
unsubscribe: () => {},
|
||||||
|
}),
|
||||||
|
storage: {
|
||||||
|
from: () => ({
|
||||||
|
upload: async () => ({ data: null, error: null }),
|
||||||
|
getPublicUrl: () => ({ data: { publicUrl: "" } }),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
isSupabaseConfigured: false,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
vi.mock("@/lib/aethex-toast", () => ({
|
||||||
|
aethexToast: {
|
||||||
|
success: vi.fn(),
|
||||||
|
error: vi.fn(),
|
||||||
|
warning: vi.fn(),
|
||||||
|
info: vi.fn(),
|
||||||
|
aethex: vi.fn(),
|
||||||
|
system: vi.fn(),
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
import { mockAuth } from "@/lib/mock-auth";
|
||||||
|
import {
|
||||||
|
aethexUserService,
|
||||||
|
aethexAchievementService,
|
||||||
|
checkProfileComplete,
|
||||||
|
type AethexUserProfile,
|
||||||
|
} from "@/lib/aethex-database-adapter";
|
||||||
|
|
||||||
|
const wait = (ms = 50) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
|
|
||||||
|
describe("onboarding passport flow", () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
localStorage.clear();
|
||||||
|
await mockAuth.signOut();
|
||||||
|
(fetch as unknown as vi.Mock).mockReset();
|
||||||
|
(fetch as unknown as vi.Mock).mockResolvedValue({
|
||||||
|
ok: false,
|
||||||
|
status: 404,
|
||||||
|
text: async () => "",
|
||||||
|
json: async () => ({}),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("persists profile setup, links providers, and awards welcome badge", async () => {
|
||||||
|
const email = `tester+${Date.now()}@example.com`;
|
||||||
|
const password = "Secret123!";
|
||||||
|
|
||||||
|
const authResult = await mockAuth.signInWithPassword(email, password);
|
||||||
|
expect(authResult.error).toBeNull();
|
||||||
|
await wait();
|
||||||
|
|
||||||
|
const user = authResult.data.user;
|
||||||
|
expect(user).toBeTruthy();
|
||||||
|
|
||||||
|
await aethexUserService.updateProfile(user.id, {
|
||||||
|
id: user.id,
|
||||||
|
username: "tester",
|
||||||
|
full_name: "Tester One",
|
||||||
|
user_type: "community_member" as AethexUserProfile["user_type"],
|
||||||
|
experience_level: "intermediate" as AethexUserProfile["experience_level"],
|
||||||
|
bio: "Building awesome experiences",
|
||||||
|
});
|
||||||
|
|
||||||
|
const hydratedProfile = await aethexUserService.getCurrentUser();
|
||||||
|
expect(checkProfileComplete(hydratedProfile)).toBe(true);
|
||||||
|
|
||||||
|
await mockAuth.linkIdentity({ provider: "github" });
|
||||||
|
const refreshedUser = (await mockAuth.getUser()).data.user;
|
||||||
|
expect(refreshedUser?.identities?.some((id: any) => id.provider === "github")).toBe(true);
|
||||||
|
|
||||||
|
await aethexAchievementService.checkAndAwardOnboardingAchievement(user.id);
|
||||||
|
const achievements = await aethexAchievementService.getUserAchievements(user.id);
|
||||||
|
const welcomeBadge = achievements.find((item) => item.name === "Welcome to AeThex");
|
||||||
|
expect(welcomeBadge).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
Loading…
Reference in a new issue