Skip to content

Commit

Permalink
[azure-functions] add test for utils
Browse files Browse the repository at this point in the history
  • Loading branch information
mildronize committed Jan 8, 2024
1 parent 4c66962 commit 79ef56f
Show file tree
Hide file tree
Showing 3 changed files with 209 additions and 8 deletions.
2 changes: 1 addition & 1 deletion packages/azure-functions/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { FunctionInput, FunctionOutput, InvocationContext } from '@azure/functions';
import { NammathamContext } from './nammatham-context';
import type { NammathamContext } from './nammatham-context';
import type { NammamthamEndpoint, PromiseLike } from '@nammatham/core';

export type HandlerFunction<TTriggerType, TReturnType> = (ctx: NammathamContext<TTriggerType>) => PromiseLike<TReturnType>;
Expand Down
199 changes: 199 additions & 0 deletions packages/azure-functions/src/utils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
import { expect, test, describe } from 'vitest';
import * as utils from './utils';
describe(`Test utils: ${utils.getMethods.name}`, () => {
test(`${utils.getMethods.name} should parsed to uppercase array`, async () => {
// Arrange
const func = {
endpointOption: {
type: 'http',
methods: ['get', 'post', 'put', 'delete'],
}
} as any;

// Act
const result = utils.getMethods(func);

// Assert
expect(result).toEqual(['GET', 'POST', 'PUT', 'DELETE']);
});

test(`${utils.getMethods.name} should return empty array if methods is not defined`, async () => {
// Arrange
const func = {
endpointOption: {
type: 'http',
}
} as any;

// Act
const result = utils.getMethods(func);

// Assert
expect(result).toEqual([]);
});
});

describe(`Test utils: ${utils.getFullUrl.name}`, () => {
test(`${utils.getFullUrl.name} should return full url`, async () => {
// Arrange
const func = {
endpointOption: {
route: 'test',
}
} as any;

// Act
const result = utils.getFullUrl(func, 3000);

// Assert
expect(result).toEqual('http://localhost:3000/api/test');
});

test(`${utils.getFullUrl.name} should return full url with prefix slash in route`, async () => {
// Arrange
const func = {
endpointOption: {
route: '/test',
}
} as any;

// Act
const result = utils.getFullUrl(func, 3000);

// Assert
expect(result).toEqual('http://localhost:3000/api/test');
});

test(`${utils.getFullUrl.name} should return empty string if route is not defined`, async () => {
// Arrange
const func = {
endpointOption: {
}
} as any;

// Act
const result = utils.getFullUrl(func, 3000);

// Assert
expect(result).toEqual('');
});
});

describe(`Test utils: ${utils.delay.name}`, () => {
test(`${utils.delay.name} should delay`, async () => {
// Arrange
const start = Date.now();

// Act
await utils.delay(10);

// Assert
expect(Date.now() - start).toBeGreaterThanOrEqual(10);
});
});

describe(`Test utils: ${utils.printRegisteredFunctions.name}`, () => {
test(`${utils.printRegisteredFunctions.name} should print functions`, async () => {
// Arrange
const app = {
functions: [
{
type: 'azure-functions',
name: 'test',
endpointOption: {
type: 'http',
route: 'test',
methods: ['get', 'post', 'put', 'delete'],
}
},
{
type: 'azure-functions',
name: 'test2',
endpointOption: {
type: 'timer',
route: 'test2',
methods: ['get', 'post', 'put', 'delete'],
}
},
],
} as any;
const option = {
port: 3000,
} as any;

// Act
const result = await utils.printRegisteredFunctions(app, option);

// Assert
expect(result).toEqual(app.functions.filter((func: any) => func?.endpointOption?.type === 'http'));
});

test(`${utils.printRegisteredFunctions.name} should not print functions if there is no function`, async () => {
// Arrange
const app = {
functions: [],
} as any;
const option = {
port: 3000,
} as any;

// Act
const result = await utils.printRegisteredFunctions(app, option);

// Assert
expect(result).toEqual([]);
});
});

describe(`Test utils: ${utils.printRegisteredNonHttpFunctions.name}`, () => {
test(`${utils.printRegisteredNonHttpFunctions.name} should print functions`, async () => {
// Arrange
const app = {
functions: [
{
type: 'azure-functions',
name: 'test',
endpointOption: {
type: 'http',
route: 'test',
methods: ['get', 'post', 'put', 'delete'],
}
},
{
type: 'azure-functions',
name: 'test2',
endpointOption: {
type: 'timer',
route: 'test2',
methods: ['get', 'post', 'put', 'delete'],
}
},
],
} as any;
const option = {
port: 3000,
} as any;

// Act
const result = await utils.printRegisteredNonHttpFunctions(app, option);

// Assert
expect(result).toEqual(app.functions.filter((func: any) => func?.endpointOption?.type !== 'http'));
});

test(`${utils.printRegisteredNonHttpFunctions.name} should not print functions if there is no function`, async () => {
// Arrange
const app = {
functions: [],
} as any;
const option = {
port: 3000,
} as any;

// Act
const result = await utils.printRegisteredNonHttpFunctions(app, option);

// Assert
expect(result).toEqual([]);
});
});
16 changes: 9 additions & 7 deletions packages/azure-functions/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,46 @@ import { blue, green, yellow } from 'colorette';
import { AfterServerStartedMetadata, NammathamApp, trimSlash } from '@nammatham/core';
import { AzureFunctionsEndpoint } from './types';

function getMethods(func: AzureFunctionsEndpoint<any, any>): string[] {
export function getMethods(func: AzureFunctionsEndpoint<any, any>): string[] {
if (!Array.isArray(func.endpointOption?.methods)) {
return [];
}
const methods = func.endpointOption?.methods?.map(method => method.toUpperCase()) ?? [];
return methods;
}

function getFullUrl(func: AzureFunctionsEndpoint<any, any>, port?: number): string {
export function getFullUrl(func: AzureFunctionsEndpoint<any, any>, port?: number): string {
const endpoint = func.endpointOption?.route ?? func.name;
if(typeof endpoint !== 'string') return '';
return `http://localhost${port ? `:${port}` : ''}/api/${trimSlash(endpoint)}`;
}

const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
export const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));

export async function printRegisteredFunctions(app: NammathamApp, option: AfterServerStartedMetadata) {
export async function printRegisteredFunctions(app: NammathamApp, option: AfterServerStartedMetadata): Promise<AzureFunctionsEndpoint<any, any>[]> {
const azureFunctions = app.functions
.filter(func => func.type === 'azure-functions')
.filter(func => func.endpointOption?.type === 'http') as AzureFunctionsEndpoint<any, any>[];
if (azureFunctions.length === 0) return;
if (azureFunctions.length === 0) return [];
await delay(100);
console.log(`\n${yellow('Functions:')}\n`);
for (const func of azureFunctions) {
const methods = `[${getMethods(func).join(',')}]`;
console.log(`\t${yellow(func.name)}: ${blue(methods)} ${green(getFullUrl(func, option.port))}\n`);
}
console.log('');
return azureFunctions;
}

/**
* FIXME: This functions is duplicated with printRegisteredFunctions, it should be merged later.
*/
export async function printRegisteredNonHttpFunctions(app: NammathamApp, option: AfterServerStartedMetadata) {
export async function printRegisteredNonHttpFunctions(app: NammathamApp, option: AfterServerStartedMetadata): Promise<AzureFunctionsEndpoint<any, any>[]> {
const azureFunctions = app.functions.filter(func => func.type === 'azure-functions').filter(func => func.endpointOption?.type !== 'http') as AzureFunctionsEndpoint<
any,
any
>[];
if (azureFunctions.length === 0) return;
if (azureFunctions.length === 0) return [];
await delay(100);
console.log(`${yellow(`----------------------------------------------`)}\n`);
console.log(`\n${yellow('Non-HTTP Functions (In Develpment Mode Only):')}\n`);
Expand All @@ -49,4 +50,5 @@ export async function printRegisteredNonHttpFunctions(app: NammathamApp, option:
console.log(`\t${yellow(func.name)}: ${blue(methods)} ${green(getFullUrl(func, option.port))}\n`);
}
console.log('');
return azureFunctions;
}

0 comments on commit 79ef56f

Please sign in to comment.