diff --git a/cfg/cspell-frontend-dictionary.txt b/cfg/cspell-frontend-dictionary.txt index c814a2cc87..55b0795a2e 100644 --- a/cfg/cspell-frontend-dictionary.txt +++ b/cfg/cspell-frontend-dictionary.txt @@ -50,3 +50,4 @@ localstorage vpnapi ctrls dockerenv +testid diff --git a/src/docker/compose.yaml b/src/docker/compose.yaml index fa7e7fe6d0..bd7cd36a3f 100644 --- a/src/docker/compose.yaml +++ b/src/docker/compose.yaml @@ -100,13 +100,13 @@ services: dockerfile: 'src/docker/frontend/Dockerfile' args: HASH_SEED: '${HASH_SEED}' - EMOJICOIN_INDEXER_URL: 'http://localhost:3000' + EMOJICOIN_INDEXER_URL: 'http://host.docker.internal:3000' NEXT_PUBLIC_APTOS_NETWORK: '${APTOS_NETWORK}' NEXT_PUBLIC_INTEGRATOR_ADDRESS: '${EMOJICOIN_INTEGRATOR_ADDRESS}' NEXT_PUBLIC_INTEGRATOR_FEE_RATE_BPS: '${FEE_RATE_BPS}' NEXT_PUBLIC_IS_ALLOWLIST_ENABLED: 'false' NEXT_PUBLIC_MODULE_ADDRESS: '${EMOJICOIN_MODULE_ADDRESS}' - NEXT_PUBLIC_BROKER_URL: 'ws://localhost:${BROKER_PORT}' + NEXT_PUBLIC_BROKER_URL: 'ws://host.docker.internal:${BROKER_PORT}' NEXT_PUBLIC_REWARDS_MODULE_ADDRESS: >- ${EMOJICOIN_REWARDS_MODULE_ADDRESS} REVALIDATION_TIME: '${REVALIDATION_TIME}' @@ -116,18 +116,18 @@ services: - 'frontend' environment: HASH_SEED: '${HASH_SEED}' - EMOJICOIN_INDEXER_URL: 'http://localhost:3000' + EMOJICOIN_INDEXER_URL: 'http://host.docker.internal:3000' NEXT_PUBLIC_APTOS_NETWORK: '${APTOS_NETWORK}' NEXT_PUBLIC_INTEGRATOR_ADDRESS: '${EMOJICOIN_INTEGRATOR_ADDRESS}' NEXT_PUBLIC_INTEGRATOR_FEE_RATE_BPS: '${FEE_RATE_BPS}' NEXT_PUBLIC_IS_ALLOWLIST_ENABLED: 'false' NEXT_PUBLIC_MODULE_ADDRESS: '${EMOJICOIN_MODULE_ADDRESS}' - NEXT_PUBLIC_BROKER_URL: 'ws://localhost:${BROKER_PORT}' + NEXT_PUBLIC_BROKER_URL: 'ws://host.docker.internal:${BROKER_PORT}' NEXT_PUBLIC_REWARDS_MODULE_ADDRESS: '${EMOJICOIN_REWARDS_MODULE_ADDRESS}' REVALIDATION_TIME: '${REVALIDATION_TIME}' healthcheck: test: 'curl -f http://localhost:3001/ || exit 1' - interval: '2m' + interval: '30s' timeout: '1s' retries: '1' start_period: '20s' diff --git a/src/docker/utils/prune.sh b/src/docker/utils/prune.sh index 81f93b2845..133a10c59c 100755 --- a/src/docker/utils/prune.sh +++ b/src/docker/utils/prune.sh @@ -137,7 +137,7 @@ if [ -n "$reset_localnet" ]; then # Bind-mounting the parent of `.aptos` gives the container the right to # delete it. docker run --rm -v "$docker_dir/localnet:/pwd" busybox rm -rf /pwd/.aptos - docker compose -f compose.local.yaml down --volumes + docker compose -f compose.local.yaml --profile frontend down --volumes else - docker compose -f compose.local.yaml down + docker compose -f compose.local.yaml --profile frontend down fi diff --git a/src/typescript/ci.env b/src/typescript/ci.env index 6fc7c9a204..3d3bff6687 100644 --- a/src/typescript/ci.env +++ b/src/typescript/ci.env @@ -1,3 +1,4 @@ +NODE_ENV="test" APTOS_NETWORK="local" NEXT_PUBLIC_APTOS_NETWORK="local" NEXT_PUBLIC_BROKER_URL="ws://localhost:3009" diff --git a/src/typescript/frontend/.eslintrc.js b/src/typescript/frontend/.eslintrc.js index 335c5f7436..d7d8b4aeab 100644 --- a/src/typescript/frontend/.eslintrc.js +++ b/src/typescript/frontend/.eslintrc.js @@ -25,7 +25,6 @@ module.exports = { "playwright.config.ts", "postcss.config.js", "tailwind.config.js", - "example.spec.ts", ], parser: "@typescript-eslint/parser", parserOptions: { diff --git a/src/typescript/frontend/package.json b/src/typescript/frontend/package.json index afaef7fb9f..ab91ee419b 100644 --- a/src/typescript/frontend/package.json +++ b/src/typescript/frontend/package.json @@ -35,6 +35,7 @@ "axios": ">=0.28.0", "big.js": "^6.2.2", "clsx": "^2.1.1", + "dotenv": "^16.4.5", "emoji-mart": "https://github.com/econia-labs/emoji-mart/raw/emojicoin-dot-fun/packages/emoji-mart/emoji-mart-v5.6.0.tgz", "emoji-regex": "^10.4.0", "framer-motion": "^11.11.4", diff --git a/src/typescript/frontend/playwright.config.ts b/src/typescript/frontend/playwright.config.ts index ccfcab6174..ce826012b1 100644 --- a/src/typescript/frontend/playwright.config.ts +++ b/src/typescript/frontend/playwright.config.ts @@ -1,4 +1,9 @@ import { defineConfig, devices } from "@playwright/test"; +import dotenv from "dotenv"; +import path from "path"; + +// Read from ".env" file. +dotenv.config({ path: path.resolve(__dirname, "../ci.env") }); /** * See https://playwright.dev/docs/test-configuration. diff --git a/src/typescript/frontend/src/components/emoji-picker/EmojiPickerWithInput.tsx b/src/typescript/frontend/src/components/emoji-picker/EmojiPickerWithInput.tsx index 725c329bd0..136c373aca 100644 --- a/src/typescript/frontend/src/components/emoji-picker/EmojiPickerWithInput.tsx +++ b/src/typescript/frontend/src/components/emoji-picker/EmojiPickerWithInput.tsx @@ -250,6 +250,7 @@ export const EmojiPickerWithInput = ({ onClick={() => { setPickerInvisible(false); }} + data-testid="emoji-input" /> {mode === "search" && close} {mode === "chat" ? ( diff --git a/src/typescript/frontend/src/lib/server-env.ts b/src/typescript/frontend/src/lib/server-env.ts index d4fc10c53e..eec40d9f10 100644 --- a/src/typescript/frontend/src/lib/server-env.ts +++ b/src/typescript/frontend/src/lib/server-env.ts @@ -43,7 +43,10 @@ export const GALXE_CAMPAIGN_ID: string | undefined = process.env.GALXE_CAMPAIGN_ export const REVALIDATION_TIME: number = Number(process.env.REVALIDATION_TIME); export const VPNAPI_IO_API_KEY: string = process.env.VPNAPI_IO_API_KEY!; -if (APTOS_NETWORK === Network.LOCAL && !EMOJICOIN_INDEXER_URL.includes("localhost")) { +if ( + APTOS_NETWORK === Network.LOCAL && + (!EMOJICOIN_INDEXER_URL.includes("localhost") || !EMOJICOIN_INDEXER_URL.includes("docker")) +) { throw new Error( `APTOS_NETWORK is ${APTOS_NETWORK} but the indexer processor url is set to ${EMOJICOIN_INDEXER_URL}` ); diff --git a/src/typescript/frontend/src/middleware.ts b/src/typescript/frontend/src/middleware.ts index 3bc7b37c1b..55350fbb05 100644 --- a/src/typescript/frontend/src/middleware.ts +++ b/src/typescript/frontend/src/middleware.ts @@ -3,6 +3,7 @@ import { COOKIE_FOR_HASHED_ADDRESS, } from "components/pages/verify/session-info"; import { authenticate } from "components/pages/verify/verify"; +import { IS_ALLOWLIST_ENABLED } from "lib/env"; import { NextResponse, type NextRequest } from "next/server"; import { ROUTES } from "router/routes"; import { normalizePossibleMarketPath } from "utils/pathname-helpers"; @@ -24,6 +25,10 @@ export default async function middleware(request: NextRequest) { return NextResponse.redirect(possibleMarketPath); } + if (!IS_ALLOWLIST_ENABLED) { + return NextResponse.next(); + } + const hashed = request.cookies.get(COOKIE_FOR_HASHED_ADDRESS)?.value; const address = request.cookies.get(COOKIE_FOR_ACCOUNT_ADDRESS)?.value; diff --git a/src/typescript/frontend/tests/e2e/search.spec.ts b/src/typescript/frontend/tests/e2e/search.spec.ts new file mode 100644 index 0000000000..14a7398aef --- /dev/null +++ b/src/typescript/frontend/tests/e2e/search.spec.ts @@ -0,0 +1,25 @@ +import { test, expect } from "@playwright/test"; +import { EmojicoinClient } from "../../../sdk/src/client/emojicoin-client"; +import { getFundedAccount } from "../../../sdk/src/utils/test/test-accounts"; +import { SYMBOL_EMOJI_DATA } from "../../../sdk/src"; + +test("check search results", async ({ page }) => { + const user = getFundedAccount("666"); + const symbols = [SYMBOL_EMOJI_DATA.byName("cat")!.emoji, SYMBOL_EMOJI_DATA.byName("cat")!.emoji]; + + const client = new EmojicoinClient(); + + await client.register(user, symbols); + + await page.goto("/home"); + + const search = page.getByTestId("emoji-input"); + expect(search).toBeVisible(); + await search.fill(symbols.join("")); + + const marketCard = page.getByText("cat,cat", { exact: true }); + expect(marketCard).toBeVisible(); + await marketCard.click(); + + await expect(page).toHaveURL(/.*cat;cat/); +}); diff --git a/src/typescript/frontend/tsconfig.json b/src/typescript/frontend/tsconfig.json index 8b30e81e83..204a045916 100644 --- a/src/typescript/frontend/tsconfig.json +++ b/src/typescript/frontend/tsconfig.json @@ -69,6 +69,7 @@ "./src/**/*.ts", "./src/**/*.tsx", ".next/types/**/*.ts", - "./dist/types/**/*.ts" + "./dist/types/**/*.ts", + "./tests/**/*.ts" ] } diff --git a/src/typescript/package.json b/src/typescript/package.json index 105641293c..623b8681ec 100644 --- a/src/typescript/package.json +++ b/src/typescript/package.json @@ -25,14 +25,13 @@ "dev:debug": "pnpm dotenv -v FETCH_DEBUG=true -- pnpm run dev", "dev:debug-verbose": "pnpm dotenv -v FETCH_DEBUG_VERBOSE=true -- pnpm run dev", "down": "pnpm run prune", - "e2e:frontend": "pnpm run load-env:e2e-frontend -- turbo run e2e:frontend --filter @econia-labs/emojicoin-frontend --log-prefix none", + "e2e:frontend": "turbo run e2e:frontend --filter @econia-labs/emojicoin-frontend --log-prefix none", "format": "turbo run format -- --write", "format:check": "turbo run format -- --check", "full-clean": "pnpm run clean && rm -rf node_modules && rm -rf sdk/node_modules && rm -rf frontend/node_modules", "lint": "turbo run lint", "lint:fix": "turbo run lint -- --fix", "load-env": "dotenv -e .env.local -e .env -e .env.example -e ../docker/example.local.env -e ../docker/.env", - "load-env:e2e-frontend": "dotenv -e .env.local -e .env -e .env.example -e ../docker/example.local.env -e ../docker/.env -e ci.env -v NODE_ENV=test", "load-env:test": "dotenv -e .env.local -e .env -e .env.example -e ../docker/example.local.env -e ../docker/.env -e ci.env", "load-env:test-debug": "dotenv -e .env.local -e .env -e .env.example -e ../docker/example.local.env -e ../docker/.env -e ci.env -v FETCH_DEBUG=true", "load-env:test-verbose": "dotenv -e .env.local -e .env -e .env.example -e ../docker/example.local.env -e ../docker/.env -e ci.env -v FETCH_DEBUG=true VERBOSE_TEST_LOGS=true", diff --git a/src/typescript/pnpm-lock.yaml b/src/typescript/pnpm-lock.yaml index c2917b1c74..4f5899249b 100644 --- a/src/typescript/pnpm-lock.yaml +++ b/src/typescript/pnpm-lock.yaml @@ -99,6 +99,9 @@ importers: clsx: specifier: ^2.1.1 version: 2.1.1 + dotenv: + specifier: ^16.4.5 + version: 16.4.5 emoji-mart: specifier: https://github.com/econia-labs/emoji-mart/raw/emojicoin-dot-fun/packages/emoji-mart/emoji-mart-v5.6.0.tgz version: https://github.com/econia-labs/emoji-mart/raw/emojicoin-dot-fun/packages/emoji-mart/emoji-mart-v5.6.0.tgz diff --git a/src/typescript/sdk/src/client/emojicoin-client.ts b/src/typescript/sdk/src/client/emojicoin-client.ts index 44f7d1d69a..912ffccf08 100644 --- a/src/typescript/sdk/src/client/emojicoin-client.ts +++ b/src/typescript/sdk/src/client/emojicoin-client.ts @@ -24,7 +24,7 @@ import { type EventsModels, getEventsAsProcessorModelsFromResponse } from "../mi import { getAptosClient } from "../utils/aptos-client"; import { toChatMessageEntryFunctionArgs } from "../emoji_data"; import customExpect from "./expect"; -import { INTEGRATOR_ADDRESS } from "../const"; +import { DEFAULT_REGISTER_MARKET_GAS_OPTIONS, INTEGRATOR_ADDRESS } from "../const"; const { expect, Expect } = customExpect; @@ -119,6 +119,7 @@ export class EmojicoinClient { emojis: this.emojisToHexStrings(symbolEmojis), integrator: this.integrator, ...options, + options: DEFAULT_REGISTER_MARKET_GAS_OPTIONS, }); const res = this.getTransactionEventData(response); return { diff --git a/src/typescript/sdk/src/utils/test/docker/docker-test-harness.ts b/src/typescript/sdk/src/utils/test/docker/docker-test-harness.ts index d03c35d1fd..8c290c8acc 100644 --- a/src/typescript/sdk/src/utils/test/docker/docker-test-harness.ts +++ b/src/typescript/sdk/src/utils/test/docker/docker-test-harness.ts @@ -73,8 +73,10 @@ export class DockerTestHarness { /** * Stops the Docker containers. */ - static async stop() { - await execPromise(`docker compose -f ${LOCAL_COMPOSE_PATH} stop`); + static async stop(frontend: boolean) { + await execPromise( + `docker compose -f ${LOCAL_COMPOSE_PATH} ${frontend && "--profile frontend"} stop` + ); const process = Number(readFileSync(TMP_PID_FILE_PATH, { encoding: "utf-8" })); if (process) { kill(process); diff --git a/src/typescript/sdk/tests/post-test.ts b/src/typescript/sdk/tests/post-test.ts index 4e6c8ed73c..4704bb6758 100644 --- a/src/typescript/sdk/tests/post-test.ts +++ b/src/typescript/sdk/tests/post-test.ts @@ -2,5 +2,5 @@ import { DockerTestHarness } from "../src/utils/test/docker/docker-test-harness"; export default async function postTest() { - await DockerTestHarness.stop(); + await DockerTestHarness.stop(false); }