@dxdeveloperexperience/hygie
Version:
Hygie is an easy-to-use Open-Source REST API allowing you to interact with GIT events. This NestJS API expose a set of customizable rules to automate your project's life cycle.
599 lines (576 loc) • 18.6 kB
text/typescript
import { Utils } from './utils';
import { GitTypeEnum } from '../webhook/utils.enum';
import { TestingModule, Test } from '@nestjs/testing';
import { DataAccessService } from '../data_access/dataAccess.service';
import { MockDataAccessService } from '../__mocks__/mocks';
import { GitEnv } from '../git/gitEnv.interface';
let app: TestingModule;
let dataAccessService: DataAccessService;
beforeAll(async () => {
app = await Test.createTestingModule({
providers: [
{ provide: DataAccessService, useClass: MockDataAccessService },
],
}).compile();
dataAccessService = app.get(DataAccessService);
});
describe('Utils', () => {
beforeEach(() => {
jest.clearAllMocks();
});
describe('transformToArray', () => {
it('should return ["a", "b", "c"]', () => {
expect(Utils.transformToArray('a,b,c', {})).toEqual(['a', 'b', 'c']);
});
it('should return ["a", "b", "c"]', () => {
expect(Utils.transformToArray(['a', 'b', 'c'], {})).toEqual([
'a',
'b',
'c',
]);
});
it('should return ["a", "b", "c"]', () => {
expect(
Utils.transformToArray(
'{{data.a}}-{{data.b}}-{{data.c}}',
{
data: {
a: 'a',
b: 'b',
c: 'c',
},
},
'-',
),
).toEqual(['a', 'b', 'c']);
});
it('should return ["a", "b", "c"]', () => {
expect(
Utils.transformToArray(['{{data.a}}', '{{data.b}}', '{{data.c}}'], {
data: {
a: 'a',
b: 'b',
c: 'c',
},
}),
).toEqual(['a', 'b', 'c']);
});
});
describe('getGitEnv', () => {
it('should return a GitEnv object', async () => {
dataAccessService.readEnv = jest.fn().mockResolvedValue({
gitApi: 'https://gitapi.com',
gitToken: 'myToken',
});
const result: GitEnv = await Utils.getGitEnv(
dataAccessService,
'myFilePath',
);
expect(result).toEqual({
gitApi: 'https://gitapi.com',
gitToken: 'myToken',
});
});
});
describe('getGitEnv', () => {
it('should throw an error', async () => {
dataAccessService.readEnv = jest.fn().mockResolvedValue({});
try {
await Utils.getGitEnv(dataAccessService, 'myFilePath');
} catch (e) {
expect(e).toEqual(new Error('envData object has empty properties'));
}
});
});
describe('getObjectValue', () => {
it('should return {}', () => {
const test: any = {};
expect(Utils.getObjectValue(test.key)).toEqual({});
});
it('should return the object', () => {
const test: any = {
key: {
key1: 'value1',
},
};
expect(Utils.getObjectValue(test.key)).toEqual({
key1: 'value1',
});
});
});
describe('getStringValue', () => {
it('should return ""', () => {
const test: any = {};
expect(Utils.getStringValue(test.key)).toBe('');
});
it('should return the string value', () => {
const test: any = {
key: 'value',
};
expect(Utils.getStringValue(test.key)).toBe('value');
});
});
describe('whichGitType', () => {
it('should return "Github"', () => {
expect(
Utils.whichGitType('https://github.com/bastienterrier/test-webhook'),
).toBe(GitTypeEnum.Github);
});
it('should return "Gitlab"', () => {
expect(
Utils.whichGitType('https://gitlab.com/bastien.terrier/test_webhook'),
).toBe(GitTypeEnum.Gitlab);
});
it('should return "Undifined"', () => {
expect(Utils.whichGitType('https://google.com')).toBe(
GitTypeEnum.Undefined,
);
});
});
describe('getRepositoryFullName', () => {
it('should return "zenika-open-source/hygie"', () => {
expect(
Utils.getRepositoryFullName(
'https://github.com/zenika-open-source/hygie',
),
).toBe('zenika-open-source/hygie');
});
});
describe('JSONtoString', () => {
it('should return "gitApi=myAPI\ngitToken=myToken', () => {
expect(
Utils.JSONtoString({
gitApi: 'myAPI',
gitToken: 'myToken',
}),
).toBe('gitApi=myAPI\ngitToken=myToken');
});
it('should return "gitApi=myAPI\ngitToken=myToken', () => {
expect(Utils.JSONtoString('gitApi=myAPI\ngitToken=myToken')).toBe(
'gitApi=myAPI\ngitToken=myToken',
);
});
});
describe('StringtoJSON', () => {
it('should return a JSON object', () => {
expect(Utils.StringtoJSON('gitApi=myAPI\ngitToken=myToken')).toEqual({
gitApi: 'myAPI',
gitToken: 'myToken',
});
});
it('should return a JSON object', () => {
expect(
Utils.StringtoJSON({
gitApi: 'myAPI',
gitToken: 'myToken',
}),
).toEqual({
gitApi: 'myAPI',
gitToken: 'myToken',
});
});
});
describe('generateUniqueId', () => {
it('shoud return two differents ids', () => {
const id1 = Utils.generateUniqueId();
const id2 = Utils.generateUniqueId();
expect(id1).not.toBe(id2);
});
});
describe('encryptToken & decryptToken', () => {
it('shoud encrypt the plain text and retrieve it', () => {
process.env.ENCRYPTION_KEY = 'somekey';
const original = 'hello, world!';
const encrypt = Utils.encryptValue(original);
const decrypt = Utils.decryptValue(encrypt);
expect(decrypt).toBe(original);
});
});
describe('splitDirectoryPath', () => {
it('shoud return two paths', () => {
const { base, name } = Utils.splitDirectoryPath(
'docs/getting_started/steps',
);
expect(base).toBe('docs/getting_started');
expect(name).toBe('steps');
});
it('shoud return two paths', () => {
const { base, name } = Utils.splitDirectoryPath('docs');
expect(base).toBe('');
expect(name).toBe('docs');
});
});
describe('getTypeAndMode', () => {
it('shoud return tree', () => {
const result = Utils.getTypeAndMode('dir');
expect(result).toEqual({ type: 'tree', mode: '040000' });
});
it('shoud return blob', () => {
const result = Utils.getTypeAndMode('file');
expect(result).toEqual({ type: 'blob', mode: '100644' });
});
it('shoud return nothing', () => {
const result = Utils.getTypeAndMode('');
expect(result).toEqual({});
});
});
// tslint:disable:max-line-length
describe('parseRuleFile', () => {
it('shoud return a YAML parsed rules object', async () => {
const yamlFile: any = `---
groups:
- groupName: check pattern 1
onBoth:
- args:
message: blablabla...
callback: LoggerRunnable
- args:
data:
message: 'data : {{#data}}- {{name}} -{{/data}}'
url: https://webhook.site/0de43177-4119-448b-bcfe-e2f6a2845ce8
callback: WebhookRunnable
rules:
- name: commitMessage
options:
regexp: "(feat|fix):s.*"
- name: oneCommitPerPR
- name: branchName
options:
regex: feature/.*
options:
allRuleResultInOne: true
enableGroups: false
enableRules: true
executeAllRules: false
rules:
- name: commitMessage
onBoth:
- args:
failDescriptionMessage: NOOOT good...
failTargetUrl: http://moogle.com/
successDescriptionMessage: good commit status!
successTargetUrl: http://www.google.com
callback: UpdateCommitStatusRunnable
onError:
- args:
message: 'pattern does not match, commit name must begin with : feat|fix|docs
and contains less than 100 numerals! Check your commit message: {{#data.commits}}
> {{message.commits}} (#{{sha}}) {{/data.commits}} '
callback: LoggerRunnable
onSuccess:
- args:
message: 'pattern match: branch: {{data.branch}} {{#data.commits}}{{sha}} =
{{matches.1}} | Scope: {{matches.2}} | Issue: {{matches.3}} {{/data.commits}}'
callback: LoggerRunnable
- args:
data:
content: "{{#data.commits}}{{sha}} = {{matches.1}} | Scope: {{matches.2}}
| Issue: {{matches.3}} {{/data.commits}}"
user: bastien terrier
url: https://webhook.site/0de43177-4119-448b-bcfe-e2f6a2845ce8
callback: WebhookRunnable
options:
maxLength: 100
regexp: "(feat|fix|docs)(([a-z]+))?:s[^(]*((#[1-9][0-9]*(?:, #[1-9][0-9]*)*))?$"
`;
const expectedResult = {
groups: [
{
groupName: 'check pattern 1',
onBoth: [
{
args: {
message: 'blablabla...',
},
callback: 'LoggerRunnable',
},
{
args: {
data: {
message: 'data : {{#data}}- {{name}} -{{/data}}',
},
url:
'https://webhook.site/0de43177-4119-448b-bcfe-e2f6a2845ce8',
},
callback: 'WebhookRunnable',
},
],
rules: [
{
name: 'commitMessage',
options: {
regexp: '(feat|fix):s.*',
},
},
{
name: 'oneCommitPerPR',
},
{
name: 'branchName',
options: {
regex: 'feature/.*',
},
},
],
},
],
options: {
allRuleResultInOne: true,
enableGroups: false,
enableRules: true,
executeAllRules: false,
},
rules: [
{
name: 'commitMessage',
onBoth: [
{
args: {
failDescriptionMessage: 'NOOOT good...',
failTargetUrl: 'http://moogle.com/',
successDescriptionMessage: 'good commit status!',
successTargetUrl: 'http://www.google.com',
},
callback: 'UpdateCommitStatusRunnable',
},
],
onError: [
{
args: {
message:
'pattern does not match, commit name must begin with : feat|fix|docs and contains less than 100 numerals! Check your commit message: {{#data.commits}} > {{message.commits}} (#{{sha}}) {{/data.commits}} ',
},
callback: 'LoggerRunnable',
},
],
onSuccess: [
{
args: {
message:
'pattern match: branch: {{data.branch}} {{#data.commits}}{{sha}} = {{matches.1}} | Scope: {{matches.2}} | Issue: {{matches.3}} {{/data.commits}}',
},
callback: 'LoggerRunnable',
},
{
args: {
data: {
content:
'{{#data.commits}}{{sha}} = {{matches.1}} | Scope: {{matches.2}} | Issue: {{matches.3}} {{/data.commits}}',
user: 'bastien terrier',
},
url:
'https://webhook.site/0de43177-4119-448b-bcfe-e2f6a2845ce8',
},
callback: 'WebhookRunnable',
},
],
options: {
maxLength: 100,
regexp:
'(feat|fix|docs)(([a-z]+))?:s[^(]*((#[1-9][0-9]*(?:, #[1-9][0-9]*)*))?$',
},
},
],
};
const parsedYAML = await Utils.parseYAMLFile(yamlFile);
expect(parsedYAML).toEqual(expectedResult);
});
it('shoud return a JSON parsed rules object', async () => {
const jsonFile: any = `{
"options": {
"executeAllRules": false,
"enableGroups": false,
"enableRules": true,
"allRuleResultInOne": true
},
"rules": [
{
"name": "commitMessage",
"options": {
"regexp": "(feat|fix|docs)(\([a-z]+\))?:\s[^(]*(\(#[1-9][0-9]*(?:, #[1-9][0-9]*)*\))?$",
"maxLength": 100
},
"onSuccess": [
{
"callback": "LoggerRunnable",
"args": {
"message": "pattern match: branch: {{data.branch}} {{#data.commits}}{{sha}} = {{matches.1}} | Scope: {{matches.2}} | Issue: {{matches.3}} {{/data.commits}}"
}
},
{
"callback": "WebhookRunnable",
"args": {
"url": "https://webhook.site/0de43177-4119-448b-bcfe-e2f6a2845ce8",
"data": {
"user": "bastien terrier",
"content": "{{#data.commits}}{{sha}} = {{matches.1}} | Scope: {{matches.2}} | Issue: {{matches.3}} {{/data.commits}}"
}
}
}
],
"onError": [
{
"callback": "LoggerRunnable",
"args": {
"message": "pattern does not match, commit name must begin with : feat|fix|docs and contains less than 100 numerals! Check your commit message: {{#data.commits}} > {{message.commits}} (#{{sha}}) {{/data.commits}} "
}
}
],
"onBoth": [
{
"callback": "UpdateCommitStatusRunnable",
"args": {
"successTargetUrl": "http://www.google.com",
"failTargetUrl": "http://moogle.com/",
"successDescriptionMessage": "good commit status!",
"failDescriptionMessage": "NOOOT good..."
}
}
]
}
],
"groups": [
{
"groupName": "check pattern 1",
"rules": [
{
"name": "commitMessage",
"options": {
"regexp": "(feat|fix):\s.*"
}
},
{
"name": "oneCommitPerPR"
},
{
"name": "branchName",
"options": {
"regex": "feature/.*"
}
}
],
"onBoth": [
{
"callback": "LoggerRunnable",
"args": {
"message": "blablabla..."
}
},
{
"callback": "WebhookRunnable",
"args": {
"url": "https://webhook.site/0de43177-4119-448b-bcfe-e2f6a2845ce8",
"data": {
"message": "data : {{#data}}- {{name}} -{{/data}}"
}
}
}
]
}
]
}
`;
const expectedResult = {
groups: [
{
groupName: 'check pattern 1',
onBoth: [
{
args: {
message: 'blablabla...',
},
callback: 'LoggerRunnable',
},
{
args: {
data: {
message: 'data : {{#data}}- {{name}} -{{/data}}',
},
url:
'https://webhook.site/0de43177-4119-448b-bcfe-e2f6a2845ce8',
},
callback: 'WebhookRunnable',
},
],
rules: [
{
name: 'commitMessage',
options: {
regexp: '(feat|fix):s.*',
},
},
{
name: 'oneCommitPerPR',
},
{
name: 'branchName',
options: {
regex: 'feature/.*',
},
},
],
},
],
options: {
allRuleResultInOne: true,
enableGroups: false,
enableRules: true,
executeAllRules: false,
},
rules: [
{
name: 'commitMessage',
onBoth: [
{
args: {
failDescriptionMessage: 'NOOOT good...',
failTargetUrl: 'http://moogle.com/',
successDescriptionMessage: 'good commit status!',
successTargetUrl: 'http://www.google.com',
},
callback: 'UpdateCommitStatusRunnable',
},
],
onError: [
{
args: {
message:
'pattern does not match, commit name must begin with : feat|fix|docs and contains less than 100 numerals! Check your commit message: {{#data.commits}} > {{message.commits}} (#{{sha}}) {{/data.commits}} ',
},
callback: 'LoggerRunnable',
},
],
onSuccess: [
{
args: {
message:
'pattern match: branch: {{data.branch}} {{#data.commits}}{{sha}} = {{matches.1}} | Scope: {{matches.2}} | Issue: {{matches.3}} {{/data.commits}}',
},
callback: 'LoggerRunnable',
},
{
args: {
data: {
content:
'{{#data.commits}}{{sha}} = {{matches.1}} | Scope: {{matches.2}} | Issue: {{matches.3}} {{/data.commits}}',
user: 'bastien terrier',
},
url:
'https://webhook.site/0de43177-4119-448b-bcfe-e2f6a2845ce8',
},
callback: 'WebhookRunnable',
},
],
options: {
maxLength: 100,
regexp:
'(feat|fix|docs)(([a-z]+))?:s[^(]*((#[1-9][0-9]*(?:, #[1-9][0-9]*)*))?$',
},
},
],
};
const parsedJSON = await Utils.parseYAMLFile(jsonFile);
expect(parsedJSON).toEqual(expectedResult);
});
});
});