Commit dbd4452d authored by tom goriunov's avatar tom goriunov Committed by GitHub

workaround for ENV replacement script (#1212)

* base implementation of client script with envs values

* better ENVs setup for pw tests

* fix tests
parent 01c7603b
......@@ -13,6 +13,7 @@
/.next/
/out/
/public/assets/
/public/envs.js
# production
/build
......
......@@ -47,9 +47,9 @@ WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# Generate .env.production with ENVs placeholders and save build args into .env file
COPY --chmod=+x ./deploy/scripts/make_envs_template.sh ./
RUN ./make_envs_template.sh ./docs/ENVS.md
# Generate .env.registry with ENVs list and save build args into .env file
COPY --chmod=+x ./deploy/scripts/collect_envs.sh ./
RUN ./collect_envs.sh ./docs/ENVS.md
# Next.js collects completely anonymous telemetry data about general usage.
# Learn more here: https://nextjs.org/telemetry
......@@ -98,8 +98,9 @@ COPY --from=builder /app/deploy/tools/feature-reporter/index.js ./feature-report
# Copy scripts
## Entripoint
COPY --chmod=+x ./deploy/scripts/entrypoint.sh .
## ENV replacer
COPY --chmod=+x ./deploy/scripts/replace_envs.sh .
## ENV validator and client script maker
COPY --chmod=+x ./deploy/scripts/validate_envs.sh .
COPY --chmod=+x ./deploy/scripts/make_envs_script.sh .
## Assets downloader
COPY --chmod=+x ./deploy/scripts/download_assets.sh .
## Favicon generator
......@@ -109,7 +110,7 @@ RUN ["chmod", "-R", "777", "./deploy/tools/favicon-generator"]
RUN ["chmod", "-R", "777", "./public"]
# Copy ENVs files
COPY --from=builder /app/.env.production .
COPY --from=builder /app/.env.registry .
COPY --from=builder /app/.env .
# Automatically leverage output traces to reduce image size
......
......@@ -2,9 +2,9 @@ import stripTrailingSlash from 'lib/stripTrailingSlash';
import { getEnvValue } from './utils';
const apiHost = getEnvValue(process.env.NEXT_PUBLIC_API_HOST);
const apiSchema = getEnvValue(process.env.NEXT_PUBLIC_API_PROTOCOL) || 'https';
const apiPort = getEnvValue(process.env.NEXT_PUBLIC_API_PORT);
const apiHost = getEnvValue('NEXT_PUBLIC_API_HOST');
const apiSchema = getEnvValue('NEXT_PUBLIC_API_PROTOCOL') || 'https';
const apiPort = getEnvValue('NEXT_PUBLIC_API_PORT');
const apiEndpoint = [
apiSchema || 'https',
'://',
......@@ -12,7 +12,7 @@ const apiEndpoint = [
apiPort && ':' + apiPort,
].filter(Boolean).join('');
const socketSchema = getEnvValue(process.env.NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL) || 'wss';
const socketSchema = getEnvValue('NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL') || 'wss';
const socketEndpoint = [
socketSchema,
'://',
......@@ -24,7 +24,7 @@ const api = Object.freeze({
host: apiHost,
endpoint: apiEndpoint,
socket: socketEndpoint,
basePath: stripTrailingSlash(getEnvValue(process.env.NEXT_PUBLIC_API_BASE_PATH) || ''),
basePath: stripTrailingSlash(getEnvValue('NEXT_PUBLIC_API_BASE_PATH') || ''),
});
export default api;
import { getEnvValue } from './utils';
const appPort = getEnvValue(process.env.NEXT_PUBLIC_APP_PORT);
const appSchema = getEnvValue(process.env.NEXT_PUBLIC_APP_PROTOCOL);
const appHost = getEnvValue(process.env.NEXT_PUBLIC_APP_HOST);
const appPort = getEnvValue('NEXT_PUBLIC_APP_PORT');
const appSchema = getEnvValue('NEXT_PUBLIC_APP_PROTOCOL');
const appHost = getEnvValue('NEXT_PUBLIC_APP_HOST');
const baseUrl = [
appSchema || 'https',
'://',
......@@ -17,7 +17,7 @@ const app = Object.freeze({
host: appHost,
port: appPort,
baseUrl,
useProxy: getEnvValue(process.env.NEXT_PUBLIC_USE_NEXT_JS_PROXY) === 'true',
useProxy: getEnvValue('NEXT_PUBLIC_USE_NEXT_JS_PROXY') === 'true',
});
export default app;
......@@ -3,20 +3,20 @@ import { getEnvValue } from './utils';
const DEFAULT_CURRENCY_DECIMALS = 18;
const chain = Object.freeze({
id: getEnvValue(process.env.NEXT_PUBLIC_NETWORK_ID),
name: getEnvValue(process.env.NEXT_PUBLIC_NETWORK_NAME),
shortName: getEnvValue(process.env.NEXT_PUBLIC_NETWORK_SHORT_NAME),
id: getEnvValue('NEXT_PUBLIC_NETWORK_ID'),
name: getEnvValue('NEXT_PUBLIC_NETWORK_NAME'),
shortName: getEnvValue('NEXT_PUBLIC_NETWORK_SHORT_NAME'),
currency: {
name: getEnvValue(process.env.NEXT_PUBLIC_NETWORK_CURRENCY_NAME),
symbol: getEnvValue(process.env.NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL),
decimals: Number(getEnvValue(process.env.NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS)) || DEFAULT_CURRENCY_DECIMALS,
name: getEnvValue('NEXT_PUBLIC_NETWORK_CURRENCY_NAME'),
symbol: getEnvValue('NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL'),
decimals: Number(getEnvValue('NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS')) || DEFAULT_CURRENCY_DECIMALS,
},
governanceToken: {
symbol: getEnvValue(process.env.NEXT_PUBLIC_NETWORK_GOVERNANCE_TOKEN_SYMBOL),
symbol: getEnvValue('NEXT_PUBLIC_NETWORK_GOVERNANCE_TOKEN_SYMBOL'),
},
rpcUrl: getEnvValue(process.env.NEXT_PUBLIC_NETWORK_RPC_URL),
isTestnet: getEnvValue(process.env.NEXT_PUBLIC_IS_TESTNET) === 'true',
verificationType: getEnvValue(process.env.NEXT_PUBLIC_NETWORK_VERIFICATION_TYPE) || 'mining',
rpcUrl: getEnvValue('NEXT_PUBLIC_NETWORK_RPC_URL'),
isTestnet: getEnvValue('NEXT_PUBLIC_IS_TESTNET') === 'true',
verificationType: getEnvValue('NEXT_PUBLIC_NETWORK_VERIFICATION_TYPE') || 'mining',
});
export default chain;
......@@ -5,12 +5,12 @@ import stripTrailingSlash from 'lib/stripTrailingSlash';
import app from '../app';
import { getEnvValue } from '../utils';
const authUrl = stripTrailingSlash(getEnvValue(process.env.NEXT_PUBLIC_AUTH_URL) || app.baseUrl);
const authUrl = stripTrailingSlash(getEnvValue('NEXT_PUBLIC_AUTH_URL') || app.baseUrl);
const logoutUrl = (() => {
try {
const envUrl = getEnvValue(process.env.NEXT_PUBLIC_LOGOUT_URL);
const auth0ClientId = getEnvValue(process.env.NEXT_PUBLIC_AUTH0_CLIENT_ID);
const envUrl = getEnvValue('NEXT_PUBLIC_LOGOUT_URL');
const auth0ClientId = getEnvValue('NEXT_PUBLIC_AUTH0_CLIENT_ID');
const returnUrl = authUrl + '/auth/logout';
if (!envUrl || !auth0ClientId) {
......@@ -31,7 +31,7 @@ const title = 'My account';
const config: Feature<{ authUrl: string; logoutUrl: string }> = (() => {
if (
getEnvValue(process.env.NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED) === 'true' &&
getEnvValue('NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED') === 'true' &&
authUrl &&
logoutUrl
) {
......
......@@ -4,7 +4,7 @@ import { getEnvValue } from '../utils';
import account from './account';
import verifiedTokens from './verifiedTokens';
const adminServiceApiHost = getEnvValue(process.env.NEXT_PUBLIC_ADMIN_SERVICE_API_HOST);
const adminServiceApiHost = getEnvValue('NEXT_PUBLIC_ADMIN_SERVICE_API_HOST');
const title = 'Address verification in "My account"';
......
......@@ -6,7 +6,7 @@ import type { AdBannerProviders } from 'types/client/adProviders';
import { getEnvValue, parseEnvJson } from '../utils';
const provider: AdBannerProviders = (() => {
const envValue = getEnvValue(process.env.NEXT_PUBLIC_AD_BANNER_PROVIDER) as AdBannerProviders;
const envValue = getEnvValue('NEXT_PUBLIC_AD_BANNER_PROVIDER') as AdBannerProviders;
return envValue && SUPPORTED_AD_BANNER_PROVIDERS.includes(envValue) ? envValue : 'slise';
})();
......@@ -27,8 +27,8 @@ type AdsBannerFeaturePayload = {
const config: Feature<AdsBannerFeaturePayload> = (() => {
if (provider === 'adbutler') {
const desktopConfig = parseEnvJson<AdButlerConfig>(getEnvValue(process.env.NEXT_PUBLIC_AD_ADBUTLER_CONFIG_DESKTOP));
const mobileConfig = parseEnvJson<AdButlerConfig>(getEnvValue(process.env.NEXT_PUBLIC_AD_ADBUTLER_CONFIG_MOBILE));
const desktopConfig = parseEnvJson<AdButlerConfig>(getEnvValue('NEXT_PUBLIC_AD_ADBUTLER_CONFIG_DESKTOP'));
const mobileConfig = parseEnvJson<AdButlerConfig>(getEnvValue('NEXT_PUBLIC_AD_ADBUTLER_CONFIG_MOBILE'));
if (desktopConfig && mobileConfig) {
return Object.freeze({
......
......@@ -5,7 +5,7 @@ import type { AdTextProviders } from 'types/client/adProviders';
import { getEnvValue } from '../utils';
const provider: AdTextProviders = (() => {
const envValue = getEnvValue(process.env.NEXT_PUBLIC_AD_TEXT_PROVIDER) as AdTextProviders;
const envValue = getEnvValue('NEXT_PUBLIC_AD_TEXT_PROVIDER') as AdTextProviders;
return envValue && SUPPORTED_AD_BANNER_PROVIDERS.includes(envValue) ? envValue : 'coinzilla';
})();
......
......@@ -5,14 +5,14 @@ import { getEnvValue } from '../utils';
const title = 'Beacon chain';
const config: Feature<{ currency: { symbol: string } }> = (() => {
if (getEnvValue(process.env.NEXT_PUBLIC_HAS_BEACON_CHAIN) === 'true') {
if (getEnvValue('NEXT_PUBLIC_HAS_BEACON_CHAIN') === 'true') {
return Object.freeze({
title,
isEnabled: true,
currency: {
symbol:
getEnvValue(process.env.NEXT_PUBLIC_BEACON_CHAIN_CURRENCY_SYMBOL) ||
getEnvValue(process.env.NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL) ||
getEnvValue('NEXT_PUBLIC_BEACON_CHAIN_CURRENCY_SYMBOL') ||
getEnvValue('NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL') ||
'', // maybe we need some other default value here
},
});
......
......@@ -3,7 +3,7 @@ import type { Feature } from './types';
import chain from '../chain';
import { getEnvValue } from '../utils';
const walletConnectProjectId = getEnvValue(process.env.NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID);
const walletConnectProjectId = getEnvValue('NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID');
const title = 'Blockchain interaction (writing to contract, etc.)';
......
......@@ -2,7 +2,7 @@ import type { Feature } from './types';
import { getEnvValue } from '../utils';
const propertyId = getEnvValue(process.env.NEXT_PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID);
const propertyId = getEnvValue('NEXT_PUBLIC_GOOGLE_ANALYTICS_PROPERTY_ID');
const title = 'Google analytics';
......
......@@ -2,7 +2,7 @@ import type { Feature } from './types';
import { getEnvValue } from '../utils';
const defaultTxHash = getEnvValue(process.env.NEXT_PUBLIC_GRAPHIQL_TRANSACTION);
const defaultTxHash = getEnvValue('NEXT_PUBLIC_GRAPHIQL_TRANSACTION');
const title = 'GraphQL API documentation';
......
......@@ -4,8 +4,8 @@ import chain from '../chain';
import { getEnvValue, getExternalAssetFilePath } from '../utils';
// config file will be downloaded at run-time and saved in the public folder
const configUrl = getExternalAssetFilePath('NEXT_PUBLIC_MARKETPLACE_CONFIG_URL', process.env.NEXT_PUBLIC_MARKETPLACE_CONFIG_URL);
const submitFormUrl = getEnvValue(process.env.NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM);
const configUrl = getExternalAssetFilePath('NEXT_PUBLIC_MARKETPLACE_CONFIG_URL');
const submitFormUrl = getEnvValue('NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM');
const title = 'Marketplace';
......
......@@ -2,7 +2,7 @@ import type { Feature } from './types';
import { getEnvValue } from '../utils';
const projectToken = getEnvValue(process.env.NEXT_PUBLIC_MIXPANEL_PROJECT_TOKEN);
const projectToken = getEnvValue('NEXT_PUBLIC_MIXPANEL_PROJECT_TOKEN');
const title = 'Mixpanel analytics';
......
......@@ -2,7 +2,7 @@ import type { Feature } from './types';
import { getEnvValue } from '../utils';
const specUrl = getEnvValue(process.env.NEXT_PUBLIC_API_SPEC_URL) || `https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml`;
const specUrl = getEnvValue('NEXT_PUBLIC_API_SPEC_URL') || `https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml`;
const title = 'REST API documentation';
......
......@@ -5,11 +5,11 @@ import { getEnvValue } from '../utils';
const title = 'Rollup (L2) chain';
const config: Feature<{ L1BaseUrl: string; withdrawalUrl: string }> = (() => {
const L1BaseUrl = getEnvValue(process.env.NEXT_PUBLIC_L1_BASE_URL);
const withdrawalUrl = getEnvValue(process.env.NEXT_PUBLIC_L2_WITHDRAWAL_URL);
const L1BaseUrl = getEnvValue('NEXT_PUBLIC_L1_BASE_URL');
const withdrawalUrl = getEnvValue('NEXT_PUBLIC_L2_WITHDRAWAL_URL');
if (
getEnvValue(process.env.NEXT_PUBLIC_IS_L2_NETWORK) === 'true' &&
getEnvValue('NEXT_PUBLIC_IS_L2_NETWORK') === 'true' &&
L1BaseUrl &&
withdrawalUrl
) {
......
......@@ -2,7 +2,7 @@ import type { Feature } from './types';
import { getEnvValue } from '../utils';
const dsn = getEnvValue(process.env.NEXT_PUBLIC_SENTRY_DSN);
const dsn = getEnvValue('NEXT_PUBLIC_SENTRY_DSN');
const title = 'Sentry error monitoring';
......@@ -12,9 +12,9 @@ const config: Feature<{ dsn: string; environment: string | undefined; cspReportU
title,
isEnabled: true,
dsn,
environment: getEnvValue(process.env.NEXT_PUBLIC_APP_ENV) || getEnvValue(process.env.NODE_ENV),
cspReportUrl: getEnvValue(process.env.SENTRY_CSP_REPORT_URI),
instance: getEnvValue(process.env.NEXT_PUBLIC_APP_INSTANCE),
environment: getEnvValue('NEXT_PUBLIC_APP_ENV') || getEnvValue('NODE_ENV'),
cspReportUrl: getEnvValue('SENTRY_CSP_REPORT_URI'),
instance: getEnvValue('NEXT_PUBLIC_APP_INSTANCE'),
});
}
......
......@@ -2,7 +2,7 @@ import type { Feature } from './types';
import { getEnvValue } from '../utils';
const apiEndpoint = getEnvValue(process.env.NEXT_PUBLIC_VISUALIZE_API_HOST);
const apiEndpoint = getEnvValue('NEXT_PUBLIC_VISUALIZE_API_HOST');
const title = 'Solidity to UML diagrams';
......
......@@ -2,7 +2,7 @@ import type { Feature } from './types';
import { getEnvValue } from '../utils';
const apiEndpoint = getEnvValue(process.env.NEXT_PUBLIC_STATS_API_HOST);
const apiEndpoint = getEnvValue('NEXT_PUBLIC_STATS_API_HOST');
const title = 'Blockchain statistics';
......
......@@ -2,7 +2,7 @@ import type { Feature } from './types';
import { getEnvValue } from '../utils';
const contractInfoApiHost = getEnvValue(process.env.NEXT_PUBLIC_CONTRACT_INFO_API_HOST);
const contractInfoApiHost = getEnvValue('NEXT_PUBLIC_CONTRACT_INFO_API_HOST');
const title = 'Verified tokens info';
......
......@@ -5,7 +5,7 @@ import type { WalletType } from 'types/client/wallets';
import { getEnvValue, parseEnvJson } from '../utils';
const wallets = ((): Array<WalletType> | undefined => {
const envValue = getEnvValue(process.env.NEXT_PUBLIC_WEB3_WALLETS);
const envValue = getEnvValue('NEXT_PUBLIC_WEB3_WALLETS');
if (envValue === 'none') {
return;
}
......@@ -28,7 +28,7 @@ const config: Feature<{ wallets: Array<WalletType>; addToken: { isDisabled: bool
isEnabled: true,
wallets,
addToken: {
isDisabled: getEnvValue(process.env.NEXT_PUBLIC_WEB3_DISABLE_ADD_TOKEN_TO_WALLET) === 'true',
isDisabled: getEnvValue('NEXT_PUBLIC_WEB3_DISABLE_ADD_TOKEN_TO_WALLET') === 'true',
},
addNetwork: {},
});
......
......@@ -4,10 +4,10 @@ import { getEnvValue, getExternalAssetFilePath } from './utils';
const defaultImageUrl = app.baseUrl + '/static/og_placeholder.png';
const meta = Object.freeze({
promoteBlockscoutInTitle: getEnvValue(process.env.NEXT_PUBLIC_PROMOTE_BLOCKSCOUT_IN_TITLE) || 'true',
promoteBlockscoutInTitle: getEnvValue('NEXT_PUBLIC_PROMOTE_BLOCKSCOUT_IN_TITLE') || 'true',
og: {
description: getEnvValue(process.env.NEXT_PUBLIC_OG_DESCRIPTION) || '',
imageUrl: getExternalAssetFilePath('NEXT_PUBLIC_OG_IMAGE_URL', process.env.NEXT_PUBLIC_OG_IMAGE_URL) || defaultImageUrl,
description: getEnvValue('NEXT_PUBLIC_OG_DESCRIPTION') || '',
imageUrl: getExternalAssetFilePath('NEXT_PUBLIC_OG_IMAGE_URL') || defaultImageUrl,
},
});
......
......@@ -2,6 +2,6 @@ import { getEnvValue } from './utils';
export default Object.freeze({
reCaptcha: {
siteKey: getEnvValue(process.env.NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY),
siteKey: getEnvValue('NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY'),
},
});
......@@ -11,36 +11,36 @@ const HOMEPAGE_PLATE_BACKGROUND_DEFAULT = 'radial-gradient(103.03% 103.03% at 0%
const UI = Object.freeze({
sidebar: {
logo: {
'default': getExternalAssetFilePath('NEXT_PUBLIC_NETWORK_LOGO', process.env.NEXT_PUBLIC_NETWORK_LOGO),
dark: getExternalAssetFilePath('NEXT_PUBLIC_NETWORK_LOGO_DARK', process.env.NEXT_PUBLIC_NETWORK_LOGO_DARK),
'default': getExternalAssetFilePath('NEXT_PUBLIC_NETWORK_LOGO'),
dark: getExternalAssetFilePath('NEXT_PUBLIC_NETWORK_LOGO_DARK'),
},
icon: {
'default': getExternalAssetFilePath('NEXT_PUBLIC_NETWORK_ICON', process.env.NEXT_PUBLIC_NETWORK_ICON),
dark: getExternalAssetFilePath('NEXT_PUBLIC_NETWORK_ICON_DARK', process.env.NEXT_PUBLIC_NETWORK_ICON_DARK),
'default': getExternalAssetFilePath('NEXT_PUBLIC_NETWORK_ICON'),
dark: getExternalAssetFilePath('NEXT_PUBLIC_NETWORK_ICON_DARK'),
},
otherLinks: parseEnvJson<Array<NavItemExternal>>(getEnvValue(process.env.NEXT_PUBLIC_OTHER_LINKS)) || [],
featuredNetworks: getExternalAssetFilePath('NEXT_PUBLIC_FEATURED_NETWORKS', process.env.NEXT_PUBLIC_FEATURED_NETWORKS),
otherLinks: parseEnvJson<Array<NavItemExternal>>(getEnvValue('NEXT_PUBLIC_OTHER_LINKS')) || [],
featuredNetworks: getExternalAssetFilePath('NEXT_PUBLIC_FEATURED_NETWORKS'),
},
footer: {
links: getExternalAssetFilePath('NEXT_PUBLIC_FOOTER_LINKS', process.env.NEXT_PUBLIC_FOOTER_LINKS),
frontendVersion: getEnvValue(process.env.NEXT_PUBLIC_GIT_TAG),
frontendCommit: getEnvValue(process.env.NEXT_PUBLIC_GIT_COMMIT_SHA),
links: getExternalAssetFilePath('NEXT_PUBLIC_FOOTER_LINKS'),
frontendVersion: getEnvValue('NEXT_PUBLIC_GIT_TAG'),
frontendCommit: getEnvValue('NEXT_PUBLIC_GIT_COMMIT_SHA'),
},
homepage: {
charts: parseEnvJson<Array<ChainIndicatorId>>(getEnvValue(process.env.NEXT_PUBLIC_HOMEPAGE_CHARTS)) || [],
charts: parseEnvJson<Array<ChainIndicatorId>>(getEnvValue('NEXT_PUBLIC_HOMEPAGE_CHARTS')) || [],
plate: {
background: getEnvValue(process.env.NEXT_PUBLIC_HOMEPAGE_PLATE_BACKGROUND) || HOMEPAGE_PLATE_BACKGROUND_DEFAULT,
textColor: getEnvValue(process.env.NEXT_PUBLIC_HOMEPAGE_PLATE_TEXT_COLOR) || 'white',
background: getEnvValue('NEXT_PUBLIC_HOMEPAGE_PLATE_BACKGROUND') || HOMEPAGE_PLATE_BACKGROUND_DEFAULT,
textColor: getEnvValue('NEXT_PUBLIC_HOMEPAGE_PLATE_TEXT_COLOR') || 'white',
},
showGasTracker: getEnvValue(process.env.NEXT_PUBLIC_HOMEPAGE_SHOW_GAS_TRACKER) === 'false' ? false : true,
showAvgBlockTime: getEnvValue(process.env.NEXT_PUBLIC_HOMEPAGE_SHOW_AVG_BLOCK_TIME) === 'false' ? false : true,
showGasTracker: getEnvValue('NEXT_PUBLIC_HOMEPAGE_SHOW_GAS_TRACKER') === 'false' ? false : true,
showAvgBlockTime: getEnvValue('NEXT_PUBLIC_HOMEPAGE_SHOW_AVG_BLOCK_TIME') === 'false' ? false : true,
},
views,
indexingAlert: {
isHidden: getEnvValue(process.env.NEXT_PUBLIC_HIDE_INDEXING_ALERT),
isHidden: getEnvValue('NEXT_PUBLIC_HIDE_INDEXING_ALERT'),
},
explorers: {
items: parseEnvJson<Array<NetworkExplorer>>(getEnvValue(process.env.NEXT_PUBLIC_NETWORK_EXPLORERS)) || [],
items: parseEnvJson<Array<NetworkExplorer>>(getEnvValue('NEXT_PUBLIC_NETWORK_EXPLORERS')) || [],
},
});
......
......@@ -4,7 +4,7 @@ import { IDENTICON_TYPES } from 'types/views/address';
import { getEnvValue } from 'configs/app/utils';
const identiconType: IdenticonType = (() => {
const value = getEnvValue(process.env.NEXT_PUBLIC_VIEWS_ADDRESS_IDENTICON_TYPE);
const value = getEnvValue('NEXT_PUBLIC_VIEWS_ADDRESS_IDENTICON_TYPE');
return IDENTICON_TYPES.find((type) => value === type) || 'jazzicon';
})();
......
......@@ -4,7 +4,7 @@ import { BLOCK_FIELDS_IDS } from 'types/views/block';
import { getEnvValue, parseEnvJson } from 'configs/app/utils';
const blockHiddenFields = (() => {
const parsedValue = parseEnvJson<Array<BlockFieldId>>(getEnvValue(process.env.NEXT_PUBLIC_VIEWS_BLOCK_HIDDEN_FIELDS)) || [];
const parsedValue = parseEnvJson<Array<BlockFieldId>>(getEnvValue('NEXT_PUBLIC_VIEWS_BLOCK_HIDDEN_FIELDS')) || [];
if (!Array.isArray(parsedValue)) {
return undefined;
......
import isBrowser from 'lib/isBrowser';
import * as regexp from 'lib/regexp';
export const getEnvValue = <T extends string>(env: T | undefined): T | undefined => env?.replaceAll('\'', '"') as T;
export const getEnvValue = (envName: string) => {
const envs = isBrowser() ? window.__envs : process.env;
if (isBrowser() && envs.NEXT_PUBLIC_APP_INSTANCE === 'pw') {
const storageValue = localStorage.getItem(envName);
if (storageValue) {
return storageValue;
}
}
return envs[envName]?.replaceAll('\'', '"');
};
export const parseEnvJson = <DataType>(env: string | undefined): DataType | null => {
try {
......@@ -10,15 +23,19 @@ export const parseEnvJson = <DataType>(env: string | undefined): DataType | null
}
};
export const getExternalAssetFilePath = (envName: string, envValue: string | undefined) => {
const parsedValue = getEnvValue(envValue);
export const getExternalAssetFilePath = (envName: string) => {
const parsedValue = getEnvValue(envName);
if (!parsedValue) {
return;
}
const fileName = envName.replace(/^NEXT_PUBLIC_/, '').replace(/_URL$/, '').toLowerCase();
const fileExtension = parsedValue.match(regexp.FILE_EXTENSION)?.[1];
return buildExternalAssetFilePath(envName, parsedValue);
};
export const buildExternalAssetFilePath = (name: string, value: string) => {
const fileName = name.replace(/^NEXT_PUBLIC_/, '').replace(/_URL$/, '').toLowerCase();
const fileExtension = value.match(regexp.FILE_EXTENSION)?.[1];
return `/assets/${ fileName }.${ fileExtension }`;
};
# Set of ENVs for Playwright components tests
#
# be aware that ALL ENVs should be present in order to make a correct variables list for the browser
# leave empty values for the ones that are not required
# app configuration
NEXT_PUBLIC_APP_PROTOCOL=http
......@@ -29,18 +26,10 @@ NEXT_PUBLIC_API_BASE_PATH=/
NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs','coin_price','market_cap']
NEXT_PUBLIC_HOMEPAGE_SHOW_AVG_BLOCK_TIME=true
NEXT_PUBLIC_HOMEPAGE_SHOW_GAS_TRACKER=true
NEXT_PUBLIC_HOMEPAGE_PLATE_BACKGROUND=
## sidebar
NEXT_PUBLIC_FEATURED_NETWORKS=
NEXT_PUBLIC_NETWORK_LOGO=
NEXT_PUBLIC_NETWORK_LOGO_DARK=
NEXT_PUBLIC_NETWORK_ICON=
NEXT_PUBLIC_NETWORK_ICON_DARK=
## footer
NEXT_PUBLIC_GIT_TAG=v1.0.11
NEXT_PUBLIC_FOOTER_LINKS=
## views
NEXT_PUBLIC_VIEWS_BLOCK_HIDDEN_FIELDS=
## misc
NEXT_PUBLIC_NETWORK_EXPLORERS=[{'title':'Bitquery','baseUrl':'https://explorer.bitquery.io/','paths':{'tx':'/goerli/tx','address':'/goerli/address','token':'/goerli/token','block':'/goerli/block'}},{'title':'Etherscan','baseUrl':'https://goerli.etherscan.io/','paths':{'tx':'/tx','address':'/address','token':'/token','block':'/block'}}]
......@@ -50,8 +39,6 @@ NEXT_PUBLIC_APP_INSTANCE=pw
NEXT_PUBLIC_MARKETPLACE_CONFIG_URL=https://localhost:3000/marketplace-config.json
NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM=https://localhost:3000/marketplace-submit-form
NEXT_PUBLIC_IS_L2_NETWORK=false
NEXT_PUBLIC_L1_BASE_URL=
NEXT_PUBLIC_L2_WITHDRAWAL_URL=
NEXT_PUBLIC_AD_BANNER_PROVIDER=slise
NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
NEXT_PUBLIC_AUTH_URL=http://localhost:3100
......@@ -61,4 +48,3 @@ NEXT_PUBLIC_STATS_API_HOST=https://localhost:3004
NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://localhost:3005
NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://localhost:3006
NEXT_PUBLIC_RE_CAPTCHA_APP_SITE_KEY=xxx
NEXT_PUBLIC_HAS_BEACON_CHAIN=
......@@ -9,11 +9,11 @@ fi
input_file="$1"
prefix="NEXT_PUBLIC_"
# Function to make the environment variables template file
# Function to make the environment variables registry file based on documentation file ENVS.md
# It will read the input file, extract all prefixed string and use them as variables names
# This variables will have placeholders for their values at buildtime which will be replaced with actual values at runtime
make_envs_template_file() {
output_file=".env.production"
# This variables will have dummy values assigned to them
make_registry_file() {
output_file=".env.registry"
# Check if file already exists and empty its content if it does
if [ -f "$output_file" ]; then
......@@ -21,7 +21,7 @@ make_envs_template_file() {
fi
grep -oE "${prefix}[[:alnum:]_]+" "$input_file" | sort -u | while IFS= read -r var_name; do
echo "$var_name=__PLACEHOLDER_FOR_${var_name}__" >> "$output_file"
echo "$var_name=__" >> "$output_file"
done
}
......@@ -41,5 +41,5 @@ save_build-time_envs() {
done
}
make_envs_template_file
make_registry_file
save_build-time_envs
\ No newline at end of file
......@@ -3,10 +3,10 @@
# Download external assets
./download_assets.sh ./public/assets
# Check run-time ENVs values integrity
node "$(dirname "$0")/envs-validator.js" "$input"
if [ $? != 0 ]; then
exit 1
# Check run-time ENVs values
./validate_envs.sh
if [ $? -ne 0 ]; then
exit 1
fi
# Generate favicons bundle
......@@ -18,8 +18,8 @@ else
fi
echo
# Execute script for replace build-time ENVs placeholders with their values at runtime
./replace_envs.sh
# Create envs.js file with run-time environment variables for the client app
./make_envs_script.sh
# Print list of enabled features
node ./feature-reporter.js
......
#!/bin/bash
echo "🌀 Creating client script with ENV values..."
# Define the output file name
output_file="./public/envs.js"
touch $output_file;
truncate -s 0 $output_file;
# Check if the .env file exists and load ENVs from it
if [ -f .env ]; then
source .env
fi
echo "window.__envs = {" >> $output_file;
# Iterate through all environment variables
for var in $(env | grep '^NEXT_PUBLIC_' | cut -d= -f1); do
# Get the value of the variable
value="${!var}"
# Write the variable name and value to the output file
echo "${var}: \"${value}\"," >> "$output_file"
done
echo "}" >> $output_file;
echo "✅ Done."
#!/bin/bash
# no verbose
set +x
# config
envFilename='.env.production'
nextFolder='./.next/'
# replacing build-stage ENVs with run-stage ENVs
# https://raphaelpralat.medium.com/system-environment-variables-in-next-js-with-docker-1f0754e04cde
function replace_envs {
# read all config file
while read line; do
# no comment or not empty
if [ "${line:0:1}" == "#" ] || [ "${line}" == "" ]; then
continue
fi
# split
configName="$(cut -d'=' -f1 <<<"$line")"
configValue="$(cut -d'=' -f2- <<<"$line")"
# get system env
envValue=$(env | grep "^$configName=" | sed "s/^$configName=//g");
# if config found
if [ -n "$configValue" ]; then
# replace all
echo "Replace: ${configValue} with: ${envValue}"
find $nextFolder \( -type d -name .git -prune \) -o -type f -print0 | xargs -0 sed -i "s#$configValue#${envValue-''}#g"
fi
done < $envFilename
}
echo ⏳ Replacing build-stage ENV placholders with their run-time values...
replace_envs
echo 👍 Done!
\ No newline at end of file
#!/bin/bash
# Check if the .env file exists
if [ -f .env ]; then
# Load the environment variables from .env
source .env
fi
# Check run-time ENVs values integrity
node "$(dirname "$0")/envs-validator.js" "$input"
if [ $? != 0 ]; then
exit 1
fi
\ No newline at end of file
/node_modules
/public
.env
.env.production
.env.registry
index.js
\ No newline at end of file
......@@ -2,7 +2,7 @@
export NEXT_PUBLIC_GIT_COMMIT_SHA=$(git rev-parse --short HEAD)
export NEXT_PUBLIC_GIT_TAG=$(git describe --tags --abbrev=0)
../../scripts/make_envs_template.sh ../../../docs/ENVS.md
../../scripts/collect_envs.sh ../../../docs/ENVS.md
yarn build
......
......@@ -81,17 +81,17 @@ async function getExternalJsonContent(fileName: string, envValue: string): Promi
});
}
async function checkPlaceholdersCongruity(runTimeEnvs: Record<string, string>) {
async function checkPlaceholdersCongruity(envsMap: Record<string, string>) {
try {
console.log(`🌀 Checking environment variables and their placeholders congruity...`);
const placeholders = await getEnvsPlaceholders(path.resolve(__dirname, '.env.production'));
const runTimeEnvs = await getEnvsPlaceholders(path.resolve(__dirname, '.env.registry'));
const buildTimeEnvs = await getEnvsPlaceholders(path.resolve(__dirname, '.env'));
const envs = Object.keys(runTimeEnvs).filter((env) => !buildTimeEnvs.includes(env));
const envs = Object.keys(envsMap).filter((env) => !buildTimeEnvs.includes(env));
const inconsistencies: Array<string> = [];
for (const env of envs) {
const hasPlaceholder = placeholders.includes(env);
const hasPlaceholder = runTimeEnvs.includes(env);
if (!hasPlaceholder) {
inconsistencies.push(env);
}
......
......@@ -8,7 +8,7 @@
"nextjs-routes": ["./nextjs/nextjs-routes.d.ts"],
}
},
"include": [ "../../../types/**/*.ts", "./index.ts", "./schema.ts" ],
"include": [ "../../../types/**/*.ts", "../../../global.d.ts", "./index.ts", "./schema.ts" ],
"tsc-alias": {
"verbose": true,
"resolveFullPaths": true,
......
......@@ -8,7 +8,7 @@
"nextjs-routes": ["./nextjs/nextjs-routes.d.ts"],
}
},
"include": [ "../../../configs/app/index.ts" ],
"include": [ "../../../configs/app/index.ts", "../../../global.d.ts" ],
"tsc-alias": {
"verbose": true,
"resolveFullPaths": true,
......
......@@ -18,6 +18,7 @@ declare global {
register: (...args: unknown) => void;
};
abkw: string;
__envs: Record<string, string>;
}
namespace NodeJS {
......
import dotenv from 'dotenv';
import fetchMock from 'jest-fetch-mock';
fetchMock.enableMocks();
const envs = dotenv.config({ path: './configs/envs/.env.jest' });
Object.defineProperty(window, 'matchMedia', {
writable: true,
value: jest.fn().mockImplementation(query => ({
......@@ -16,6 +20,11 @@ Object.defineProperty(window, 'matchMedia', {
})),
});
Object.defineProperty(window, '__envs', {
writable: true,
value: envs.parsed || {},
});
// eslint-disable-next-line no-console
const consoleError = console.error;
......
......@@ -20,9 +20,9 @@
"lint:tsc": "tsc -p ./tsconfig.json",
"prepare": "husky install",
"format-svg": "svgo -r ./icons",
"test:pw": "./playwright/make-envs-script.sh && NODE_OPTIONS=\"--max-old-space-size=4096\" ./node_modules/.bin/dotenv -e ./configs/envs/.env.pw -- playwright test -c playwright-ct.config.ts",
"test:pw:local": "export NODE_PATH=$(pwd)/node_modules && rm -rf ./playwright/.cache && yarn test:pw",
"test:pw:docker": "docker run --rm --network host -v $(pwd):/work/ -w /work/ -it mcr.microsoft.com/playwright:v1.35.1-focal ./playwright/run-tests.sh",
"test:pw": "./tools/scripts/pw.sh",
"test:pw:local": "export NODE_PATH=$(pwd)/node_modules && yarn test:pw",
"test:pw:docker": "docker run --rm --network host -v $(pwd):/work/ -w /work/ -it mcr.microsoft.com/playwright:v1.35.1-focal ./tools/scripts/pw.docker.sh",
"test:pw:ci": "yarn test:pw --project=$PW_PROJECT",
"test:jest": "jest",
"test:jest:watch": "jest --watch",
......
......@@ -39,6 +39,9 @@ class MyDocument extends Document {
rel="stylesheet"
/>
{ /* eslint-disable-next-line @next/next/no-sync-scripts */ }
<script src="/envs.js"/>
{ /* FAVICON */ }
<link rel="icon" href="/favicon/favicon.ico" sizes="48x48"/>
<link rel="icon" sizes="32x32" type="image/png" href="/favicon/favicon-32x32.png"/>
......
......@@ -68,7 +68,7 @@ const config: PlaywrightTestConfig = defineConfig({
},
},
define: {
'process.env': 'process.env', // Port over window.process envs
'process.env': '__envs', // Port process.env over window.__envs
},
},
},
......
......@@ -7,7 +7,7 @@
</head>
<body>
<div id="root"></div>
<script type="module" src="/playwright/envs.js"></script>
<script type="module" src="/public/envs.js"></script>
<script type="module" src="/playwright/index.ts"></script>
</body>
</html>
#!/bin/bash
targetFile='./playwright/envs.js'
declare -a envFiles=('./configs/envs/.env.pw')
touch $targetFile;
truncate -s 0 $targetFile;
echo "Creating script file with envs"
echo "window.process = { env: { } };" >> $targetFile;
for envFile in "${envFiles[@]}"
do
# read each env file
while read line; do
# if it is a comment or an empty line, continue to next one
if [ "${line:0:1}" == "#" ] || [ "${line}" == "" ]; then
continue
fi
# split by "=" sign to get variable name and value
configName="$(cut -d'=' -f1 <<<"$line")";
configValue="$(cut -d'=' -f2- <<<"$line")";
# if there is a value, escape it and add line to target file
escapedConfigValue=$(echo $configValue | sed s/\'/\"/g);
echo "window.process.env.${configName} = localStorage.getItem('${configName}') ?? '${escapedConfigValue}';" >> $targetFile;
done < $envFile
done
echo "Done"
\ No newline at end of file
......@@ -22,13 +22,13 @@ fi
# download assets for the running instance
dotenv \
-e $config_file \
-- bash -c './deploy/scripts/download_assets.sh ./public/assets' \
-- bash -c './deploy/scripts/download_assets.sh ./public/assets'
# run the app
# generate envs.js file and run the app
dotenv \
-v NEXT_PUBLIC_GIT_COMMIT_SHA=$(git rev-parse --short HEAD) \
-v NEXT_PUBLIC_GIT_TAG=$(git describe --tags --abbrev=0) \
-e $config_file \
-e $secrets_file \
-- bash -c 'next dev -- -p $NEXT_PUBLIC_APP_PORT' |
-- bash -c './deploy/scripts/make_envs_script.sh && next dev -- -p $NEXT_PUBLIC_APP_PORT' |
pino-pretty
\ No newline at end of file
#!/bin/sh
#!/bin/bash
yarn install --modules-folder node_modules_linux
export NODE_PATH=$(pwd)/node_modules_linux
rm -rf ./playwright/.cache
yarn test:pw "$@"
\ No newline at end of file
yarn test:pw "$@"
#!/bin/bash
config_file="./configs/envs/.env.pw"
rm -rf ./playwright/.cache
dotenv \
-e $config_file \
-- bash -c './deploy/scripts/make_envs_script.sh'
dotenv \
-v NODE_OPTIONS=\"--max-old-space-size=4096\" \
-e $config_file \
-- playwright test -c playwright-ct.config.ts "$@"
import { test, expect } from '@playwright/experimental-ct-react';
import React from 'react';
import { getExternalAssetFilePath } from 'configs/app/utils';
import { buildExternalAssetFilePath } from 'configs/app/utils';
import { apps as appsMock } from 'mocks/apps/apps';
import * as searchMock from 'mocks/search/index';
import contextWithEnvs from 'playwright/fixtures/contextWithEnvs';
......@@ -181,7 +181,7 @@ test('search by tx hash +@mobile', async({ mount, page }) => {
});
test.describe('with apps', () => {
const MARKETPLACE_CONFIG_URL = getExternalAssetFilePath('NEXT_PUBLIC_MARKETPLACE_CONFIG_URL', 'https://marketplace-config.json') || '';
const MARKETPLACE_CONFIG_URL = buildExternalAssetFilePath('NEXT_PUBLIC_MARKETPLACE_CONFIG_URL', 'https://marketplace-config.json') || '';
const extendedTest = test.extend({
context: contextWithEnvs([
{ name: 'NEXT_PUBLIC_MARKETPLACE_CONFIG_URL', value: MARKETPLACE_CONFIG_URL },
......
......@@ -2,7 +2,7 @@ import { test as base, expect } from '@playwright/experimental-ct-react';
import React from 'react';
import type { WindowProvider } from 'wagmi';
import { getExternalAssetFilePath } from 'configs/app/utils';
import { buildExternalAssetFilePath } from 'configs/app/utils';
import { FOOTER_LINKS } from 'mocks/config/footerLinks';
import contextWithEnvs from 'playwright/fixtures/contextWithEnvs';
import TestApp from 'playwright/TestApp';
......@@ -11,7 +11,7 @@ import * as configs from 'playwright/utils/configs';
import Footer from './Footer';
const FOOTER_LINKS_URL = getExternalAssetFilePath('NEXT_PUBLIC_FOOTER_LINKS', 'https://localhost:3000/footer-links.json') || '';
const FOOTER_LINKS_URL = buildExternalAssetFilePath('NEXT_PUBLIC_FOOTER_LINKS', 'https://localhost:3000/footer-links.json') || '';
const BACKEND_VERSION_API_URL = buildApiUrl('config_backend_version');
const INDEXING_ALERT_API_URL = buildApiUrl('homepage_indexing_status');
......
import { test as base, expect, devices } from '@playwright/experimental-ct-react';
import React from 'react';
import { getExternalAssetFilePath } from 'configs/app/utils';
import { buildExternalAssetFilePath } from 'configs/app/utils';
import { FEATURED_NETWORKS_MOCK } from 'mocks/config/network';
import authFixture from 'playwright/fixtures/auth';
import contextWithEnvs, { createContextWithEnvs } from 'playwright/fixtures/contextWithEnvs';
......@@ -9,7 +9,7 @@ import TestApp from 'playwright/TestApp';
import Burger from './Burger';
const FEATURED_NETWORKS_URL = getExternalAssetFilePath('NEXT_PUBLIC_FEATURED_NETWORKS', 'https://localhost:3000/featured-networks.json') || '';
const FEATURED_NETWORKS_URL = buildExternalAssetFilePath('NEXT_PUBLIC_FEATURED_NETWORKS', 'https://localhost:3000/featured-networks.json') || '';
const LOGO_URL = 'https://localhost:3000/my-logo.png';
base.use({ viewport: devices['iPhone 13 Pro'].viewport });
......
......@@ -3,7 +3,7 @@ import { test as base, expect } from '@playwright/experimental-ct-react';
import type { Locator } from '@playwright/test';
import React from 'react';
import { getExternalAssetFilePath } from 'configs/app/utils';
import { buildExternalAssetFilePath } from 'configs/app/utils';
import * as cookies from 'lib/cookies';
import authFixture from 'playwright/fixtures/auth';
import contextWithEnvs, { createContextWithEnvs } from 'playwright/fixtures/contextWithEnvs';
......@@ -21,7 +21,7 @@ const hooksConfig = {
},
};
const FEATURED_NETWORKS_URL = getExternalAssetFilePath('NEXT_PUBLIC_FEATURED_NETWORKS', 'https://localhost:3000/featured-networks.json') || '';
const FEATURED_NETWORKS_URL = buildExternalAssetFilePath('NEXT_PUBLIC_FEATURED_NETWORKS', 'https://localhost:3000/featured-networks.json') || '';
const test = base.extend({
context: contextWithEnvs([
......
......@@ -2,7 +2,7 @@ import { test as base, expect } from '@playwright/experimental-ct-react';
import type { Locator } from '@playwright/test';
import React from 'react';
import { getExternalAssetFilePath } from 'configs/app/utils';
import { buildExternalAssetFilePath } from 'configs/app/utils';
import contextWithEnvs from 'playwright/fixtures/contextWithEnvs';
import TestApp from 'playwright/TestApp';
import * as configs from 'playwright/utils/configs';
......@@ -44,8 +44,8 @@ base.describe('placeholder logo', () => {
});
base.describe('custom logo', () => {
const LOGO_URL = getExternalAssetFilePath('NEXT_PUBLIC_NETWORK_LOGO', 'https://localhost:3000/my-logo.png') || '';
const ICON_URL = getExternalAssetFilePath('NEXT_PUBLIC_NETWORK_ICON', 'https://localhost:3000/my-icon.png') || '';
const LOGO_URL = buildExternalAssetFilePath('NEXT_PUBLIC_NETWORK_LOGO', 'https://localhost:3000/my-logo.png') || '';
const ICON_URL = buildExternalAssetFilePath('NEXT_PUBLIC_NETWORK_ICON', 'https://localhost:3000/my-icon.png') || '';
const test = base.extend({
context: contextWithEnvs([
{ name: 'NEXT_PUBLIC_NETWORK_LOGO', value: LOGO_URL },
......@@ -91,10 +91,10 @@ base.describe('custom logo', () => {
});
base.describe('custom logo with dark option -@default +@dark-mode', () => {
const LOGO_URL = getExternalAssetFilePath('NEXT_PUBLIC_NETWORK_LOGO', 'https://localhost:3000/my-logo.png') || '';
const LOGO_URL_DARK = getExternalAssetFilePath('NEXT_PUBLIC_NETWORK_LOGO_DARK', 'https://localhost:3000/my-logo.png') || '';
const ICON_URL = getExternalAssetFilePath('NEXT_PUBLIC_NETWORK_ICON', 'https://localhost:3000/my-icon.png') || '';
const ICON_URL_DARK = getExternalAssetFilePath('NEXT_PUBLIC_NETWORK_ICON_DARK', 'https://localhost:3000/my-icon.png') || '';
const LOGO_URL = buildExternalAssetFilePath('NEXT_PUBLIC_NETWORK_LOGO', 'https://localhost:3000/my-logo.png') || '';
const LOGO_URL_DARK = buildExternalAssetFilePath('NEXT_PUBLIC_NETWORK_LOGO_DARK', 'https://localhost:3000/my-logo.png') || '';
const ICON_URL = buildExternalAssetFilePath('NEXT_PUBLIC_NETWORK_ICON', 'https://localhost:3000/my-icon.png') || '';
const ICON_URL_DARK = buildExternalAssetFilePath('NEXT_PUBLIC_NETWORK_ICON_DARK', 'https://localhost:3000/my-icon.png') || '';
const test = base.extend({
context: contextWithEnvs([
{ name: 'NEXT_PUBLIC_NETWORK_LOGO', value: LOGO_URL },
......
import { test, expect } from '@playwright/experimental-ct-react';
import React from 'react';
import { getExternalAssetFilePath } from 'configs/app/utils';
import { buildExternalAssetFilePath } from 'configs/app/utils';
import { FEATURED_NETWORKS_MOCK } from 'mocks/config/network';
import contextWithEnvs from 'playwright/fixtures/contextWithEnvs';
import TestApp from 'playwright/TestApp';
import NetworkMenu from './NetworkMenu';
const FEATURED_NETWORKS_URL = getExternalAssetFilePath('NEXT_PUBLIC_FEATURED_NETWORKS', 'https://localhost:3000/featured-networks.json') || '';
const FEATURED_NETWORKS_URL = buildExternalAssetFilePath('NEXT_PUBLIC_FEATURED_NETWORKS', 'https://localhost:3000/featured-networks.json') || '';
const extendedTest = test.extend({
context: contextWithEnvs([
......
......@@ -2,7 +2,7 @@ import { LightMode } from '@chakra-ui/react';
import { test as base, expect } from '@playwright/experimental-ct-react';
import React from 'react';
import { getExternalAssetFilePath } from 'configs/app/utils';
import { buildExternalAssetFilePath } from 'configs/app/utils';
import * as textAdMock from 'mocks/ad/textAd';
import { apps as appsMock } from 'mocks/apps/apps';
import * as searchMock from 'mocks/search/index';
......@@ -273,7 +273,7 @@ test('recent keywords suggest +@mobile', async({ mount, page }) => {
});
base.describe('with apps', () => {
const MARKETPLACE_CONFIG_URL = getExternalAssetFilePath('NEXT_PUBLIC_MARKETPLACE_CONFIG_URL', 'https://marketplace-config.json') || '';
const MARKETPLACE_CONFIG_URL = buildExternalAssetFilePath('NEXT_PUBLIC_MARKETPLACE_CONFIG_URL', 'https://marketplace-config.json') || '';
const test = base.extend({
context: contextWithEnvs([
{ name: 'NEXT_PUBLIC_MARKETPLACE_CONFIG_URL', value: MARKETPLACE_CONFIG_URL },
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment