Skip to content

Testing branch -This request applies to issue #4- Add testing with jest #81

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .babelrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
presets: [
'@babel/preset-env',
]

};
12 changes: 12 additions & 0 deletions babel.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module.exports = {
presets: [
[
'@babel/preset-env',
{
targets: {
node: 'current',
},
},
],
],
};
21 changes: 21 additions & 0 deletions jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type { Config } from '@jest/types'



/** @type {import('ts-jest').JestConfigWithTsJest} */

const config: Config.InitialOptions = {
preset: 'ts-jest/presets/default-esm',
testEnvironment: 'node',
verbose:true,
extensionsToTreatAsEsm: ['.ts'],
transform: {
"^.+\\.jsx?$": "babel-jest"
},

transformIgnorePatterns: ['<rootDir>/node_modules/'],
};



export default config
9,095 changes: 6,643 additions & 2,452 deletions package-lock.json

Large diffs are not rendered by default.

10 changes: 9 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -2,12 +2,14 @@
"name": "csv-to-sql-insert",
"version": "0.1.0",
"type": "module",
"module": "commonjs",
"repository": "https://github.com/gitdagray/csv-to-sql",
"description": "input a csv file, output a sql insert statement",
"main": "index.js",
"scripts": {
"start": "npm run build && node dist/index.js",
"build": "tsc --skipLibCheck"
"build": "tsc --skipLibCheck",
"test": "jest"
},
"author": {
"name": "Dave Gray",
@@ -16,8 +18,11 @@
},
"license": "MIT",
"devDependencies": {
"@babel/preset-env": "^7.23.8",
"@types/jest": "^29.5.11",
"@types/node": "^20.10.5",
"@typescript-eslint/eslint-plugin": "^6.15.0",
"babel-jest": "^29.7.0",
"eslint": "^8.56.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-node": "^4.1.0",
@@ -29,8 +34,11 @@
"eslint-plugin-prettier": "^5.1.1",
"eslint-plugin-promise": "^6.1.1",
"husky": "^8.0.3",
"jest": "^29.7.0",
"prettier": "^3.1.1",
"pretty-quick": "^3.1.3",
"ts-jest": "^29.1.1",
"ts-node": "^10.9.2",
"typescript": "^5.3.3"
},
"husky": {
11 changes: 11 additions & 0 deletions sql/undefined.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
INSERT INTO ExampleTable (id, description, entryDate, location, rate, isActive)
VALUES
(1, "American Farms", "2023-11-17 00:00:00.000", "New York", 0.05, 1),
(2, "Beatles", "2023-11-01 00:00:00.000", NULL, 0.01, 0),
(3, "True Licensing", "2023-12-02 00:00:00.000", NULL, 0.25, 1),
(4, "1 100", "2023-12-10 00:00:00.000", "Chicago", 0.5, 1),
(6, "Smith, John", "2023-10-03 00:00:00.000", "Dallas", 0.35, 1),
(7, "Brown, Esq., John", "2023-06-01 00:00:00.000", "Finland", 0.05, 1),
(8, "Merry Merry Christmas", "2023-01-01 00:00:00.000", NULL, 0, 1),
(9, "another entry", "2023-03-24 00:00:00.000", NULL, 1.05, 0),
(10, 42, "2023-04-01 00:00:00.000", "London", 0.2, 1);
23 changes: 18 additions & 5 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { promises as fs ,existsSync} from "fs";
import {createIfNot} from "./utils/fileUtils.js"

import {createIfNot} from "./utils/fileUtils.ts"
import * as path from "node:path"
async function writeSQL(statement: string, saveFileAs = "", isAppend: boolean = false) {



export async function writeSQL(statement: string, saveFileAs = "", isAppend: boolean = false) {
try {
const destinationFile = process.argv[2] || saveFileAs;
if (!destinationFile) {
@@ -18,15 +22,16 @@ async function writeSQL(statement: string, saveFileAs = "", isAppend: boolean =
}
}

async function readCSV(csvFileName = "", batchSize: number = 0) {
export async function readCSV(csvFileName:string = "", batchSize: number = 0) {
try {
const fileAndTableName = process.argv[2] || csvFileName;
const fileAndTableName = process.argv[2] || csvFileName||"ExampleTable";

batchSize = parseInt(process.argv[3]) || batchSize || 500;
let isAppend: boolean = false;

if (!fileAndTableName) {
throw new Error("Missing csvFileName parameter");

}
if(!existsSync(path.resolve(`./csv/${fileAndTableName}.csv`))){
console.log("file not found")
@@ -35,12 +40,16 @@ async function readCSV(csvFileName = "", batchSize: number = 0) {
const data = await fs.readFile(`csv/${fileAndTableName}.csv`, {
encoding: "utf8",
});

const linesArray = data.split(/\r|\n/).filter((line) => line);
const columnNames = linesArray?.shift()?.split(",") || [];
let beginSQLInsert = `INSERT INTO ${fileAndTableName} (`;

columnNames.forEach((name) => (beginSQLInsert += `${name}, `));

beginSQLInsert = beginSQLInsert.slice(0, -2) + ")\nVALUES\n";
let values = "";

linesArray.forEach((line, index) => {
// Parses each line of CSV into field values array
const arr = line.split(/,(?=(?:(?:[^"]*"){2})*[^"]*$)/);
@@ -67,6 +76,7 @@ async function readCSV(csvFileName = "", batchSize: number = 0) {
let valueLine = "\t(";
arr.forEach((value) => {
// Matches NULL values, Numbers,

// Strings accepted as numbers, and Booleans (0 or 1)
if (value === "NULL" || !isNaN(+value)) {
valueLine += `${value}, `;
@@ -83,6 +93,7 @@ async function readCSV(csvFileName = "", batchSize: number = 0) {
valueLine = valueLine.slice(0, -2) + "),\n";
values += valueLine;
});

values = values.slice(0, -2) + ";";
const sqlStatement = beginSQLInsert + values;
// Write File
@@ -91,5 +102,7 @@ async function readCSV(csvFileName = "", batchSize: number = 0) {
console.log(err);
}
}
readCSV();

readCSV("ExampleTable",500);

console.log("Finished!");
63 changes: 63 additions & 0 deletions src/tests/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { writeSQL } from "../index";

import { promises as fs, existsSync} from "fs";

//I DECIDED TO TEST WRITESQL FUNCTION BECAUSE READ CSV ULTIMATELY CALLS UPON WRITE SQL

describe('csv to sql test suite', () => {
jest.mock('fs', () => ({
existsSync: jest.fn(),
mkdirSync: jest.fn(),
mkdir: jest.fn(),
appendFile: jest.fn(),
writeFile: jest.fn()
}));
//const existsSyncSpy = jest.spyOn(fs, 'existsSync');
const mkdirSyncSpy = jest.spyOn(fs, 'mkdir');
const appendFileSpy = jest.spyOn(fs, 'appendFile');
const writeFileSpy = jest.spyOn(fs, 'writeFile');
afterEach(() => {
jest.clearAllMocks();
});

it('should write to a new SQL file exclusively',()=>{
//arrange
const sqlStatement = `INSERT INTO ExampleTable (id, description, entryDate, location, rate, isActive)
VALUES`
const filePath = "./ExampleTable.csv"
const isAppend = false

//act
writeSQL(sqlStatement, filePath,isAppend)


//assert
expect(appendFileSpy).not.toHaveBeenCalled()
expect(writeFileSpy).toHaveBeenCalled()


})



it('should append to an existing SQL file,but not create a new one' ,()=>{
//arrange
const sqlStatement = `INSERT INTO ExampleTable (id, description, entryDate, location, rate, isActive)
VALUES`
const filePath = "./ExampleTable.csv"
const isAppend = true

//act
writeSQL(sqlStatement, filePath,isAppend)


//assert

expect(writeFileSpy).not.toHaveBeenCalled()
expect(appendFileSpy).toHaveBeenCalled()


})


});
16 changes: 14 additions & 2 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
{
"compilerOptions": {
"target": "es6",
"target": "es2020",
"module": "ES2020",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"noEmitOnError": true
"noEmitOnError": true,
"types": ["node","jest"],
"esModuleInterop": true,
"allowImportingTsExtensions": true,
"noEmit": true
},
"include": ["src/**/*.ts"],
"exclude": ["node_modules"]
,
"ts-node": {
// these options are overrides used only by ts-node
"compilerOptions": {
"module": "commonjs"
}
}

}