最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Why my env variable load 2 times, 1st time with proper values 2nd time with empty values - Stack Overflow

programmeradmin2浏览0评论

During Playwright API test I'm not able to read API_URL value for specified env in test.

my global-setup:

import * as dotenv from 'dotenv';
import fs from 'fs/promises';
import path from 'path';

interface User {
  username: string;
  password: string;
  cis: string;
  debitCard: string;
}

interface BankAccount {
  accountNumber: string;
  title: string;
}

interface TransferTitles {
  [key: string]: string;
}

export let CONFIG: {
  BASE_URL: string;
  API_URL: string;
  ENV: string;
  USERS: User[];
  BANK_ACCOUNTS: BankAccount[];
  COMMON_TRANSFER_TITLES: TransferTitles;
} = {
  BASE_URL: '',
  API_URL: '',
  ENV: '',

};

async function globalSetup(): Promise<void> {
  const environment = process.env.ENV || 'uat';
  console.log(`Loading environment: ${environment}`);
  const envPath = path.resolve(__dirname, `../../.env.${environment}`);
  console.log(`Loading .env file from: ${envPath}`);
  dotenv.config({ path: envPath, override: true });
  console.log(`Loaded BASE_URL from .env: ${process.env.BASE_URL}`);
  console.log(`Loaded API_URL from .env: ${process.env.API_URL}`);

  CONFIG = {
    BASE_URL: process.env.BASE_URL ?? '[NOT SET]',,
    API_URL: process.env.API_URL ?? '[NOT SET]',
    ENV: environment,
    COMMON_TRANSFER_TITLES: {},
    USERS: [],
    BANK_ACCOUNTS: [],
  };

  try {
    const commonDataPath = path.resolve(__dirname, './COMMON/commonData.json');
    const commonData = await fs.readFile(commonDataPath, 'utf8');
    const parsedCommonData = JSON.parse(commonData);
    CONFIG.COMMON_TRANSFER_TITLES = parsedCommonData.transferTitles;
    console.log('Common data loaded successfully.');
  } catch (error) {
    console.error('Error loading common data:', error);
    throw new Error('Failed to load common data');
  }

  try {
    const testDataPath = path.resolve(__dirname, `./${environment}/testData-${environment}.json`);
    const testData = await fs.readFile(testDataPath, 'utf8');
    const parsedTestData = JSON.parse(testData);
    CONFIG.USERS = parsedTestData.users;
    CONFIG.BANK_ACCOUNTS = parsedTestData.bankAccounts;
    console.log(`${environment} data loaded successfully.`);
  } catch (error) {
    console.error(`Error loading ${environment} data:`, error);
    throw new Error(`Failed to load ${environment} data`);
  }

  console.log('Global setup completed. Configuration and test data loaded.');
  console.log(`Final BASE_URL in CONFIG: ${CONFIG.BASE_URL}`);
  console.log(`Final API_URL in CONFIG: ${CONFIG.API_URL}`);

  global.CONFIG = CONFIG;
}

export default globalSetup;

my api_requests file in utils

import { CONFIG } from './global-setup';
import { APIRequestContext } from '@playwright/test';

const headersUnblock = {
  'sim-state': 'UNKNOWN',
  'device-flag-vpn': 'true',
  'os-type': 'iOS',
};

console.log('CONFIG.API_URL at top level:', CONFIG.API_URL);

export const putUnblockRequest = async (request: APIRequestContext): Promise<any> => {
  console.log('CONFIG.API_URL inside function:', CONFIG.API_URL);
  const baseApiUrl = CONFIG.API_URL;
  const path = '/my/path';
  const url = `${baseApiUrl}${path}`;
  console.log('Full URL:', url);
  const response = await request.fetch(url, {
    method: 'PUT',
    headers: headersUnblock,
  });
  console.log('Response:', response);
  return response;
};

My api.spec.ts file:


import { putUnblockRequest } from '../../src/utils/api_requests';
import { expect, request as pwRequest, test } from '@playwright/test';
import { CONFIG } from '../../src/utils/global-setup';
console.log('CONFIG after import:', CONFIG);

test.describe('API Tests', () => {
  let request: any;

  test.beforeAll(async ({ playwright }) => {
    request = await pwRequest.newContext({
      extraHTTPHeaders: {},
    });
  });

  test.afterAll(async () => {
    await request.dispose();
  });

  

  test.only('PUT request to unblock all channels', async () => {
    console.log('CONFIG.API_URL BEFORE calling putUnblockRequest:', CONFIG.API_URL);
    const response = await putUnblockRequest(request);
    expect(response.status()).toBe(204);
  });
});

Why I'm not able to perform API test? - my URL from api_requests I tried everything. I lost my CONFIG.API_URL when I'm entering into function it is available when try to console.log('CONFIG.API_URL at top level:', CONFIG.API_URL);

 const baseApiUrl = CONFIG.API_URL;
  const path = '/my/path';
  const url = `${baseApiUrl}${path}`;

is always just /my/path

During Playwright API test I'm not able to read API_URL value for specified env in test.

my global-setup:

import * as dotenv from 'dotenv';
import fs from 'fs/promises';
import path from 'path';

interface User {
  username: string;
  password: string;
  cis: string;
  debitCard: string;
}

interface BankAccount {
  accountNumber: string;
  title: string;
}

interface TransferTitles {
  [key: string]: string;
}

export let CONFIG: {
  BASE_URL: string;
  API_URL: string;
  ENV: string;
  USERS: User[];
  BANK_ACCOUNTS: BankAccount[];
  COMMON_TRANSFER_TITLES: TransferTitles;
} = {
  BASE_URL: '',
  API_URL: '',
  ENV: '',

};

async function globalSetup(): Promise<void> {
  const environment = process.env.ENV || 'uat';
  console.log(`Loading environment: ${environment}`);
  const envPath = path.resolve(__dirname, `../../.env.${environment}`);
  console.log(`Loading .env file from: ${envPath}`);
  dotenv.config({ path: envPath, override: true });
  console.log(`Loaded BASE_URL from .env: ${process.env.BASE_URL}`);
  console.log(`Loaded API_URL from .env: ${process.env.API_URL}`);

  CONFIG = {
    BASE_URL: process.env.BASE_URL ?? '[NOT SET]',,
    API_URL: process.env.API_URL ?? '[NOT SET]',
    ENV: environment,
    COMMON_TRANSFER_TITLES: {},
    USERS: [],
    BANK_ACCOUNTS: [],
  };

  try {
    const commonDataPath = path.resolve(__dirname, './COMMON/commonData.json');
    const commonData = await fs.readFile(commonDataPath, 'utf8');
    const parsedCommonData = JSON.parse(commonData);
    CONFIG.COMMON_TRANSFER_TITLES = parsedCommonData.transferTitles;
    console.log('Common data loaded successfully.');
  } catch (error) {
    console.error('Error loading common data:', error);
    throw new Error('Failed to load common data');
  }

  try {
    const testDataPath = path.resolve(__dirname, `./${environment}/testData-${environment}.json`);
    const testData = await fs.readFile(testDataPath, 'utf8');
    const parsedTestData = JSON.parse(testData);
    CONFIG.USERS = parsedTestData.users;
    CONFIG.BANK_ACCOUNTS = parsedTestData.bankAccounts;
    console.log(`${environment} data loaded successfully.`);
  } catch (error) {
    console.error(`Error loading ${environment} data:`, error);
    throw new Error(`Failed to load ${environment} data`);
  }

  console.log('Global setup completed. Configuration and test data loaded.');
  console.log(`Final BASE_URL in CONFIG: ${CONFIG.BASE_URL}`);
  console.log(`Final API_URL in CONFIG: ${CONFIG.API_URL}`);

  global.CONFIG = CONFIG;
}

export default globalSetup;

my api_requests file in utils

import { CONFIG } from './global-setup';
import { APIRequestContext } from '@playwright/test';

const headersUnblock = {
  'sim-state': 'UNKNOWN',
  'device-flag-vpn': 'true',
  'os-type': 'iOS',
};

console.log('CONFIG.API_URL at top level:', CONFIG.API_URL);

export const putUnblockRequest = async (request: APIRequestContext): Promise<any> => {
  console.log('CONFIG.API_URL inside function:', CONFIG.API_URL);
  const baseApiUrl = CONFIG.API_URL;
  const path = '/my/path';
  const url = `${baseApiUrl}${path}`;
  console.log('Full URL:', url);
  const response = await request.fetch(url, {
    method: 'PUT',
    headers: headersUnblock,
  });
  console.log('Response:', response);
  return response;
};

My api.spec.ts file:


import { putUnblockRequest } from '../../src/utils/api_requests';
import { expect, request as pwRequest, test } from '@playwright/test';
import { CONFIG } from '../../src/utils/global-setup';
console.log('CONFIG after import:', CONFIG);

test.describe('API Tests', () => {
  let request: any;

  test.beforeAll(async ({ playwright }) => {
    request = await pwRequest.newContext({
      extraHTTPHeaders: {},
    });
  });

  test.afterAll(async () => {
    await request.dispose();
  });

  

  test.only('PUT request to unblock all channels', async () => {
    console.log('CONFIG.API_URL BEFORE calling putUnblockRequest:', CONFIG.API_URL);
    const response = await putUnblockRequest(request);
    expect(response.status()).toBe(204);
  });
});

Why I'm not able to perform API test? - my URL from api_requests I tried everything. I lost my CONFIG.API_URL when I'm entering into function it is available when try to console.log('CONFIG.API_URL at top level:', CONFIG.API_URL);

 const baseApiUrl = CONFIG.API_URL;
  const path = '/my/path';
  const url = `${baseApiUrl}${path}`;

is always just /my/path

Share Improve this question edited Jan 21 at 9:54 Shehan Lakshitha 3481 silver badge14 bronze badges asked Jan 20 at 15:54 HSTestingQAHSTestingQA 11 bronze badge
Add a comment  | 

2 Answers 2

Reset to default 0

Ok, i managed to do it by myself, solution was so easy. Need to add await for globalSetup() in test

  test.beforeAll(async ({ playwright }) => {
await globalSetup();
request = await pwRequest.newContext({
  extraHTTPHeaders: {},
});

});

Looks like the problem is that you are reassigning the exported value CONFIG in your globalSetup function:

CONFIG = {
  BASE_URL: process.env.BASE_URL ?? '[NOT SET]',,
  API_URL: process.env.API_URL ?? '[NOT SET]',
  ENV: environment,
  COMMON_TRANSFER_TITLES: {},
  USERS: [],
  BANK_ACCOUNTS: [],
};

While this statement changes the value of CONFIG inside globalSetup, it does not overwrite the cached exported CONFIG that you're importing into your spec files.

Maybe just put the config into its own module and don't try to initialize it via the globalSetup hook. For example:

// config.ts

// Call dotenv.load, read values from data files, etc. ...

export default {
  API_URL: process.env.API_URL,
  BASE_URL: process.env.BASE_URL,
  ENV: process.env.ENV,
  USERS: ...,
  BANK_ACCOUNTS: ...,
  COMMON_TRANSFER_TITLES: ...,
};

Alternatively, Playwright allows you to specify custom options or parameters in your playwright.config.ts that are injected into every test case. IMO, that's the most elegant way to configure tests.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论