Skip to content

Commit 7019bb0

Browse files
authored
Merge pull request #1199 from webstech/git-test
CI: add tests for git serialization and sequencing
2 parents 24faef3 + 4758f3c commit 7019bb0

File tree

4 files changed

+130
-6
lines changed

4 files changed

+130
-6
lines changed

lib/git.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,20 @@ export function git(args: string[], options?: IGitOptions | undefined):
4545
if (!process.stdout) {
4646
throw new Error(`No stdout for "git ${args.join(" ")}`);
4747
}
48-
const promises: Array<Promise<void>> = [];
48+
let linePromise: Promise<void> | undefined;
4949
const handleLine = (line: string): boolean => {
5050
try {
51-
promises.push(lineHandler(line));
51+
if (!linePromise) {
52+
linePromise = lineHandler(line);
53+
} else {
54+
linePromise = linePromise.then(() => {
55+
return lineHandler(line);
56+
});
57+
}
58+
linePromise.catch((reason) => {
59+
reject(reason);
60+
process.kill();
61+
});
5262
} catch (reason) {
5363
reject(reason);
5464
process.kill();
@@ -74,7 +84,12 @@ export function git(args: string[], options?: IGitOptions | undefined):
7484
if (buffer.length > 0) {
7585
handleLine(buffer);
7686
}
77-
Promise.all(promises).then(() => resolve("")).catch(reject);
87+
if (linePromise) {
88+
linePromise.then(() => { resolve(""); })
89+
.catch((reason) => { reject(reason); });
90+
} else {
91+
resolve("");
92+
}
7893
});
7994
};
8095
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
"transform": {
3636
"\\.(ts|tsx)$": "ts-jest"
3737
},
38-
"testRegex": "/tests/(?!test-lib).*\\.(ts|tsx|js)$"
38+
"testRegex": "/tests/.*\\.test\\.(ts|tsx|js)$"
3939
},
4040
"devDependencies": {
4141
"@types/html-to-text": "^8.1.1",

tests/git.test.ts

Lines changed: 91 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,95 @@
1-
import { expect, test } from "@jest/globals";
2-
import { gitConfig } from "../lib/git";
1+
import { expect, jest, test } from "@jest/globals";
2+
import { git, gitConfig } from "../lib/git";
3+
import logger from "./logger";
4+
5+
jest.setTimeout(180000);
6+
7+
// init config in env
8+
const configCount = 20;
9+
process.env.GIT_CONFIG_COUNT = `${configCount}`;
10+
for (let i = 0; i < configCount; i++) {
11+
process.env[`GIT_CONFIG_KEY_${i}`] = `TEST.TS.case${i}`;
12+
process.env[`GIT_CONFIG_VALUE_${i}`] = `test.case${i} value`;
13+
}
14+
15+
const sleep = async (ms: number) => {
16+
await new Promise<void>((resolve) => {
17+
setTimeout(() => { resolve(); }, ms);
18+
});
19+
};
320

421
test("finds core.bare", async () => {
522
expect(await gitConfig("core.bare")).toMatch(/true|false/);
623
});
24+
25+
test("serialization", async () => {
26+
let waitTime = 10;
27+
type vars = { myWait: number; waitTime: number };
28+
const times = new Array<vars>();
29+
30+
const lineHandler = async (): Promise<void> => {
31+
if (waitTime) {
32+
const myWait = --waitTime;
33+
logger(`waiting ${myWait}`);
34+
await sleep(waitTime*50+waitTime%2*60); // odd/even have different waits
35+
logger(`waiting ${myWait} done`);
36+
// track waitTime before and after wait
37+
times.push( {myWait, waitTime});
38+
}
39+
};
40+
41+
expect(await git(["config", "--get-regexp", "TEST"], {lineHandler})).toMatch("");
42+
times.map((el) => {
43+
logger(el.waitTime, el.myWait);
44+
});
45+
times.map((el) => {
46+
expect(el.waitTime).toEqual(el.myWait);
47+
});
48+
});
49+
50+
test("sequencing", async () => {
51+
let waitTime = configCount;
52+
let buffer = "";
53+
54+
const lineHandler = async (line: string): Promise<void> => {
55+
waitTime--;
56+
await sleep(waitTime*50+waitTime%2*60); // odd/even have different waits
57+
buffer += `${line}\n`;
58+
};
59+
60+
expect(await git(["config", "--get-regexp", "TEST"], {lineHandler})).toMatch("");
61+
expect(await git(["config", "--get-regexp", "TEST"], { trimTrailingNewline: false })).toEqual(buffer);
62+
});
63+
64+
test("slow stdout", async () => {
65+
// ready for syntax checking
66+
const codeModel = `
67+
{
68+
let i = 30;
69+
const o = setInterval(() => {
70+
process.stdout.write('Printing line ' + i + '$nl');
71+
if (!--i) {
72+
clearInterval(o);
73+
}
74+
}, 100);
75+
}
76+
`;
77+
78+
// compact spaces/newlines and add one as needed
79+
const code = codeModel.replace(/ +/g, " ").replace(/\n/g, "").replace(/\$nl/, "\\n");
80+
81+
let buffer = "";
82+
83+
// eslint-disable-next-line @typescript-eslint/require-await
84+
const lineHandler = async (line: string): Promise<void> => {
85+
buffer += `${line}\n`;
86+
};
87+
88+
// set config (using "-c", `alias.node="!node"`, does not work - ! is escaped)
89+
process.env.GIT_CONFIG_COUNT = `1`;
90+
process.env.GIT_CONFIG_KEY_0 = `alias.node`;
91+
process.env.GIT_CONFIG_VALUE_0 = `!node`;
92+
93+
expect(await git([`node`, `-e`, `${code}`], {lineHandler})).toEqual("");
94+
expect(await git([`node`, `-e`, `${code}`])).toEqual(buffer);
95+
});

tests/logger.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Utility to assist in testing. Provides a logger to use if --GGGVERBOSE is specified on the command.
2+
// This makes it easier to leave verbose log info in the source in case it is needed.
3+
// Normal use would be: npm test --GGGVERBOSE some.test.ts
4+
5+
// Using code:
6+
// import logger from "./logger";
7+
// logger("some test related data");
8+
9+
const logger = (() => {
10+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
11+
const debugLog = (...body: any[]) => {
12+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
13+
return console.log(...body);
14+
};
15+
const nodebugLog = () => { return; };
16+
17+
return process.env.npm_config_GGGVERBOSE ? debugLog : nodebugLog;
18+
})();
19+
20+
export default logger;

0 commit comments

Comments
 (0)