Skip to content

Commit

Permalink
fix: use env as default env dirname (AnWeber/vscode-httpyac#198)
Browse files Browse the repository at this point in the history
  • Loading branch information
AnWeber committed Jun 10, 2023
1 parent 5504f75 commit d08d875
Show file tree
Hide file tree
Showing 5 changed files with 343 additions and 31 deletions.
3 changes: 2 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"program": "${workspaceFolder}/bin/httpyac.js",
"args": [
"send",
"${file}"
"${file}",
"--all"
],
"outFiles": [
"${workspaceFolder}/dist/**/*.js"
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## [unreleased]
### Fixes

- use `env` as default env dirname (Anweber/vscode-httpyac#198)

## [6.4.6] (2023-06-09)

### Fixes
Expand Down
50 changes: 27 additions & 23 deletions src/plugins/dotenv/dotenvVariableProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,18 @@ const defaultFiles: Array<string> = ['.env'];
export async function provideDotenvEnvironments(context: VariableProviderContext): Promise<string[]> {
const files: Array<string> = [];

files.push(...(await readEnvDir(process.env.HTTPYAC_ENV, context)));
files.push(...(await readEnvDir(context.config?.envDirName, context)));
if (process.env.HTTPYAC_ENV) {
try {
files.push(...(await fileProvider.readdir(process.env.HTTPYAC_ENV)));
} catch (err) {
log.warn(`HTTPYAC_ENV ${process.env.HTTPYAC_ENV} has read error`, err);
}
}

const dirOfFile = fileProvider.dirname(context.httpFile.fileName);
if (dirOfFile) {
await utils.iterateUntilRoot(dirOfFile, context.httpFile.rootDir, async (dir: PathLike) => {
files.push(...(await readEnvDir(getEnvdirname(context) || 'env', dir)));
files.push(...(await fileProvider.readdir(dir)));
});
}
Expand All @@ -29,10 +35,10 @@ export async function provideDotenvEnvironments(context: VariableProviderContext
});
}

async function readEnvDir(dir: string | undefined, context: VariableProviderContext): Promise<Array<string>> {
async function readEnvDir(dir: string | undefined, rootDir: PathLike | undefined): Promise<Array<string>> {
const files = [];
if (dir && utils.isString(dir)) {
const absoluteDir = await utils.toAbsoluteFilename(dir, context.httpFile.rootDir);
const absoluteDir = await utils.toAbsoluteFilename(dir, rootDir);
if (absoluteDir) {
files.push(...(await fileProvider.readdir(absoluteDir)));
}
Expand All @@ -47,27 +53,35 @@ export async function provideDotenvVariables(
const searchFiles = getSearchFiles(env);
const variables: Array<Variables> = [];

const globalEnv = process.env.HTTPYAC_ENV;
if (globalEnv && utils.isString(globalEnv)) {
const globalEnvAbsolute = await utils.toAbsoluteFilename(globalEnv, context.httpFile.rootDir);
if (globalEnvAbsolute) {
variables.push(...(await getEnvVariables(searchFiles, globalEnvAbsolute)));
}
if (process.env.HTTPYAC_ENV) {
variables.push(...(await getEnvVariables(searchFiles, process.env.HTTPYAC_ENV)));
}

await getEnvFolderVariables(context.config?.envDirName, searchFiles, context.httpFile.rootDir);
const dirOfFile = fileProvider.dirname(context.httpFile.fileName);
if (dirOfFile) {
const vars: Array<Variables> = [];
await utils.iterateUntilRoot(dirOfFile, context.httpFile.rootDir, async (dir: PathLike) => {
vars.unshift(...(await getEnvFolderVariables(context.config?.envDirName, searchFiles, dir)));
vars.unshift(...(await getEnvFolderVariables(getEnvdirname(context), searchFiles, dir)));
vars.unshift(...(await getEnvVariables(searchFiles, dir)));
});
variables.push(...vars);
}
return Object.assign({}, ...variables);
}

function getEnvdirname(context: VariableProviderContext) {
return context.config?.envDirName || 'env';
}

function getSearchFiles(env: string[] | undefined) {
const searchFiles = [...defaultFiles];
if (env) {
for (const environment of env) {
searchFiles.push(`${environment}.env`, `.env.${environment}`);
}
}
return searchFiles;
}

async function getEnvFolderVariables(
envDirName: string | undefined,
searchFiles: string[],
Expand All @@ -83,16 +97,6 @@ async function getEnvFolderVariables(
return variables;
}

function getSearchFiles(env: string[] | undefined) {
const searchFiles = [...defaultFiles];
if (env) {
for (const environment of env) {
searchFiles.push(`${environment}.env`, `.env.${environment}`);
}
}
return searchFiles;
}

async function getEnvVariables(searchFiles: string[], dir: PathLike) {
const files = await fileProvider.readdir(dir);
const foundFiles = searchFiles.filter(file => files.indexOf(file) >= 0);
Expand Down
241 changes: 241 additions & 0 deletions src/test/environment/dotenv.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
import { getEnvironments, send } from '../../httpYacApi';
import { VariableProviderContext } from '../../models';
import { initNestedFileProvider, parseHttp, sendHttpFile } from '../testUtils';
import { getLocal } from 'mockttp';

describe('environment.dotenv', () => {
const localServer = getLocal();
let envContent = '';
const httpContent = `
GET /json
foo: {{foo}}
`;
beforeAll(async () => {
await localServer.start();
envContent = `
host=http://localhost:${localServer.port}
foo=bar`;
});
afterAll(async () => await localServer.stop());

describe('provideEnvironments', () => {
it('parse .env in root dir', async () => {
initNestedFileProvider({
childs: {
'.env': envContent,
'dev.env': envContent,
'prod.env': envContent,
'.env.local': envContent,
},
});
const httpFile = await parseHttp(httpContent, '/src/test.http');
const envs = await getEnvironments({
httpFile,
} as VariableProviderContext);

expect(envs).toEqual(['dev', 'local', 'prod']);
});

it('parse .env in env dir', async () => {
initNestedFileProvider({
childs: {
env: {
childs: {
'.env': envContent,
'dev.env': envContent,
'prod.env': envContent,
'.env.local': envContent,
},
},
},
});
const httpFile = await parseHttp(httpContent, '/src/test.http');
const envs = await getEnvironments({
httpFile,
} as VariableProviderContext);

expect(envs).toEqual(['dev', 'local', 'prod']);
});
it('parse .env in config env dir', async () => {
initNestedFileProvider({
childs: {
env: {
childs: {
'.env': envContent,
'not.env': envContent,
},
},
foo: {
childs: {
'.env': envContent,
'dev.env': envContent,
'prod.env': envContent,
'.env.local': envContent,
},
},
},
});
const httpFile = await parseHttp(httpContent, '/src/test.http');
const envs = await getEnvironments({
httpFile,
config: {
envDirName: 'foo',
},
} as VariableProviderContext);

expect(envs).toEqual(['dev', 'local', 'prod']);
});
it('parse .env in httpyenv dir', async () => {
initNestedFileProvider({
childs: {
foo: {
childs: {
'.env': envContent,
'dev.env': envContent,
'prod.env': envContent,
'.env.local': envContent,
},
},
},
});
const httpFile = await parseHttp(httpContent, '/src/test.http');
try {
process.env.HTTPYAC_ENV = '/foo';
const envs = await getEnvironments({
httpFile,
} as VariableProviderContext);

expect(envs).toEqual(['dev', 'local', 'prod']);
} finally {
delete process.env.HTTPYAC_ENV;
}
});
});

describe('provideVariables', () => {
it('parse .env in root dir', async () => {
initNestedFileProvider({
childs: {
'.env': envContent,
src: {
childs: {
'test.http': httpContent,
},
},
},
});
const mockedEndpoints = await localServer.forGet('/json').thenJson(200, { foo: 'bar', test: 1 });

const httpFile = await parseHttp(httpContent, '/src/test.http');
await sendHttpFile(httpFile);

const requests = await mockedEndpoints.getSeenRequests();
expect(requests[0].headers.foo).toBe('bar');
});
it('parse .env in env folder', async () => {
initNestedFileProvider({
childs: {
env: {
childs: {
'.env': envContent,
},
},
src: {
childs: {
'test.http': httpContent,
},
},
},
});
const mockedEndpoints = await localServer.forGet('/json').thenJson(200, { foo: 'bar', test: 1 });

const httpFile = await parseHttp(httpContent, '/src/test.http');
await sendHttpFile(httpFile);

const requests = await mockedEndpoints.getSeenRequests();
expect(requests[0].headers.foo).toBe('bar');
});
it('parse .env in config env dir', async () => {
initNestedFileProvider({
childs: {
foo: {
childs: {
'.env': envContent,
},
},
src: {
childs: {
'test.http': httpContent,
},
},
},
});
const mockedEndpoints = await localServer.forGet('/json').thenJson(200, { foo: 'bar', test: 1 });

const httpFile = await parseHttp(httpContent, '/src/test.http');
await send({
httpFile,
config: {
envDirName: '/foo',
},
});

const requests = await mockedEndpoints.getSeenRequests();
expect(requests[0].headers.foo).toBe('bar');
});
it('use activeenvironemt', async () => {
initNestedFileProvider({
childs: {
foo: {
childs: {
'.env': envContent,
},
},
src: {
childs: {
'test.http': httpContent,
},
},
},
});
const mockedEndpoints = await localServer.forGet('/json').thenJson(200, { foo: 'bar', test: 1 });

try {
process.env.HTTPYAC_ENV = '/foo';
const httpFile = await parseHttp(httpContent, '/src/test.http');
await send({
httpFile,
});

const requests = await mockedEndpoints.getSeenRequests();
expect(requests[0].headers.foo).toBe('bar');
} finally {
delete process.env.HTTPYAC_ENV;
}
});
it('parse .env in HTTPYAC_ENV', async () => {
initNestedFileProvider({
childs: {
env: {
childs: {
'dev.env': envContent,
},
},
src: {
childs: {
'test.http': httpContent,
},
},
},
});
const mockedEndpoints = await localServer.forGet('/json').thenJson(200, { foo: 'bar', test: 1 });
const httpFile = await parseHttp(httpContent, '/src/test.http');
httpFile.activeEnvironment = ['dev'];
await send({
httpFile,
});
const requests = await mockedEndpoints.getSeenRequests();
expect(requests[0].headers.foo).toBe('bar');
});
});
});
Loading

0 comments on commit d08d875

Please sign in to comment.