diff --git a/.gitignore b/.gitignore index d3b4daac04d..335efdc5586 100644 --- a/.gitignore +++ b/.gitignore @@ -111,3 +111,6 @@ tsconfig.tsbuildinfo # Yalc .yalc yalc.lock + +# Local https certificate/key +config/webpack/*.pem diff --git a/README.md b/README.md index fce7cee8dcd..fdbf82df381 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ #### Table of Contents * [Local Development](#local-development) +* [Testing on browsers on simulators and emulators](#testing-on-browsers-on-simulators-and-emulators) * [Running The Tests](#running-the-tests) * [Debugging](#debugging) * [App Structure and Conventions](#app-structure-and-conventions) @@ -34,12 +35,22 @@ These instructions should get you set up ready to work on New Expensify 🙌 1. Install `nvm` then `node` & `npm`: `brew install nvm && nvm install` 2. Install `watchman`: `brew install watchman` 3. Install dependencies: `npm install` +4. Install `mkcert`: `brew install mkcert` followed by `npm run setup-https`. If you are not using macOS, follow the instructions [here](https://github.com/FiloSottile/mkcert?tab=readme-ov-file#installation). +5. Create a host entry in your local hosts file, `/etc/hosts` for dev.new.expensify.com pointing to localhost: +``` +127.0.0.1 dev.new.expensify.com +``` You can use any IDE or code editing tool for developing on any platform. Use your favorite! ## Recommended `node` setup In order to have more consistent builds, we use a strict `node` and `npm` version as defined in the `package.json` `engines` field and `.nvmrc` file. `npm install` will fail if you do not use the version defined, so it is recommended to install `node` via `nvm` for easy node version management. Automatic `node` version switching can be installed for [`zsh`](https://github.com/nvm-sh/nvm#zsh) or [`bash`](https://github.com/nvm-sh/nvm#bash) using `nvm`. +## Configuring HTTPS +The webpack development server now uses https. If you're using a mac, you can simply run `npm run setup-https`. + +If you're using another operating system, you will need to ensure `mkcert` is installed, and then follow the instructions in the repository to generate certificates valid for `new.expesify.com.dev` and `localhost`. The certificate should be named `certificate.pem` and the key should be named `key.pem`. They should be placed in `config/webpack`. + ## Running the web app 🕸 * To run the **development web app**: `npm run web` * Changes applied to Javascript will be applied automatically via WebPack as configured in `webpack.dev.js` @@ -103,6 +114,43 @@ variables referenced here get updated since your local `.env` file is ignored. ---- +# Testing on browsers in simulators and emulators + +The development server is reached through the HTTPS protocol, and any client that access the development server needs a certificate. + +You create this certificate by following the instructions in [`Configuring HTTPS`](#configuring-https) of this readme. When accessing the website served from the development server on browsers in iOS simulator or Android emulator, these virtual devices need to have the same certificate installed. Follow the steps below to install them. + +#### Pre-requisite for Android flow +1. Open any emulator using Android Studio +2. Use `adb push "$(mkcert -CAROOT)/rootCA.pem" /storage/emulated/0/Download/` to push certificate to install in Download folder. +3. Install the certificate as CA certificate from the settings. On the Android emulator, this option can be found in Settings > Security > Encryption & Credentials > Install a certificate > CA certificate. +4. Close the emulator. + +Note - If you want to run app on `https://127.0.0.1:8082`, then just install the certificate and use `adb reverse tcp:8082 tcp:8082` on every startup. + +#### Android Flow +1. Run `npm run setupNewDotWebForEmulators android` +2. Select the emulator you want to run if prompted. (If single emulator is available, then it will open automatically) +3. Let the script execute till the message `🎉 Done!`. + +Note - If you want to run app on `https://dev.new.expensify.com:8082`, then just do the Android flow and use `npm run startAndroidEmulator` to start the Android Emulator every time (It will configure the emulator). + + +Possible Scenario: +The flow may fail to root with error `adbd cannot run as root in production builds`. In this case, please refer to https://stackoverflow.com/a/45668555. Or use `https://127.0.0.1:8082` for less hassle. + +#### iOS Flow +1. Run `npm run setupNewDotWebForEmulators ios` +2. Select the emulator you want to run if prompted. (If single emulator is available, then it will open automatically) +3. Let the script execute till the message `🎉 Done!`. + +#### All Flow +1. Run `npm run setupNewDotWebForEmulators all` or `npm run setupNewDotWebForEmulators` +2. Check if the iOS flow runs first and then Android flow runs. +3. Let the script execute till the message `🎉 Done!`. + +---- + # Running the tests ## Unit tests Unit tests are valuable when you want to test one component. They should be short, fast, and ideally only test one thing. diff --git a/config/webpack/webpack.dev.js b/config/webpack/webpack.dev.js index 19999491395..e28383eff55 100644 --- a/config/webpack/webpack.dev.js +++ b/config/webpack/webpack.dev.js @@ -44,6 +44,14 @@ module.exports = (env = {}) => ...proxySettings, historyApiFallback: true, port, + host: 'dev.new.expensify.com', + server: { + type: 'https', + options: { + key: path.join(__dirname, 'key.pem'), + cert: path.join(__dirname, 'certificate.pem'), + }, + }, }, plugins: [ new DefinePlugin({ diff --git a/contributingGuides/APPLE_GOOGLE_SIGNIN.md b/contributingGuides/APPLE_GOOGLE_SIGNIN.md index 9032a99dfbb..3ade13554bd 100644 --- a/contributingGuides/APPLE_GOOGLE_SIGNIN.md +++ b/contributingGuides/APPLE_GOOGLE_SIGNIN.md @@ -161,10 +161,10 @@ function beginAppleSignIn(idToken) { You can use any SSH tunneling service that allows you to configure custom subdomains so that we have a consistent address to use. We'll use ngrok in these examples, but ngrok requires a paid account for this. If you need a free option, try serveo.net. -After you've set ngrok up to be able to run on your machine (requires configuring a key with the command line tool, instructions provided by the ngrok website after you create an account), test hosting the web app on a custom subdomain. This example assumes the development web app is running at `localhost:8082`: +After you've set ngrok up to be able to run on your machine (requires configuring a key with the command line tool, instructions provided by the ngrok website after you create an account), test hosting the web app on a custom subdomain. This example assumes the development web app is running at `dev.new.expensify.com:8082`: ``` -ngrok http 8082 --host-header="localhost:8082" --subdomain=mysubdomain +ngrok http 8082 --host-header="dev.new.expensify.com:8082" --subdomain=mysubdomain ``` The `--host-header` flag is there to avoid webpack errors with header validation. In addition, add `allowedHosts: 'all'` to the dev server config in `webpack.dev.js`: diff --git a/desktop/main.js b/desktop/main.js index 5e184d529af..7ab8d748b54 100644 --- a/desktop/main.js +++ b/desktop/main.js @@ -85,7 +85,7 @@ _.assign(console, log.functions); // until it detects that it has been upgraded to the correct version. const EXPECTED_UPDATE_VERSION_FLAG = '--expected-update-version'; -const APP_DOMAIN = __DEV__ ? `http://localhost:${port}` : 'app://-'; +const APP_DOMAIN = __DEV__ ? `https://dev.new.expensify.com:${port}` : 'app://-'; let expectedUpdateVersion; for (let i = 0; i < process.argv.length; i++) { @@ -221,7 +221,7 @@ const mainWindow = () => { let deeplinkUrl; let browserWindow; - const loadURL = __DEV__ ? (win) => win.loadURL(`http://localhost:${port}`) : serve({directory: `${__dirname}/www`}); + const loadURL = __DEV__ ? (win) => win.loadURL(`https://dev.new.expensify.com:${port}`) : serve({directory: `${__dirname}/www`}); // Prod and staging set the icon in the electron-builder config, so only update it here for dev if (__DEV__) { diff --git a/desktop/start.js b/desktop/start.js index d9ec59b71c8..05a1b031350 100644 --- a/desktop/start.js +++ b/desktop/start.js @@ -32,7 +32,7 @@ portfinder env, }, { - command: `wait-port localhost:${port} && npx electronmon ./desktop/dev.js`, + command: `wait-port dev.new.expensify.com:${port} && npx electronmon ./desktop/dev.js`, name: 'Electron', prefixColor: 'cyan.dim', env, diff --git a/docs/_includes/CONST.html b/docs/_includes/CONST.html index 4b87f87931d..231423f1058 100644 --- a/docs/_includes/CONST.html +++ b/docs/_includes/CONST.html @@ -1,7 +1,7 @@ {% if jekyll.environment == "production" %} {% assign MAIN_SITE_URL = "https://new.expensify.com" %} {% else %} - {% assign MAIN_SITE_URL = "http://localhost:8082" %} + {% assign MAIN_SITE_URL = "https://dev.new.expensify.com:8082" %} {% endif %} {% capture CONCIERGE_CHAT_URL %}{{MAIN_SITE_URL}}/concierge{% endcapture %} diff --git a/package.json b/package.json index d013caa1c40..c86ae5dfe26 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,8 @@ "test:e2e": "node tests/e2e/testRunner.js --development", "gh-actions-unused-styles": "./.github/scripts/findUnusedKeys.sh", "workflow-test": "./workflow_tests/scripts/runWorkflowTests.sh", - "workflow-test:generate": "node workflow_tests/utils/preGenerateTest.js" + "workflow-test:generate": "node workflow_tests/utils/preGenerateTest.js", + "setup-https": "mkcert -install && mkcert -cert-file config/webpack/certificate.pem -key-file config/webpack/key.pem dev.new.expensify.com localhost 127.0.0.1" }, "dependencies": { "@expensify/react-native-web": "0.18.15", diff --git a/src/CONST.ts b/src/CONST.ts index dbe47c6ed1a..cc3c7e0922f 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -448,7 +448,7 @@ const CONST = { ONFIDO_TERMS_OF_SERVICE_URL: 'https://onfido.com/terms-of-service/', // Use Environment.getEnvironmentURL to get the complete URL with port number - DEV_NEW_EXPENSIFY_URL: 'http://localhost:', + DEV_NEW_EXPENSIFY_URL: 'https://dev.new.expensify.com:', SIGN_IN_FORM_WIDTH: 300, diff --git a/src/libs/Navigation/linkingConfig.js b/src/libs/Navigation/linkingConfig.js index 533dbf51633..86c3e67cab2 100644 --- a/src/libs/Navigation/linkingConfig.js +++ b/src/libs/Navigation/linkingConfig.js @@ -4,7 +4,7 @@ import CONST from '../../CONST'; import NAVIGATORS from '../../NAVIGATORS'; export default { - prefixes: ['new-expensify://', 'https://www.expensify.cash', 'https://staging.expensify.cash', 'http://localhost', CONST.NEW_EXPENSIFY_URL, CONST.STAGING_NEW_EXPENSIFY_URL], + prefixes: ['new-expensify://', 'https://www.expensify.cash', 'https://staging.expensify.cash', 'https://dev.new.expensify.com', CONST.NEW_EXPENSIFY_URL, CONST.STAGING_NEW_EXPENSIFY_URL], config: { initialRouteName: SCREENS.HOME, screens: { diff --git a/tests/unit/ReportUtilsTest.js b/tests/unit/ReportUtilsTest.js index 24397a04a0e..40a0ea31ce8 100644 --- a/tests/unit/ReportUtilsTest.js +++ b/tests/unit/ReportUtilsTest.js @@ -503,8 +503,7 @@ describe('ReportUtils', () => { expect(ReportUtils.getReportIDFromLink('new-expensify://r/75431276')).toBe('75431276'); expect(ReportUtils.getReportIDFromLink('https://www.expensify.cash/r/75431276')).toBe('75431276'); expect(ReportUtils.getReportIDFromLink('https://staging.new.expensify.com/r/75431276')).toBe('75431276'); - expect(ReportUtils.getReportIDFromLink('http://localhost/r/75431276')).toBe('75431276'); - expect(ReportUtils.getReportIDFromLink('http://localhost:8080/r/75431276')).toBe('75431276'); + expect(ReportUtils.getReportIDFromLink('https://dev.new.expensify.com/r/75431276')).toBe('75431276'); expect(ReportUtils.getReportIDFromLink('https://staging.expensify.cash/r/75431276')).toBe('75431276'); expect(ReportUtils.getReportIDFromLink('https://new.expensify.com/r/75431276')).toBe('75431276'); });