diff --git a/.vscode/settings.json b/.vscode/settings.json index 11bdfb1..52c2ba8 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,7 +2,7 @@ "files.associations": { "**/*.jinja": "jinja" }, - "python.testing.pytestArgs": ["tests"], + "python.testing.pytestArgs": ["."], "python.testing.unittestEnabled": false, "python.testing.pytestEnabled": true, "files.eol": "\n" diff --git a/README.md b/README.md index 4c2ba20..ce14352 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,24 @@
- +

- - - - + npm version + +

--- -This template provides a baseline React web app for developing integrating with any [ARC32](https://github.com/algorandfoundation/ARCs/blob/main/ARCs/arc-0032.md) compliant Algorand smart contracts. - -To use it [install AlgoKit](https://github.com/algorandfoundation/algokit-cli#readme) and then either pass in `-t react` to `algokit init` or select the `react` template interactively during `algokit init`. - -This is one of the official frontend templates used by AlgoKit to initialise an Algorand enabled React web app ready for integrating with your smart contracts. It's made by relying on a [Copier templates](https://copier.readthedocs.io/en/stable/). +This template is a starter template for building an Algorand based dApp on React with [`subtopia-js-sdk`](https://github.com/subtopia-algo/subtopia-js) integration. The template is based on the official [`algokit-react-template`](https://github.com/algorandfoundation/algokit-react-frontend-template). ## Features -This template supports the following features: +The template offers two presets, the recommended preset includes all of the above, a custom preset allows you to select which features you want to include in your project. + +The full list of features includes the following: +- Subtopia SDK integration for interacting with the Subtopia protocol. Includes a sample TestNet based subscription integrated. - React web app with [Tailwind CSS](https://tailwindcss.com/) and [TypeScript](https://www.typescriptlang.org/) - Styled framework agnostic CSS components using [DaisyUI](https://daisyui.com/). - Starter jest unit tests for typescript functions. Can be disabled if not needed. diff --git a/copier.yaml b/copier.yaml index df22c29..79067ba 100644 --- a/copier.yaml +++ b/copier.yaml @@ -55,7 +55,7 @@ use_daisy_ui: type: bool help: Do you want to use a daisyUI? Framework agnostic CSS component library for building modern websites and web applications fast. default: yes - when: '{{ use_tailwind != false && preset == "custom" }}' + when: '{{ use_tailwind != false and preset == "custom" }}' use_jest: type: bool diff --git a/tests_generated/test_default_preset/.algokit.toml b/tests_generated/test_default_preset/.algokit.toml new file mode 100644 index 0000000..839cfe5 --- /dev/null +++ b/tests_generated/test_default_preset/.algokit.toml @@ -0,0 +1,2 @@ +[algokit] +min_version = "v1.3.0b1" diff --git a/tests_generated/test_default_preset/.copier-answers.yml b/tests_generated/test_default_preset/.copier-answers.yml new file mode 100644 index 0000000..e64f596 --- /dev/null +++ b/tests_generated/test_default_preset/.copier-answers.yml @@ -0,0 +1,13 @@ +# Changes here will be overwritten by Copier; NEVER EDIT MANUALLY +_commit: +_src_path: +algod_port: 4001 +algod_server: http://localhost +algod_token: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +cloud_provider: none +indexer_port: 8980 +indexer_server: http://localhost +indexer_token: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +preset: default +project_name: test_default_preset + diff --git a/tests_generated/test_default_preset/.editorconfig b/tests_generated/test_default_preset/.editorconfig new file mode 100644 index 0000000..a83b72c --- /dev/null +++ b/tests_generated/test_default_preset/.editorconfig @@ -0,0 +1,9 @@ +[*] +charset = utf-8 +insert_final_newline = true +end_of_line = lf +indent_style = space +indent_size = 2 +tab_width = 2 +max_line_length = 140 +trim_trailing_whitespace = true diff --git a/tests_generated/test_default_preset/.env.template b/tests_generated/test_default_preset/.env.template new file mode 100644 index 0000000..e05d499 --- /dev/null +++ b/tests_generated/test_default_preset/.env.template @@ -0,0 +1,67 @@ +# ====================== +# LocalNet configuration +# uncomment below to use +# ====================== + +VITE_ENVIRONMENT=local + +# Algod +VITE_ALGOD_TOKEN=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +VITE_ALGOD_SERVER=http://localhost +VITE_ALGOD_PORT=4001 +VITE_ALGOD_NETWORK="" + +# Indexer +VITE_INDEXER_TOKEN=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +VITE_INDEXER_SERVER=http://localhost +VITE_INDEXER_PORT=8980 + +# KMD +# Please note: +# 1. This is only needed for LocalNet since +# by default KMD provider is ignored on other networks. +# 2. AlgoKit LocalNet starts with a single wallet called 'unencrypted-default-wallet', +# with heaps of tokens available for testing. +VITE_KMD_TOKEN=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +VITE_KMD_SERVER=http://localhost +VITE_KMD_PORT=4002 +VITE_KMD_WALLET="unencrypted-default-wallet" +VITE_KMD_PASSWORD="" + +# # ====================== +# # TestNet configuration: +# # uncomment below to use +# # ====================== + +# VITE_ENVIRONMENT=local + +# # Algod +# VITE_ALGOD_TOKEN="" +# VITE_ALGOD_SERVER="https://testnet-api.algonode.cloud" +# VITE_ALGOD_PORT="" +# VITE_ALGOD_NETWORK="testnet" + +# # Indexer +# VITE_INDEXER_TOKEN="" +# VITE_INDEXER_SERVER="https://testnet-idx.algonode.cloud" +# VITE_INDEXER_PORT="" + + +# # ====================== +# # MainNet configuration: +# # uncomment below to use +# # ====================== + +# VITE_ENVIRONMENT=production + +# # Algod +# VITE_ALGOD_TOKEN="" +# VITE_ALGOD_SERVER="https://mainnet-api.algonode.cloud" +# VITE_ALGOD_PORT="" +# VITE_ALGOD_NETWORK="mainnet" + +# # Indexer +# VITE_INDEXER_TOKEN="" +# VITE_INDEXER_SERVER="https://mainnet-idx.algonode.cloud" +# VITE_INDEXER_PORT="" + diff --git a/tests_generated/test_default_preset/.eslintrc b/tests_generated/test_default_preset/.eslintrc new file mode 100644 index 0000000..868fe37 --- /dev/null +++ b/tests_generated/test_default_preset/.eslintrc @@ -0,0 +1,27 @@ +{ + "root": true, + "env": { + "node": true + }, + "parser": "@typescript-eslint/parser", + "plugins": ["@typescript-eslint", "prettier"], + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended", + "plugin:prettier/recommended" + ], + "rules": { + "prettier/prettier": "warn", + "no-console": "warn", + "@typescript-eslint/no-unused-vars": [ + "warn", + { + "ignoreRestSiblings": true, + "argsIgnorePattern": "^_", + "destructuredArrayIgnorePattern": "^_" + } + ], + "prefer-template": "error" + } +} diff --git a/tests_generated/test_default_preset/.gitattributes b/tests_generated/test_default_preset/.gitattributes new file mode 100644 index 0000000..6313b56 --- /dev/null +++ b/tests_generated/test_default_preset/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf diff --git a/tests_generated/test_default_preset/.github/workflows/checks.yaml b/tests_generated/test_default_preset/.github/workflows/checks.yaml new file mode 100644 index 0000000..e22e436 --- /dev/null +++ b/tests_generated/test_default_preset/.github/workflows/checks.yaml @@ -0,0 +1,54 @@ +name: Check code base + +on: + workflow_call: + inputs: + run-build: + required: false + type: boolean + default: false + push: + branches: + - main + +jobs: + checks: + runs-on: 'ubuntu-latest' + steps: + - name: Check out repository + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Setup node + uses: actions/setup-node@v3 + with: + node-version: 18 + + - name: Install dependencies + run: npm ci + + - name: Run linters + run: npm run lint + + - name: Run unit tests + run: npm run test + + - name: Create placeholder .env file + if: ${{ inputs.run-build }} + uses: makerxstudio/shared-config/.github/actions/env-to-placeholders@main + with: + env-output-path: './.env' + env-template-path: './.env.template' + env-variable-prefix: VITE_ + + - name: Build + if: ${{ inputs.run-build }} + run: npm run build + + - name: Archive + if: ${{ inputs.run-build }} + uses: actions/upload-artifact@v3 + with: + name: dist + path: dist/ diff --git a/tests_generated/test_default_preset/.github/workflows/pr.yaml b/tests_generated/test_default_preset/.github/workflows/pr.yaml new file mode 100644 index 0000000..a80f784 --- /dev/null +++ b/tests_generated/test_default_preset/.github/workflows/pr.yaml @@ -0,0 +1,8 @@ +name: Pull Request validation + +on: [pull_request] + +jobs: + pr-check: + name: Perform Checks + uses: ./.github/workflows/checks.yaml diff --git a/tests_generated/test_default_preset/.github/workflows/release.yaml b/tests_generated/test_default_preset/.github/workflows/release.yaml new file mode 100644 index 0000000..ea6f087 --- /dev/null +++ b/tests_generated/test_default_preset/.github/workflows/release.yaml @@ -0,0 +1,61 @@ +name: Release + +on: + push: + branches: + - main + paths-ignore: + - "docs/**" + - "**.md" + - ".vscode/**" + - ".idea/**" + +permissions: + contents: read + packages: read + +jobs: + lint-and-build: + name: CI dApp + uses: ./.github/workflows/checks.yaml + + deploy: + runs-on: ubuntu-latest + name: Deploy to Netlify + environment: Prod + concurrency: "${{ github.workflow }}-prod" + needs: + - lint-and-build + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Download build artifacts + uses: actions/download-artifact@v3 + with: + name: dist + path: dist + + - name: Replace template vars + uses: makerxstudio/shared-config/.github/actions/placeholder-transforms@main + with: + app-artifact-path: './dist' + static-site-transforms: |- + VITE_ALGOD_TOKEN:${{ secrets.VITE_ALGOD_TOKEN }} + VITE_ALGOD_SERVER:${{ vars.VITE_ALGOD_SERVER }} + VITE_ALGOD_PORT:${{ vars.VITE_ALGOD_PORT }} + VITE_ALGOD_NETWORK:${{ vars.VITE_ALGOD_NETWORK }} + VITE_INDEXER_SERVER:${{ vars.VITE_INDEXER_SERVER }} + VITE_INDEXER_PORT:${{ vars.VITE_INDEXER_PORT }} + VITE_INDEXER_TOKEN:${{ secrets.VITE_INDEXER_TOKEN }} + VITE_ENVIRONMENT:${{ vars.VITE_ENVIRONMENT }} + + - name: Install netlify cli + run: npm i netlify-cli + + - name: Publish to netlify + run: netlify deploy --prod --dir "dist" + env: + NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} + NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} + diff --git a/tests_generated/test_default_preset/.gitignore b/tests_generated/test_default_preset/.gitignore new file mode 100644 index 0000000..26dc019 --- /dev/null +++ b/tests_generated/test_default_preset/.gitignore @@ -0,0 +1,35 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# production +/build + + +# dotenv environment variable files +.env +env/ + +# misc +/dist +.DS_Store + + +npm-debug.log* +yarn-debug.log* +yarn-error.log* +/test-results/ +/playwright-report/ +/playwright/.cache/ + +# PyCharm +.idea +!.idea/ +.idea/* +!.idea/runConfigurations/ diff --git a/tests_generated/test_default_preset/.prettierignore b/tests_generated/test_default_preset/.prettierignore new file mode 100644 index 0000000..dbda6ae --- /dev/null +++ b/tests_generated/test_default_preset/.prettierignore @@ -0,0 +1,12 @@ +# don't ever format node_modules +node_modules +# don't lint format output (make sure it's set to your correct build folder name) +dist +build +# don't format nyc coverage output +coverage +# don't format generated types +**/generated/types.d.ts +**/generated/types.ts +# don't format ide files +.idea diff --git a/tests_generated/test_default_preset/.prettierrc.js b/tests_generated/test_default_preset/.prettierrc.js new file mode 100644 index 0000000..066b8e5 --- /dev/null +++ b/tests_generated/test_default_preset/.prettierrc.js @@ -0,0 +1,10 @@ +module.exports = { + singleQuote: true, + jsxSingleQuote: false, + semi: false, + tabWidth: 2, + trailingComma: 'all', + printWidth: 140, + endOfLine: 'lf', + arrowParens: 'always', +} diff --git a/tests_generated/test_default_preset/.vscode/extensions.json b/tests_generated/test_default_preset/.vscode/extensions.json new file mode 100644 index 0000000..5c94122 --- /dev/null +++ b/tests_generated/test_default_preset/.vscode/extensions.json @@ -0,0 +1,14 @@ +{ + "recommendations": [ + "EditorConfig.EditorConfig", + "dotenv.dotenv-vscode", + "esbenp.prettier-vscode", + "dbaeumer.vscode-eslint", + "krysenlo.vite-plugin-eslint-problemmatcher", + "ms-playwright.playwright", + "Orta.vscode-jest", + "bradlc.vscode-tailwindcss", + "csstools.postcss", + ] +} + diff --git a/tests_generated/test_default_preset/.vscode/launch.json b/tests_generated/test_default_preset/.vscode/launch.json new file mode 100644 index 0000000..7edaf04 --- /dev/null +++ b/tests_generated/test_default_preset/.vscode/launch.json @@ -0,0 +1,68 @@ +{ + "configurations": [ + { + "type": "msedge", + "request": "launch", + "name": "Run (Edge)", + "url": "http://localhost:5173", + "webRoot": "${workspaceFolder}", + "presentation": { + "hidden": false, + "group": "2. Web" + } + }, + { + "type": "chrome", + "request": "launch", + "name": "Run (Chrome)", + "url": "http://localhost:5173", + "webRoot": "${workspaceFolder}", + "presentation": { + "hidden": false, + "group": "2. Web" + } + }, + { + "type": "firefox", + "request": "launch", + "name": "Run (Firefox)", + "url": "http://localhost:5173", + "webRoot": "${workspaceFolder}", + "presentation": { + "hidden": false, + "group": "2. Web" + } + }, + { + "name": "Run dApp", + "type": "node", + "request": "launch", + "runtimeExecutable": "npm", + "runtimeArgs": ["run", "dev"], + "cwd": "${workspaceRoot}", + "console": "integratedTerminal", + "skipFiles": ["/**", "node_modules/**"], + "presentation": { + "hidden": false, + "group": "1. Run Project", + "order": 1 + } + }, + { + "name": "Run dApp (+ LocalNet)", + "type": "node", + "request": "launch", + "runtimeExecutable": "npm", + "runtimeArgs": ["run", "dev"], + "cwd": "${workspaceRoot}", + "console": "integratedTerminal", + "skipFiles": ["/**", "node_modules/**"], + "preLaunchTask": "Start AlgoKit LocalNet", + "presentation": { + "hidden": false, + "group": "1. Run Project", + "order": 1 + } + } + ] +} diff --git a/tests_generated/test_default_preset/.vscode/settings.json b/tests_generated/test_default_preset/.vscode/settings.json new file mode 100644 index 0000000..6ffe6b3 --- /dev/null +++ b/tests_generated/test_default_preset/.vscode/settings.json @@ -0,0 +1,13 @@ +{ + "editor.formatOnSave": true, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.codeActionsOnSave": { + "source.fixAll.eslint": true, + "source.organizeImports": true + }, + "dotenv.enableAutocloaking": false, + "jest.autoRun": { + "watch": false, + "onSave": "test-file" + } +} diff --git a/tests_generated/test_default_preset/.vscode/tasks.json b/tests_generated/test_default_preset/.vscode/tasks.json new file mode 100644 index 0000000..d611c4f --- /dev/null +++ b/tests_generated/test_default_preset/.vscode/tasks.json @@ -0,0 +1,15 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "Start AlgoKit LocalNet", + "command": "algokit", + "args": ["localnet", "start"], + "type": "shell", + "options": { + "cwd": "${workspaceFolder}" + }, + "problemMatcher": [] + } + ] +} diff --git a/tests_generated/test_default_preset/LICENSE b/tests_generated/test_default_preset/LICENSE new file mode 100644 index 0000000..b39bcd6 --- /dev/null +++ b/tests_generated/test_default_preset/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Algorand Foundation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/tests_generated/test_default_preset/README.md b/tests_generated/test_default_preset/README.md new file mode 100644 index 0000000..a28ffbc --- /dev/null +++ b/tests_generated/test_default_preset/README.md @@ -0,0 +1,82 @@ +# test_default_preset + +This starter React project has been generated using AlgoKit. See below for default getting started instructions. + +# Setup + +### Initial setup + +1. Clone this repository locally +2. Install pre-requisites: + - Make sure to have [Docker](https://www.docker.com/) installed and running on your machine. + - Install `AlgoKit` - [Link](https://github.com/algorandfoundation/algokit-cli#install): The minimum required version is `1.1`. Ensure you can execute `algokit --version` and get `1.1` or later. + - Bootstrap your local environment; run `algokit bootstrap all` within this folder, which will run `npm install` to install NPM packages and dependencies for your frontend component/webapp. + - Run `algokit localnet start` to start a local Algorand network in Docker. If you are using VS Code launch configurations provided by the template, this will be done automatically for you. +3. Open the project and start debugging / developing via: + - VS Code + 1. Open the repository root in VS Code + 2. Install recommended extensions + 3. Hit F5 (or whatever you have debug mapped to) and it should start running with breakpoint debugging. + - JetBrains WebStorm + 1. Open the repository root in WebStorm + 2. Hit Shift+F10|Ctrl+R (or whatever you have debug mapped to). Then Shift+CMD|Ctrl+Click on the link in the console to open the browser with debugger attached. + - Other + 1. Open the repository root in your text editor of choice + 2. In a terminal run `npm run dev` + +### Subsequently + +1. If you update to the latest source code and there are new dependencies you will need to run `algokit bootstrap all` again +2. Follow step 3 above + +> Please note, by default frontend is pre configured to run against Algorand LocalNet. If you want to run against TestNet or MainNet, comment out the current environment variable and uncomment the relevant one in [`.env`](.env) file that is created after running bootstrap command and based on [`.env.template`](.env.template). + +### Continuous Integration + +This project uses [GitHub Actions](https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions) to define CI workflows, which are located in the [`.github/workflows`](./.github/workflows) folder. + +For pull requests and pushes to `main` branch against this repository the following checks are automatically performed by GitHub Actions: + +- `install`: Installs dependencies using `npm` +- `lint`: Lints the codebase using `ESLint` +- `build`: Builds the codebase using `vite` + +### Continuous Deployment + +The project template provides base Github Actions workflows for continuous deployment to [Netlify](https://www.netlify.com/) or [Vercel](https://vercel.com/). These workflows are located in the [`.github/workflows`](./.github/workflows) folder. + +> Please note: when configuring the github repository for the first time. Depending on selected provider you will need to set the provider secrets in the repository settings. For netlify you can pass the project specific environment variables as part of Github actions secrets, while for vercel you will need to set the secrets on your site instance (refer to the [Vercel documentation](https://vercel.com/docs/cli#commands/secrets) for more details). + +# Algorand Wallet integrations + +The template comes with [`use-wallet`](https://github.com/txnlab/use-wallet) integration, which provides a React hook for connecting to an Algorand wallet providers. The following wallet providers are included by default: +- LocalNet: +- - [KMD/Local Wallet](https://github.com/TxnLab/use-wallet#kmd-algorand-key-management-daemon) - Algorand's Key Management Daemon (KMD) is a service that manages Algorand private keys and signs transactions. Works best with AlgoKit LocalNet and allows you to easily test and interact with your dApps locally. +- TestNet and others: +- - [Pera Wallet](https://perawallet.app). +- - [Defly Wallet](https://defly.app). +- - [Exodus Wallet](https://www.exodus.com). +- - [Daffi Wallet](https://www.daffi.me). + +Refer to official [`use-wallet`](https://github.com/txnlab/use-wallet) documentation for detailed guidelines on how to integrate with other wallet providers (such as WalletConnect v2). Too see implementation details on the use wallet hook and initialization of extra wallet providers refer to [`App.tsx`](./src/App.tsx). + +# Tools + +This project makes use of React and Tailwind to provider a base project configuration to develop frontends for your Algorand dApps and interactions with smart contracts. The following tools are in use: + +- [AlgoKit Utils](https://github.com/algorandfoundation/algokit-utils-ts) - Various TypeScript utilities to simplify interactions with Algorand and AlgoKit. +- [React](https://reactjs.org/) - A JavaScript library for building user interfaces. +- [Tailwind CSS](https://tailwindcss.com/) - A utility-first CSS framework for rapidly building custom designs. +- [daisyUI](https://daisyui.com/) - A component library for Tailwind CSS. +- [use-wallet](https://github.com/txnlab/use-wallet) - A React hook for connecting to an Algorand wallet providers. +- [npm](https://www.npmjs.com/): Node.js package manager +- [jest](https://jestjs.io/): JavaScript testing framework +- [playwright](https://playwright.dev/): Browser automation library +- [Prettier](https://prettier.io/): Opinionated code formatter +- [ESLint](https://eslint.org/): Tool for identifying and reporting on patterns in JavaScript +- Github Actions workflows for build validation +It has also been configured to have a productive dev experience out of the box in [VS Code](https://code.visualstudio.com/), see the [.vscode](./.vscode) folder. +# Integrating with smart contracts and application clients + +Refer to the detailed guidance on [integrating with smart contracts and application clients](./src/contracts/README.md). In essence, for any smart contract codebase generated with AlgoKit or other tools that produce compile contracts into ARC34 compliant app specifications, you can use the `algokit generate` command to generate TypeScript or Python typed client. Once generated simply drag and drop the generated client into `./src/contracts` and import it into your React components as you see fit. + diff --git a/tests_generated/test_default_preset/index.html b/tests_generated/test_default_preset/index.html new file mode 100644 index 0000000..a85566a --- /dev/null +++ b/tests_generated/test_default_preset/index.html @@ -0,0 +1,15 @@ + + + + + + AlgoKit React Template + + +
+ + + + diff --git a/tests_generated/test_default_preset/jest.config.ts b/tests_generated/test_default_preset/jest.config.ts new file mode 100644 index 0000000..28a8c3d --- /dev/null +++ b/tests_generated/test_default_preset/jest.config.ts @@ -0,0 +1,20 @@ +import type { Config } from '@jest/types' + +const config: Config.InitialOptions = { + preset: 'ts-jest', + testEnvironment: 'node', + testMatch: ['**/*.spec.ts', '**/*.spec.tsx'], + moduleDirectories: ['node_modules', 'src'], + transform: { + '': [ + 'ts-jest', + { + tsconfig: 'tsconfig.test.json', + }, + ], + }, + coveragePathIgnorePatterns: ['tests'], + testPathIgnorePatterns: ['/tests/'], + } + +export default config diff --git a/tests_generated/test_default_preset/package.json b/tests_generated/test_default_preset/package.json new file mode 100644 index 0000000..4223cae --- /dev/null +++ b/tests_generated/test_default_preset/package.json @@ -0,0 +1,74 @@ +{ + "name": "test_default_preset", + "version": "0.1.0", + "author": { + "name": "None", + "email": "None" + }, + "private": true, + "engines": { + "node": ">=18.0" + }, + "devDependencies": { + "@types/node": "18.17.14", + "@types/react": "18.2.11", + "@types/react-dom": "18.2.4", + "@vitejs/plugin-react-swc": "3.3.2", + "autoprefixer": "10.4.14", + "eslint": "8.42.0", + "eslint-config-prettier": "8.8.0", + "eslint-plugin-prettier": "5.0.0", + "@typescript-eslint/eslint-plugin": "6.5.0", + "@typescript-eslint/parser": "6.5.0", + "postcss": "^8.4.24", + "tailwindcss": "3.3.2", + "ts-jest": "^29.1.1", + "@types/jest": "29.5.2", + "ts-node": "10.9.1", + "typescript": "5.1.6", + "@playwright/test": "^1.35.0", + "playwright": "^1.35.0", + "vite": "4.4.9" + }, + "dependencies": { + "@walletconnect/modal-sign-html": "^2.6.1", + "@algorandfoundation/algokit-utils": "^4.1.0", + "@blockshake/defly-connect": "^1.1.6", + "@daffiwallet/connect": "^1.0.3", + "@perawallet/connect": "^1.3.1", + "@txnlab/use-wallet": "^2.1.1", + "algosdk": "^2.5.0", + "daisyui": "^3.1.0", + "notistack": "^3.0.1", + "react": "^18.2.0", + "react-dom": "18.2.0", + "tslib": "^2.6.2" + }, + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "test": "jest --coverage --passWithNoTests", + "playwright:test": "playwright test", + "lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "lint:fix": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0 --fix", + "preview": "vite preview" + }, + "eslintConfig": { + "extends": [ + "react-app/jest", + "react-app" + ] + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + } +} diff --git a/tests_generated/test_default_preset/playwright.config.ts b/tests_generated/test_default_preset/playwright.config.ts new file mode 100644 index 0000000..d7cbca6 --- /dev/null +++ b/tests_generated/test_default_preset/playwright.config.ts @@ -0,0 +1,73 @@ +import { defineConfig, devices } from '@playwright/test' + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './tests', + /* Run tests in files in parallel */ + fullyParallel: true, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Base URL to use in actions like `await page.goto('/')`. */ + // baseURL: 'http://127.0.0.1:3000', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + testIdAttribute: 'data-test-id', + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + + { + name: 'firefox', + use: { ...devices['Desktop Firefox'] }, + }, + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { ...devices['Pixel 5'] }, + // }, + // { + // name: 'Mobile Safari', + // use: { ...devices['iPhone 12'] }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { ...devices['Desktop Edge'], channel: 'msedge' }, + // }, + // { + // name: 'Google Chrome', + // use: { ..devices['Desktop Chrome'], channel: 'chrome' }, + // }, + ], + + /* Run your local dev server before starting the tests */ + webServer: { + command: 'npm run dev', + url: 'http://localhost:5173', + reuseExistingServer: !process.env.CI, + }, +}) diff --git a/tests_generated/test_default_preset/postcss.config.js b/tests_generated/test_default_preset/postcss.config.js new file mode 100644 index 0000000..33ad091 --- /dev/null +++ b/tests_generated/test_default_preset/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} diff --git a/tests_generated/test_default_preset/public/index.html b/tests_generated/test_default_preset/public/index.html new file mode 100644 index 0000000..0d3a3a5 --- /dev/null +++ b/tests_generated/test_default_preset/public/index.html @@ -0,0 +1,37 @@ + + + + + + + + + + React App + + + +
+ + + diff --git a/tests_generated/test_default_preset/public/robots.txt b/tests_generated/test_default_preset/public/robots.txt new file mode 100644 index 0000000..e9e57dc --- /dev/null +++ b/tests_generated/test_default_preset/public/robots.txt @@ -0,0 +1,3 @@ +# https://www.robotstxt.org/robotstxt.html +User-agent: * +Disallow: diff --git a/tests_generated/test_default_preset/src/App.tsx b/tests_generated/test_default_preset/src/App.tsx new file mode 100644 index 0000000..79657e2 --- /dev/null +++ b/tests_generated/test_default_preset/src/App.tsx @@ -0,0 +1,107 @@ +import { DeflyWalletConnect } from '@blockshake/defly-connect' +import { DaffiWalletConnect } from '@daffiwallet/connect' +import { PeraWalletConnect } from '@perawallet/connect' +import { PROVIDER_ID, ProvidersArray, WalletProvider, useInitializeProviders, useWallet } from '@txnlab/use-wallet' +import algosdk from 'algosdk' +import { SnackbarProvider } from 'notistack' +import { useState } from 'react' +import ConnectWallet from './components/ConnectWallet' +import Transact from './components/Transact' +import { getAlgodConfigFromViteEnvironment, getKmdConfigFromViteEnvironment } from './utils/network/getAlgoClientConfigs' + +let providersArray: ProvidersArray +if (import.meta.env.VITE_ALGOD_NETWORK === '') { + const kmdConfig = getKmdConfigFromViteEnvironment() + providersArray = [ + { + id: PROVIDER_ID.KMD, + clientOptions: { + wallet: kmdConfig.wallet, + password: kmdConfig.password, + host: kmdConfig.server, + token: String(kmdConfig.token), + port: String(kmdConfig.port), + }, + }, + ] +} else { + providersArray = [ + { id: PROVIDER_ID.DEFLY, clientStatic: DeflyWalletConnect }, + { id: PROVIDER_ID.PERA, clientStatic: PeraWalletConnect }, + { id: PROVIDER_ID.DAFFI, clientStatic: DaffiWalletConnect }, + { id: PROVIDER_ID.EXODUS }, + // If you are interested in WalletConnect v2 provider + // refer to https://github.com/TxnLab/use-wallet for detailed integration instructions + ] +} + +export default function App() { + const [openWalletModal, setOpenWalletModal] = useState(false) + const [openDemoModal, setOpenDemoModal] = useState(false) + const { activeAddress } = useWallet() + + const toggleWalletModal = () => { + setOpenWalletModal(!openWalletModal) + } + + const toggleDemoModal = () => { + setOpenDemoModal(!openDemoModal) + } + + const algodConfig = getAlgodConfigFromViteEnvironment() + + const walletProviders = useInitializeProviders({ + providers: providersArray, + nodeConfig: { + network: algodConfig.network, + nodeServer: algodConfig.server, + nodePort: String(algodConfig.port), + nodeToken: String(algodConfig.token), + }, + algosdkStatic: algosdk, + }) + + return ( + + +
+
+
+

+ Welcome to
AlgoKit 🙂
+

+

+ This starter has been generated using official AlgoKit React template. Refer to the resource below for next steps. +

+ +
+ + Getting started + + +
+ + + {activeAddress && ( + + )} +
+ + + +
+
+
+ + + ) +} diff --git a/tests_generated/test_default_preset/src/assets/logo.svg b/tests_generated/test_default_preset/src/assets/logo.svg new file mode 100644 index 0000000..7169476 --- /dev/null +++ b/tests_generated/test_default_preset/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/tests_generated/test_default_preset/src/components/Account.tsx b/tests_generated/test_default_preset/src/components/Account.tsx new file mode 100644 index 0000000..6a6345e --- /dev/null +++ b/tests_generated/test_default_preset/src/components/Account.tsx @@ -0,0 +1,28 @@ +import { useWallet } from '@txnlab/use-wallet' +import { useMemo } from 'react' +import { ellipseAddress } from '../utils/ellipseAddress' +import { getAlgodConfigFromViteEnvironment } from '../utils/network/getAlgoClientConfigs' + +const Account = () => { + const { activeAddress } = useWallet() + const algoConfig = getAlgodConfigFromViteEnvironment() + + const dappFlowNetworkName = useMemo(() => { + return algoConfig.network === '' ? 'sandbox' : algoConfig.network.toLocaleLowerCase() + }, [algoConfig.network]) + + return ( +
+ + Address: {ellipseAddress(activeAddress)} + +
Network: {algoConfig.network === '' ? 'localnet' : algoConfig.network}
+
+ ) +} + +export default Account diff --git a/tests_generated/test_default_preset/src/components/ConnectWallet.tsx b/tests_generated/test_default_preset/src/components/ConnectWallet.tsx new file mode 100644 index 0000000..c4225bc --- /dev/null +++ b/tests_generated/test_default_preset/src/components/ConnectWallet.tsx @@ -0,0 +1,86 @@ +import { Provider, useWallet } from '@txnlab/use-wallet' +import Account from './Account' + +interface ConnectWalletInterface { + openModal: boolean + closeModal: () => void +} + +const ConnectWallet = ({ openModal, closeModal }: ConnectWalletInterface) => { + const { providers, activeAddress } = useWallet() + + const isKmd = (provider: Provider) => provider.metadata.name.toLowerCase() === 'kmd' + + return ( + +
+

Select wallet provider

+ +
+ {activeAddress && ( + <> + +
+ + )} + + {!activeAddress && + providers?.map((provider) => ( + + ))} +
+ +
+ + {activeAddress && ( + + )} +
+ +
+ ) +} +export default ConnectWallet diff --git a/tests_generated/test_default_preset/src/components/ErrorBoundary.tsx b/tests_generated/test_default_preset/src/components/ErrorBoundary.tsx new file mode 100644 index 0000000..435bf61 --- /dev/null +++ b/tests_generated/test_default_preset/src/components/ErrorBoundary.tsx @@ -0,0 +1,46 @@ +import React, { ReactNode } from 'react' + +interface ErrorBoundaryProps { + children: ReactNode +} + +interface ErrorBoundaryState { + hasError: boolean + error: Error | null +} + +class ErrorBoundary extends React.Component { + constructor(props: ErrorBoundaryProps) { + super(props) + this.state = { hasError: false, error: null } + } + + static getDerivedStateFromError(error: Error): ErrorBoundaryState { + // Update state so the next render will show the fallback UI. + return { hasError: true, error: error } + } + + render(): ReactNode { + if (this.state.hasError) { + // You can render any custom fallback UI + return ( +
+
+
+

Error occured

+

+ {this.state.error?.message.includes('Attempt to get default algod configuration') + ? 'Please make sure to set up your environment variables correctly. Create a .env file based on .env.template and fill in the required values. This controls the network and credentials for connections with Algod and Indexer.' + : this.state.error?.message} +

+
+
+
+ ) + } + + return this.props.children + } +} + +export default ErrorBoundary diff --git a/tests_generated/test_default_preset/src/components/Transact.tsx b/tests_generated/test_default_preset/src/components/Transact.tsx new file mode 100644 index 0000000..16bd932 --- /dev/null +++ b/tests_generated/test_default_preset/src/components/Transact.tsx @@ -0,0 +1,95 @@ +import * as algokit from '@algorandfoundation/algokit-utils' +import { useWallet } from '@txnlab/use-wallet' +import algosdk from 'algosdk' +import { useSnackbar } from 'notistack' +import { useState } from 'react' +import { getAlgodConfigFromViteEnvironment } from '../utils/network/getAlgoClientConfigs' + +interface TransactInterface { + openModal: boolean + setModalState: (value: boolean) => void +} + +const Transact = ({ openModal, setModalState }: TransactInterface) => { + const [loading, setLoading] = useState(false) + const [receiverAddress, setReceiverAddress] = useState('') + + const algodConfig = getAlgodConfigFromViteEnvironment() + const algodClient = algokit.getAlgoClient({ + server: algodConfig.server, + port: algodConfig.port, + token: algodConfig.token, + }) + + const { enqueueSnackbar } = useSnackbar() + + const { signer, activeAddress, signTransactions, sendTransactions } = useWallet() + + const handleSubmitAlgo = async () => { + setLoading(true) + + if (!signer || !activeAddress) { + enqueueSnackbar('Please connect wallet first', { variant: 'warning' }) + return + } + + const suggestedParams = await algodClient.getTransactionParams().do() + + const transaction = algosdk.makePaymentTxnWithSuggestedParamsFromObject({ + from: activeAddress, + to: receiverAddress, + amount: 1e6, + suggestedParams, + }) + + const encodedTransaction = algosdk.encodeUnsignedTransaction(transaction) + + const signedTransactions = await signTransactions([encodedTransaction]) + + const waitRoundsToConfirm = 4 + + try { + enqueueSnackbar('Sending transaction...', { variant: 'info' }) + const { id } = await sendTransactions(signedTransactions, waitRoundsToConfirm) + enqueueSnackbar(`Transaction sent: ${id}`, { variant: 'success' }) + setReceiverAddress('') + } catch (e) { + enqueueSnackbar('Failed to send transaction', { variant: 'error' }) + } + + setLoading(false) + } + + return ( + +
+

Send payment transaction

+
+ { + setReceiverAddress(e.target.value) + }} + /> +
+ + +
+
+
+ ) +} + +export default Transact diff --git a/tests_generated/test_default_preset/src/contracts/README.md b/tests_generated/test_default_preset/src/contracts/README.md new file mode 100644 index 0000000..e056b58 --- /dev/null +++ b/tests_generated/test_default_preset/src/contracts/README.md @@ -0,0 +1,13 @@ +## How to connect my web app with Algorand smart contracts? + +The following folder is reserved for the Algorand Application Clients. The clients are used to interact with instances of Algorand Smart Contracts (ASC1s) deployed on-chain. + +To integrate this react frontend template with your smart contracts codebase, perform the following steps: + +1. Generate the typed client using `algokit generate client -l typescript -o {path/to/this/folder}` +2. The generated typescript client should be ready to be imported and used in this react frontend template, making it a full fledged dApp. + +### FAQ + +- **How to interact with the smart contract?** + - The generated client provides a set of functions that can be used to interact with the ABI (Application Binary Interface) compliant Algorand smart contract. For example, if the smart contract has a function called `hello`, the generated client will have a function called `hello` that can be used to interact with the smart contract. Refer to a [full-stack end-to-end starter template](https://github.com/algorandfoundation/algokit-fullstack-template) for a reference example on invoking and interacting with typescript typed clients generated. diff --git a/tests_generated/test_default_preset/src/interfaces/network.ts b/tests_generated/test_default_preset/src/interfaces/network.ts new file mode 100644 index 0000000..a458edc --- /dev/null +++ b/tests_generated/test_default_preset/src/interfaces/network.ts @@ -0,0 +1,26 @@ +import { AlgoClientConfig } from '@algorandfoundation/algokit-utils/types/network-client' +import type { TokenHeader } from 'algosdk/dist/types/client/urlTokenBaseHTTPClient' + +export interface AlgoViteClientConfig extends AlgoClientConfig { + /** Base URL of the server e.g. http://localhost, https://testnet-api.algonode.cloud/, etc. */ + server: string + /** The port to use e.g. 4001, 443, etc. */ + port: string | number + /** The token to use for API authentication (or undefined if none needed) - can be a string, or an object with the header key => value */ + token: string | TokenHeader + /** String representing current Algorand Network type (testnet/mainnet and etc) */ + network: string +} + +export interface AlgoViteKMDConfig extends AlgoClientConfig { + /** Base URL of the server e.g. http://localhost, https://testnet-api.algonode.cloud/, etc. */ + server: string + /** The port to use e.g. 4001, 443, etc. */ + port: string | number + /** The token to use for API authentication (or undefined if none needed) - can be a string, or an object with the header key => value */ + token: string | TokenHeader + /** KMD wallet name */ + wallet: string + /** KMD wallet password */ + password: string +} diff --git a/tests_generated/test_default_preset/src/main.tsx b/tests_generated/test_default_preset/src/main.tsx new file mode 100644 index 0000000..adf72ec --- /dev/null +++ b/tests_generated/test_default_preset/src/main.tsx @@ -0,0 +1,13 @@ +import React from 'react' +import ReactDOM from 'react-dom/client' +import App from './App' +import './styles/main.css' +import ErrorBoundary from './components/ErrorBoundary' + +ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( + + + + + , +) diff --git a/tests_generated/test_default_preset/src/styles/main.css b/tests_generated/test_default_preset/src/styles/main.css new file mode 100644 index 0000000..b5c61c9 --- /dev/null +++ b/tests_generated/test_default_preset/src/styles/main.css @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/tests_generated/test_default_preset/src/utils/ellipseAddress.spec.tsx b/tests_generated/test_default_preset/src/utils/ellipseAddress.spec.tsx new file mode 100644 index 0000000..2cbff10 --- /dev/null +++ b/tests_generated/test_default_preset/src/utils/ellipseAddress.spec.tsx @@ -0,0 +1,15 @@ +import { ellipseAddress } from './ellipseAddress' + +describe('ellipseAddress', () => { + it('should return ellipsed address with specified width', () => { + const address = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' + const result = ellipseAddress(address, 4) + expect(result).toBe('aaaa...aaaa') + }) + + it('should return empty string when address is empty', () => { + const address = '' + const result = ellipseAddress(address) + expect(result).toBe('') + }) +}) diff --git a/tests_generated/test_default_preset/src/utils/ellipseAddress.ts b/tests_generated/test_default_preset/src/utils/ellipseAddress.ts new file mode 100644 index 0000000..542f46f --- /dev/null +++ b/tests_generated/test_default_preset/src/utils/ellipseAddress.ts @@ -0,0 +1,3 @@ +export function ellipseAddress(address = ``, width = 6): string { + return address ? `${address.slice(0, width)}...${address.slice(-width)}` : address +} diff --git a/tests_generated/test_default_preset/src/utils/network/getAlgoClientConfigs.ts b/tests_generated/test_default_preset/src/utils/network/getAlgoClientConfigs.ts new file mode 100644 index 0000000..b5121f8 --- /dev/null +++ b/tests_generated/test_default_preset/src/utils/network/getAlgoClientConfigs.ts @@ -0,0 +1,41 @@ +import { AlgoViteClientConfig, AlgoViteKMDConfig } from '../../interfaces/network' + +export function getAlgodConfigFromViteEnvironment(): AlgoViteClientConfig { + if (!import.meta.env.VITE_ALGOD_SERVER) { + throw new Error('Attempt to get default algod configuration without specifying VITE_ALGOD_SERVER in the environment variables') + } + + return { + server: import.meta.env.VITE_ALGOD_SERVER, + port: import.meta.env.VITE_ALGOD_PORT, + token: import.meta.env.VITE_ALGOD_TOKEN, + network: import.meta.env.VITE_ALGOD_NETWORK, + } +} + +export function getIndexerConfigFromViteEnvironment(): AlgoViteClientConfig { + if (!import.meta.env.VITE_INDEXER_SERVER) { + throw new Error('Attempt to get default algod configuration without specifying VITE_INDEXER_SERVER in the environment variables') + } + + return { + server: import.meta.env.VITE_INDEXER_SERVER, + port: import.meta.env.VITE_INDEXER_PORT, + token: import.meta.env.VITE_INDEXER_TOKEN, + network: import.meta.env.VITE_ALGOD_NETWORK, + } +} + +export function getKmdConfigFromViteEnvironment(): AlgoViteKMDConfig { + if (!import.meta.env.VITE_KMD_SERVER) { + throw new Error('Attempt to get default kmd configuration without specifying VITE_KMD_SERVER in the environment variables') + } + + return { + server: import.meta.env.VITE_KMD_SERVER, + port: import.meta.env.VITE_KMD_PORT, + token: import.meta.env.VITE_KMD_TOKEN, + wallet: import.meta.env.VITE_KMD_WALLET, + password: import.meta.env.VITE_KMD_PASSWORD, + } +} diff --git a/tests_generated/test_default_preset/src/vite-env.d.ts b/tests_generated/test_default_preset/src/vite-env.d.ts new file mode 100644 index 0000000..67c2d30 --- /dev/null +++ b/tests_generated/test_default_preset/src/vite-env.d.ts @@ -0,0 +1,24 @@ +/// + +interface ImportMetaEnv { + readonly VITE_ENVIRONMENT: string + + readonly VITE_ALGOD_TOKEN: string + readonly VITE_ALGOD_SERVER: string + readonly VITE_ALGOD_PORT: string + readonly VITE_ALGOD_NETWORK: string + + readonly VITE_INDEXER_TOKEN: string + readonly VITE_INDEXER_SERVER: string + readonly VITE_INDEXER_PORT: string + + readonly VITE_KMD_TOKEN: string + readonly VITE_KMD_SERVER: string + readonly VITE_KMD_PORT: string + readonly VITE_KMD_PASSWORD: string + readonly VITE_KMD_WALLET: string +} + +interface ImportMeta { + readonly env: ImportMetaEnv +} diff --git a/tests_generated/test_default_preset/tailwind.config.js b/tests_generated/test_default_preset/tailwind.config.js new file mode 100644 index 0000000..a9f7a95 --- /dev/null +++ b/tests_generated/test_default_preset/tailwind.config.js @@ -0,0 +1,11 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: ['./src/**/*.{js,ts,jsx,tsx}'], + theme: { + extend: {}, + }, + daisyui: { + themes: ['lofi'], + }, + plugins: [require('daisyui')], + } diff --git a/tests_generated/test_default_preset/tests/example.spec.ts b/tests_generated/test_default_preset/tests/example.spec.ts new file mode 100644 index 0000000..df83322 --- /dev/null +++ b/tests_generated/test_default_preset/tests/example.spec.ts @@ -0,0 +1,38 @@ +import { randomAccount } from '@algorandfoundation/algokit-utils' +import { expect, test } from '@playwright/test' + +test.beforeEach(async ({ page }) => { + await page.goto('http://localhost:5173/') +}) + +test('has title', async ({ page }) => { + // Expect a title "to contain" a substring. + await expect(page).toHaveTitle('AlgoKit React Template') +}) + +test('get started link', async ({ page }) => { + await expect(page.getByTestId('getting-started')).toHaveText('Getting started') +}) + +test('authentication and dummy payment transaction', async ({ page }) => { + page.on('dialog', async (dialog) => { + dialog.message() === 'KMD password' ? await dialog.accept() : await dialog.dismiss() + }) + + // 1. Must be able to connect to a KMD wallet provider + await page.getByTestId('connect-wallet').click() + await page.getByTestId('kmd-connect').click() + await page.getByTestId('close-wallet-modal').click() + + // 2. Must be able to send a dummy payment transaction + await page.getByTestId('transactions-demo').click() + + const dummyAccount = randomAccount() + await page.getByTestId('receiver-address').fill(dummyAccount.addr) + await page.getByTestId('send-algo').click() + + // 3. Must be able to see a notification that the transaction was sent + const notification = await page.getByText('Transaction sent:') + await notification.waitFor() + expect(notification).toBeTruthy() +}) diff --git a/tests_generated/test_default_preset/tsconfig.json b/tests_generated/test_default_preset/tsconfig.json new file mode 100644 index 0000000..5cde02a --- /dev/null +++ b/tests_generated/test_default_preset/tsconfig.json @@ -0,0 +1,38 @@ +{ + "compilerOptions": { + "target": "ES2020" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */, + "module": "ES2022" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */, + "declaration": true /* Generates corresponding '.d.ts' file. */, + "declarationMap": true /* Generates a sourcemap for each corresponding '.d.ts' file. */, + "sourceMap": true /* Generates corresponding '.map' file. */, + "strict": true /* Enable all strict type-checking options. */, + "noImplicitReturns": true /* Report error when not all code paths in function return a value. */, + "noFallthroughCasesInSwitch": true /* Report errors for fallthrough cases in switch statement. */, + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, + "experimentalDecorators": true /* Enables experimental support for ES7 decorators. */, + "emitDecoratorMetadata": true /* Enables experimental support for emitting type metadata for decorators. */, + "skipLibCheck": true /* Skip type checking of declaration files. */, + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */, + "allowJs": false, + "allowSyntheticDefaultImports": true, + "moduleResolution": "Node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + "outDir": "./dist/" + }, + "include": [ + "src/**/*.ts", + "src/**/*.tsx", + "vite.config.js", + "src/utils/ellipseAddress.spec.tsx", + "src/utils/ellipseAddress.spec.tsx", + "src/main.tsx", + ], + "references": [ + { + "path": "./tsconfig.node.json" + } + ] +} diff --git a/tests_generated/test_default_preset/tsconfig.node.json b/tests_generated/test_default_preset/tsconfig.node.json new file mode 100644 index 0000000..9d31e2a --- /dev/null +++ b/tests_generated/test_default_preset/tsconfig.node.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "composite": true, + "module": "ESNext", + "moduleResolution": "Node", + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/tests_generated/test_default_preset/vite.config.ts b/tests_generated/test_default_preset/vite.config.ts new file mode 100644 index 0000000..5e5b6ee --- /dev/null +++ b/tests_generated/test_default_preset/vite.config.ts @@ -0,0 +1,7 @@ +import react from '@vitejs/plugin-react-swc' +import { defineConfig } from 'vite' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], +})