import { expect, test } from "@playwright/test"; import { login, bobUsername, bobPassword, aliceUsername, apiBaseUrl } from "./helpers"; test("bob sends a DM to alice via /messages page", async ({ browser }) => { const bobContext = await browser.newContext(); const bobPage = await bobContext.newPage(); // Collect console logs for diagnostics const consoleLogs: string[] = []; bobPage.on("console", (msg) => consoleLogs.push(`[${msg.type()}] ${msg.text()}`)); const pageErrors: string[] = []; bobPage.on("pageerror", (err) => pageErrors.push(err.message)); // Login as bob (sets auth cookies + nsec in localStorage) await login(bobPage, bobUsername, bobPassword); // Resolve Alice's pubkey from username const aliceRes = await bobPage.request.get(`${apiBaseUrl}/users/${aliceUsername}`); const alicePubkey = (await aliceRes.json()).pubkey; expect(alicePubkey, "Alice should have a pubkey").toBeTruthy(); // Navigate to /messages selecting alice by pubkey await bobPage.goto(`/messages/${alicePubkey}`); await bobPage.waitForLoadState("domcontentloaded"); // Wait for the message textarea to become visible const textarea = bobPage.locator("#message-contents"); await expect(textarea).toBeVisible({ timeout: 15_000 }); // Type a test message const testMessage = `e2e test message ${Date.now()}`; await textarea.fill(testMessage); // Wait for send button to be enabled (groupId must be set by MLS group creation) const sendButton = bobPage.locator('button[aria-label="Send"]'); const isEnabled = await sendButton.isEnabled({ timeout: 15_000 }).catch(() => false); if (!isEnabled) { // MLS group creation may have failed — check console const errors = consoleLogs.filter((l) => /error|fail/i.test(l)); console.log("[e2e] Console errors:", errors.slice(-10).join("\n ")); console.log("[e2e] Page errors:", pageErrors.join("\n ")); test.skip(true, "MLS group creation failed — send button never enabled"); await bobContext.close(); return; } await sendButton.click(); // Wait for textarea to clear (message sent) await expect(textarea).toHaveValue("", { timeout: 15_000 }); // Verify the message appears in the chat (optimistic UI) const sentBubble = bobPage.locator(".message").filter({ hasText: testMessage }); await expect(sentBubble).toBeVisible({ timeout: 10_000 }); // Verify no error message appeared in the UI const sendError = bobPage.locator(".warning em"); const hasError = await sendError .filter({ hasText: /failed|error/i }) .isVisible({ timeout: 1_000 }) .catch(() => false); if (hasError) { const errorText = await sendError.innerText(); console.log(`[e2e] UI error: ${errorText}`); } expect(hasError, "No send error should appear").toBeFalsy(); // Dump diagnostics const errors = consoleLogs.filter((l) => /error|fail|blocked/i.test(l)); if (errors.length) { console.log("[e2e] Console errors:\n " + errors.join("\n ")); } await bobContext.close(); }); te-5 coinos ui — legacy coinos.io web app (SvelteKit)coinos
aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/LandingHeader.svelte
blob: 35b9de0664bf148d88a0e07b6493e0421e24668b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
<script>
	import { goto } from '$app/navigation';
	import { scroll } from '$lib/utils';
	import { Icon } from '$comp';
	import { t } from '$lib/translations';

	export let howItWorks;
	export let faq;
	export let about;
	export let user;

	let showMobileMenu = false;
	const mobileMenuButtonClick = (section) => {
		showMobileMenu = false;
		scroll(section);
	};
</script>

<header class="w-full lg:w-5/6 py-5 mx-auto fixed md:sticky z-10 top-0 bg-white/90">
	<nav class="block xl:flex flex-wrap justify-between items-center">
		<div class="flex justify-start md:justify-center items-center md:space-x-10">
			<a href="/" class="hidden md:block">
				<Icon icon="logo" style="mb-5 xl:mb-0" />
			</a>
			<Icon icon="logo" style="block md:hidden ml-5 w-48" />
		</div>

		<!-- desktop nav -->
		<div class="hidden space-x-10 md:flex flex-wrap justify-center items-center font-bold">
			<button class="hover:opacity-80" on:click={() => scroll(howItWorks)}
				>{$t('howItWorks.header')}</button
			>
			<button class="hover:opacity-80" on:click={() => scroll(faq)}>{$t('faq.header')}</button>
			<button class="hover:opacity-80" on:click={() => scroll(about)}>{$t('about.header')}</button>
			{#if !user}
				<button
					class="border rounded-full px-6 py-2 font-bold hover:opacity-80"
					on:click={() => goto('/register')}
					>{$t('nav.startInSeconds')}
				</button>
				<button
					class="bg-black text-white border rounded-full px-6 py-2 font-bold hover:opacity-80"
					on:click={() => goto('/login')}
				>
					{$t('nav.signIn')}
				</button>
			{:else}
				<button
					class="border rounded-full px-6 py-2 font-bold"
					on:click={() => goto(`/${user.username}/dashboard`)}
					>{$t('nav.account')}
				</button>
				<button
					class="bg-black text-white border rounded-full px-6 py-2 font-bold"
					on:click={() => goto('/logout')}
				>
					{$t('nav.signOut')}
				</button>
			{/if}
		</div>

		<!-- mobile nav -->
		<button
			class="block md:hidden absolute top-[34.5px] right-10 z"
			on:click={() => (showMobileMenu = !showMobileMenu)}
			><Icon icon={!showMobileMenu ? 'menu' : 'close'} />
		</button>

		<div
			class="container w-full px-10 md:hidden absolute top-0 {showMobileMenu
				? 'right-0'
				: 'right-[-100%]'} transition-all ease-in-out duration-300 h-[100vh] w-full bg-white"
		>
			<div class="space-y-8 mt-24 font-bold text-xl">
				<button on:click={() => mobileMenuButtonClick(howItWorks)} class="block"
					>{$t('howItWorks.header')}</button
				>
				<button on:click={() => mobileMenuButtonClick(faq)} class="block">{$t('faq.header')}</button
				>
				<button on:click={() => mobileMenuButtonClick(about)} class="block"
					>{$t('about.header')}</button
				>
				{#if !user}
					<button
						class="border rounded-full px-6 py-2 font-bold block w-full"
						on:click={() => goto('/register')}
						>{$t('nav.startInSeconds')}
					</button>
					<button
						class="bg-black text-white border rounded-full px-6 py-2 font-bold block w-full"
						on:click={() => goto('/login')}
					>
						{$t('nav.signIn')}
					</button>
				{:else}
					<button
						class="border rounded-full px-6 py-2 font-bold block"
						on:click={() => goto(`/${user.username}/dashboard`)}
						>{$t('nav.account')}
					</button>
					<button
						class="bg-black text-white border rounded-full px-6 py-2 font-bold block"
						on:click={() => goto('/logout')}
					>
						{$t('nav.signOut')}
					</button>
				{/if}
			</div>
		</div>
	</nav>
</header>

<style>
	.z {
		z-index: 100;
	}
</style>