Skip to content

Commit

Permalink
Merge pull request #891 from Green-Software-Foundation/if-csv
Browse files Browse the repository at this point in the history
Build `if-csv`
  • Loading branch information
narekhovhannisyan authored Jul 16, 2024
2 parents ad1c825 + 669a422 commit 3ea46b3
Show file tree
Hide file tree
Showing 18 changed files with 614 additions and 89 deletions.
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"if-diff": "./build/if-diff/index.js",
"if-run": "./build/if-run/index.js",
"if-env": "./build/if-env/index.js",
"if-check": "./build/if-check/index.js"
"if-check": "./build/if-check/index.js",
"if-csv": "./build/if-csv/index.js"
},
"bugs": {
"url": "https://github.com/Green-Software-Foundation/if/issues/new?assignees=&labels=feedback&projects=&template=feedback.md&title=Feedback+-+"
Expand Down Expand Up @@ -76,6 +77,7 @@
"fix": "gts fix",
"fix:package": "fixpack",
"if-check": "cross-env CURRENT_DIR=$(node -p \"process.env.INIT_CWD\") npx ts-node src/if-check/index.ts",
"if-csv": "cross-env CURRENT_DIR=$(node -p \"process.env.INIT_CWD\") npx ts-node src/if-csv/index.ts",
"if-diff": "npx ts-node src/if-diff/index.ts",
"if-env": "cross-env CURRENT_DIR=$(node -p \"process.env.INIT_CWD\") npx ts-node src/if-env/index.ts",
"if-run": "npx ts-node src/if-run/index.ts",
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/common/lib/load.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jest.mock(
}),
{virtual: true}
);
jest.mock('../../../if-diff/util/helpers', () => ({
jest.mock('../../../common/util/helpers', () => ({
parseManifestFromStdin: () => {
if (process.env.readline === 'valid-source') {
return `
Expand Down
44 changes: 44 additions & 0 deletions src/__tests__/common/util/helpers.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
jest.mock('node:readline/promises', () =>
require('../../../__mocks__/readline')
);

import {parseManifestFromStdin} from '../../../common/util/helpers';

describe('common/util/helpers: ', () => {
describe('parseManifestFromStdin(): ', () => {
it('returns empty string if there is no data in stdin.', async () => {
const response = await parseManifestFromStdin();
const expectedResult = '';

expect(response).toEqual(expectedResult);
});

it('returns empty string if nothing is piped.', async () => {
const originalIsTTY = process.stdin.isTTY;
process.stdin.isTTY = true;
const response = await parseManifestFromStdin();
const expectedResult = '';

expect(response).toEqual(expectedResult);
process.stdin.isTTY = originalIsTTY;
});

it('throws error if there is no manifest in stdin.', async () => {
process.env.readline = 'no_manifest';
expect.assertions(1);

const response = await parseManifestFromStdin();

expect(response).toEqual('');
});

it('returns empty string if there is no data in stdin.', async () => {
process.env.readline = 'manifest';
const response = await parseManifestFromStdin();
const expectedMessage =
'\nname: mock-name\ndescription: mock-description\n';

expect(response).toEqual(expectedMessage);
});
});
});
264 changes: 264 additions & 0 deletions src/__tests__/if-csv/util/helpers.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
import {jest} from '@jest/globals';
import * as fs from 'fs/promises';
import {stringify} from 'csv-stringify/sync';
import {ERRORS} from '@grnsft/if-core/utils';

import {generateCsv, getManifestData} from '../../../if-csv/util/helpers';
import {CsvOptions} from '../../../if-csv/types/csv';

const {ManifestValidationError} = ERRORS;

import {
tree,
context,
aggregated,
aggregation,
} from '../../../__mocks__/builtins/export-yaml';

jest.mock('fs/promises', () => {
const originalModule =
jest.requireActual<typeof import('fs/promises')>('fs/promises');
return {
__esModule: true,
...originalModule,
writeFile: jest.fn(() => Promise.resolve()),
};
});

describe('if-csv/util/helpers: ', () => {
describe('generateCsv(): ', () => {
it('generates CSV file with correct data.', async () => {
const outputPath = 'output';
const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z'];
const matrix = [
columns,
['tree.carbon', 8000.000004051243, 8000.000004051243],
[
'tree.children.child-1.carbon',
4000.0000020256216,
4000.0000020256216,
],
[
'tree.children.child-2.carbon',
4000.0000020256216,
4000.0000020256216,
],
];
const reformedTree = Object.assign({}, tree, {
children: {
...tree.children,
'child-1': {
...tree.children['child-1'],
aggregated,
},
'child-2': {
...tree.children['child-2'],
aggregated,
},
},
});

const options: CsvOptions = {
tree: reformedTree,
context,
outputPath,
params: 'carbon',
};

await generateCsv(options);

expect(fs.writeFile).toHaveBeenCalledWith(
'output.csv',
stringify(matrix, {columns})
);
});

it('generates CSV file when the `outputs` type is missing.', async () => {
const outputPath = 'output';
const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z'];
const matrix = [
columns,
['tree.carbon', 8000.000004051243, 8000.000004051243],
[
'tree.children.child-1.carbon',
4000.0000020256216,
4000.0000020256216,
],
[
'tree.children.child-2.carbon',
4000.0000020256216,
4000.0000020256216,
],
];

const reformedTree = Object.assign({}, tree, {
children: {
...tree.children,
'child-1': {
...tree.children['child-1'],
aggregated,
},
'child-2': {
...tree.children['child-2'],
aggregated,
},
},
});

const options: CsvOptions = {
tree: reformedTree,
context,
outputPath,
params: 'carbon',
};

await generateCsv(options);

expect.assertions(1);

expect(fs.writeFile).toHaveBeenCalledWith(
'output.csv',
stringify(matrix, {columns})
);
});

it('generates CSV file when `aggregation` persists.', async () => {
const outputPath = 'output';
const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z'];
const matrix = [
columns,
['tree.carbon', 8000.000004051243, 8000.000004051243],
[
'tree.children.child-1.carbon',
4000.0000020256216,
4000.0000020256216,
],
[
'tree.children.child-2.carbon',
4000.0000020256216,
4000.0000020256216,
],
];

const reformedContext = Object.assign({}, context, {aggregation});
const reformedTree = Object.assign({}, tree, {
children: {
...tree.children,
'child-1': {
...tree.children['child-1'],
aggregated,
},
'child-2': {
...tree.children['child-2'],
aggregated,
},
},
});

const options: CsvOptions = {
tree: reformedTree,
context: reformedContext,
outputPath,
params: 'carbon',
};

await generateCsv(options);

expect.assertions(1);
expect(fs.writeFile).toHaveBeenCalledWith(
'output.csv',
stringify(matrix, {columns})
);
});

it('returns string when `outputPath` is not provided', async () => {
const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z'];
const matrix = [
columns,
['tree.carbon', 8000.000004051243, 8000.000004051243],
[
'tree.children.child-1.carbon',
4000.0000020256216,
4000.0000020256216,
],
];

const options: CsvOptions = {
tree,
context,
outputPath: undefined,
params: 'carbon',
};

const result = await generateCsv(options);

expect.assertions(1);
expect(result).toEqual(stringify(matrix, {columns}));
});

it('generates CSV file when `aggregation` is missing.', async () => {
const outputPath = 'output';
const columns = ['Path', 'Aggregated', '2023-12-12T00:00:00.000Z'];
const matrix = [
columns,
['tree.carbon', 8000.000004051243, 8000.000004051243],
[
'tree.children.child-1.carbon',
4000.0000020256216,
4000.0000020256216,
],
[
'tree.children.child-2.carbon',
4000.0000020256216,
4000.0000020256216,
],
];

const options: CsvOptions = {
tree,
context,
outputPath,
params: 'carbon',
};

await generateCsv(options);

expect.assertions(1);
expect(fs.writeFile).toHaveBeenCalledWith(
'output.csv',
stringify(matrix, {columns})
);
});
});

describe('getManifestData(): ', () => {
it('returns correct manifest data.', async () => {
process.env.MOCK_MANIFEST = 'true';
const mockManifestPath = './src/__mocks__/mock-manifest.yaml';
const result = await getManifestData(mockManifestPath);

expect.assertions(2);
expect(result).toHaveProperty('description');
expect(result).toHaveProperty('tree');
});

it('throws an error when there is not `outputs` in the manifest.', async () => {
process.env.MOCK_MANIFEST = 'false';
const mockManifestPath = '';
const load = require('../../../common/lib/load');
const spyLoad = jest.spyOn(load, 'load');

spyLoad.mockReturnValue({
rawManifest: {tree: {children: {child: {}}}},
});
expect.assertions(1);
try {
await getManifestData(mockManifestPath);
} catch (error) {
expect(error).toEqual(
new ManifestValidationError('Manifest outputs are not available!')
);
}
});
});
});
4 changes: 2 additions & 2 deletions src/__tests__/if-diff/lib/load.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jest.mock(
}),
{virtual: true}
);
jest.mock('../../../if-diff/util/helpers', () => ({
jest.mock('../../../common/util/helpers', () => ({
parseManifestFromStdin: () => {
if (process.env.readline === 'valid-source') {
return `
Expand Down Expand Up @@ -44,7 +44,7 @@ import {PluginParams} from '@grnsft/if-core/types';

import {loadIfDiffFiles} from '../../../if-diff/lib/load';

import {parseManifestFromStdin} from '../../../if-diff/util/helpers';
import {parseManifestFromStdin} from '../../../common/util/helpers';

import {STRINGS} from '../../../if-diff/config';

Expand Down
Loading

0 comments on commit 3ea46b3

Please sign in to comment.