Skip to content

Commit 3a1212b

Browse files
committed
feat(EnqueuerAsNodeChild): Ability to run enqueuer as a child and exchange IPC messages with it
1 parent 854f07c commit 3a1212b

21 files changed

+2442
-2044
lines changed

output/examples.json

+962-962
Large diffs are not rendered by default.

output/examples.yml

+962-962
Large diffs are not rendered by default.

package-lock.json

+311-85
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "enqueuer",
3-
"version": "5.0.0",
3+
"version": "5.0.4",
44
"description": "Polyglot flow testing tool",
55
"main": "./js/enqueuer.js",
66
"typings": "./js/enqueuer.d.ts",

src/asserters/expect-to-be-equal-to-asserter.test.ts

+8-8
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ describe('ExpectToBeEqualToAsserter', () => {
6767

6868
const assertion: Assertion = {
6969
name: 'assertion 0',
70-
expect: {value: 123, deep: {nested: true, array: [4, 3, 2]}},
71-
toBeEqualTo: {value: 123, deep: {nested: true, array: [4, 3, 2]}},
70+
expect: {value: 123, cycle: {nested: true, array: [4, 3, 2]}},
71+
toBeEqualTo: {value: 123, cycle: {nested: true, array: [4, 3, 2]}},
7272
};
7373

7474
const literal = {
@@ -87,14 +87,14 @@ describe('ExpectToBeEqualToAsserter', () => {
8787
const assertion: Assertion = {
8888
name: 'assertion 0',
8989
expect: {
90-
deep: {
90+
cycle: {
9191
nested: true, array: [4, 3, 2]
9292
},
9393
value: 123,
9494
},
9595
toBeEqualTo: {
9696
value: 123,
97-
deep: {
97+
cycle: {
9898
nested: true, array: [4, 3, 2]
9999
}
100100
}
@@ -115,9 +115,9 @@ describe('ExpectToBeEqualToAsserter', () => {
115115

116116
const assertion: Assertion = {
117117
name: 'assertion 0',
118-
expect: {value: 123, deep: {nested: true, array: [4, 3, 2]}},
118+
expect: {value: 123, cycle: {nested: true, array: [4, 3, 2]}},
119119
not: null,
120-
toBeEqualTo: {value: 123, deep: {nested: true}},
120+
toBeEqualTo: {value: 123, cycle: {nested: true}},
121121
};
122122

123123
const literal = {
@@ -136,8 +136,8 @@ describe('ExpectToBeEqualToAsserter', () => {
136136

137137
const assertion: Assertion = {
138138
name: 'assertion 0',
139-
expect: {value: 123, deep: {nested: true, array: [4, 3, 2]}},
140-
toBeEqualTo: {value: 123, deep: {nested: false, array: [4, 3, 2]}},
139+
expect: {value: 123, cycle: {nested: true, array: [4, 3, 2]}},
140+
toBeEqualTo: {value: 123, cycle: {nested: false, array: [4, 3, 2]}},
141141
};
142142

143143
const literal = {

src/configurations/configuration.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {DynamicModulesManager} from '../plugins/dynamic-modules-manager';
66
import {LogLevel} from '../loggers/log-level';
77
import {prettifyJson} from '../outputs/prettify-json';
88

9-
// process.setMaxListeners(30);
9+
process.setMaxListeners(30);
1010

1111
export class Configuration {
1212
private static instance: Configuration;
+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import {RequisitionRunner} from './requisition-runners/requisition-runner';
2+
import {NotificationEmitter} from './notifications/notification-emitter';
3+
import {EnqueuerAsNodeChildRunner} from "./enqueuer-as-node-child-runner";
4+
import {Notifications} from "./notifications/notifications";
5+
6+
7+
jest.mock('./requisition-runners/requisition-runner');
8+
jest.mock('./notifications/notification-emitter');
9+
10+
const processOnMock = jest.fn();
11+
process.on = processOnMock;
12+
13+
const processSendMock = jest.fn();
14+
process.send = processSendMock;
15+
16+
const runMock = jest.fn();
17+
const requisitionRunnerConstructorMock = jest.fn(() => ({run: runMock}));
18+
// @ts-ignore
19+
RequisitionRunner.mockImplementation(requisitionRunnerConstructorMock);
20+
21+
let notificationEmitterOnMock = jest.fn();
22+
// @ts-ignore
23+
NotificationEmitter.on.mockImplementation(notificationEmitterOnMock);
24+
25+
describe('EnqueuerAsNodeChildRunner', () => {
26+
beforeEach(() => {
27+
processOnMock.mockClear();
28+
processSendMock.mockClear();
29+
requisitionRunnerConstructorMock.mockClear();
30+
runMock.mockClear();
31+
notificationEmitterOnMock.mockClear();
32+
});
33+
34+
it('should listen to message', async () => {
35+
const statusCode = await new EnqueuerAsNodeChildRunner().execute(true);
36+
37+
expect(statusCode).toBe(0);
38+
expect(processOnMock.mock.calls[0][0]).toBe('message');
39+
});
40+
41+
it('should send exit message', async () => {
42+
const statusCode = 0;
43+
await new EnqueuerAsNodeChildRunner().execute(true);
44+
45+
expect(processOnMock.mock.calls[1][0]).toBe('exit');
46+
47+
const onExitCallback = processOnMock.mock.calls[1][1];
48+
onExitCallback(statusCode);
49+
50+
expect(processSendMock).toHaveBeenCalledWith({
51+
event: 'PROCESS_EXIT',
52+
value: statusCode
53+
});
54+
});
55+
56+
it('should run enqueuer runner when a message arrives', async () => {
57+
const requisition = 'value';
58+
await new EnqueuerAsNodeChildRunner().execute(true);
59+
60+
const onMessageCallback = processOnMock.mock.calls[0][1];
61+
onMessageCallback({event: 'runRequisition', value: requisition});
62+
expect(requisitionRunnerConstructorMock).toHaveBeenCalledWith(requisition);
63+
expect(runMock).toHaveBeenCalled();
64+
});
65+
66+
it('should not run enqueuer when a message arrives but is not a requisitions', async () => {
67+
await new EnqueuerAsNodeChildRunner().execute(true);
68+
69+
const onMessageCallback = processOnMock.mock.calls[0][1];
70+
onMessageCallback({event: 'NOT_A REQUISITION'});
71+
expect(requisitionRunnerConstructorMock).not.toHaveBeenCalled();
72+
expect(runMock).not.toHaveBeenCalled();
73+
});
74+
75+
it('should register senders to every notification', async () => {
76+
await new EnqueuerAsNodeChildRunner().execute(true);
77+
78+
const everyNotificationKey = Object.keys(Notifications)
79+
.map((key: any) => Notifications[key])
80+
.filter((key: any) => typeof key === 'number')
81+
82+
expect(notificationEmitterOnMock.mock.calls.map((call: any) => call[0]))
83+
.toEqual(everyNotificationKey);
84+
});
85+
86+
it('should send when notification is emitted', async () => {
87+
await new EnqueuerAsNodeChildRunner().execute(true);
88+
89+
const report = {cycle: {}};
90+
report.cycle = report;
91+
92+
notificationEmitterOnMock.mock.calls[0][1]({report});
93+
expect(processSendMock).toHaveBeenCalledWith({
94+
event: 'REQUISITION_FINISHED',
95+
value: {
96+
report: {}
97+
}
98+
});
99+
});
100+
101+
});

src/enqueuer-as-node-child-runner.ts

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import {RequisitionRunner} from './requisition-runners/requisition-runner';
2+
import {NotificationEmitter} from './notifications/notification-emitter';
3+
import {ObjectDecycler} from './object-parser/object-decycler';
4+
import {Notifications} from './notifications/notifications';
5+
6+
export class EnqueuerAsNodeChildRunner {
7+
8+
public execute(shouldEnd: boolean = false): Promise<number> {
9+
console.log('Rocking and rolling');
10+
this.registerSenders();
11+
this.registerListeners();
12+
return new Promise<number>(resolve => {
13+
if (shouldEnd) {
14+
resolve(0);
15+
}
16+
});
17+
}
18+
19+
private registerListeners() {
20+
process.on('message', async message => {
21+
if (message.event === 'runRequisition') {
22+
await new RequisitionRunner(message.value).run();
23+
}
24+
});
25+
process.on('exit', (code) => {
26+
process.send!({
27+
event: 'PROCESS_EXIT',
28+
value: code
29+
});
30+
});
31+
}
32+
33+
private registerSenders() {
34+
35+
Object.keys(Notifications)
36+
.map((key: any) => Notifications[key])
37+
.filter((key: any) => typeof key === 'number')
38+
.forEach((notificationNameIndex: any) => {
39+
const notification = Notifications[notificationNameIndex];
40+
// @ts-ignore
41+
NotificationEmitter.on(notificationNameIndex, (report: any) => {
42+
process.send!(
43+
{
44+
event: notification,
45+
value: new ObjectDecycler().decycle(report)
46+
});
47+
});
48+
49+
});
50+
}
51+
52+
}

src/enqueuer-runner.test.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ import {Configuration} from './configurations/configuration';
33
import {RequisitionFilePatternParser} from './requisition-runners/requisition-file-pattern-parser';
44
import {RequisitionRunner} from './requisition-runners/requisition-runner';
55
import {SummaryTestOutput} from './outputs/summary-test-output';
6-
import {NotificationEmitter, Notifications} from './notifications/notification-emitter';
6+
import {NotificationEmitter} from './notifications/notification-emitter';
77
import {Logger} from './loggers/logger';
88
import {LogLevel} from './loggers/log-level';
9+
import {Notifications} from "./notifications/notifications";
910

1011
jest.mock('./outputs/summary-test-output');
1112
jest.mock('./configurations/configuration');
@@ -84,6 +85,7 @@ describe('EnqueuerRunner', () => {
8485
it('should call Summary', async () => {
8586

8687
const printMock = jest.fn();
88+
// @ts-ignore
8789
SummaryTestOutput.mockImplementationOnce(() => ({
8890
print: printMock
8991
}));
@@ -106,6 +108,7 @@ describe('EnqueuerRunner', () => {
106108

107109
it('should log Summary error', () => {
108110

111+
// @ts-ignore
109112
SummaryTestOutput.mockImplementationOnce(() => {
110113
throw 'error';
111114
});

src/enqueuer-runner.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@ import {RequisitionFilePatternParser} from './requisition-runners/requisition-fi
77
import {RequisitionRunner} from './requisition-runners/requisition-runner';
88
import {Configuration} from './configurations/configuration';
99
import {RequisitionAdopter} from './components/requisition-adopter';
10-
import {NotificationEmitter, Notifications} from './notifications/notification-emitter';
10+
import {NotificationEmitter} from './notifications/notification-emitter';
1111
import {SummaryTestOutput} from './outputs/summary-test-output';
1212
import {PublisherModel} from './models/inputs/publisher-model';
1313
import {TestModel} from './models/outputs/test-model';
1414
import {LogLevel} from './loggers/log-level';
15+
import {Notifications} from './notifications/notifications';
1516

1617
export class EnqueuerRunner {
1718
private static reportName: string = 'enqueuer';

src/enqueuer.ts

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export * from './requisition-runners/requisition-runner';
3535
export * from './strings/id-generator';
3636

3737
export * from './notifications/notification-emitter';
38+
export * from './notifications/notifications';
3839

3940
export * from './plugins/dynamic-modules-manager';
4041
export * from './plugins/protocol-manager';

src/handlers/stream-input-handler.test.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ describe('StreamInputHandler', () => {
8686
};
8787

8888
const message = {
89-
deep: {
89+
cycle: {
9090
'object': 2
9191
}
9292
};
@@ -129,4 +129,4 @@ describe('StreamInputHandler', () => {
129129

130130
});
131131

132-
});
132+
});

src/index.ts

+12-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
11
#!/usr/bin/env node
22
import {EnqueuerStarter} from './enqueuer-starter';
3+
import {EnqueuerAsNodeChildRunner} from './enqueuer-as-node-child-runner';
34

5+
// It's the executable
46
if (require.main === module) {
5-
new EnqueuerStarter()
6-
.start()
7-
.then((statusCode: number) => process.exit(statusCode));
7+
// It's the a child process
8+
if (process.send) {
9+
new EnqueuerAsNodeChildRunner()
10+
.execute()
11+
.then((statusCode: number) => process.exit(statusCode));
12+
} else {
13+
new EnqueuerStarter()
14+
.start()
15+
.then((statusCode: number) => process.exit(statusCode));
16+
}
817
}

src/notifications/notification-emitter.test.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import {NotificationEmitter, Notifications} from './notification-emitter';
1+
import {NotificationEmitter} from './notification-emitter';
2+
import {Notifications} from './notifications';
23

34
describe('NotificationEmitter', () => {
45
it('Should emit notification', done => {

src/notifications/notification-emitter.ts

+1-11
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,6 @@
11
import {EventEmitter} from 'events';
22
import {Logger} from '../loggers/logger';
3-
4-
export enum Notifications {
5-
REQUISITION_FINISHED,
6-
PUBLISHER_FINISHED,
7-
SUBSCRIPTION_FINISHED,
8-
HOOK_FINISHED,
9-
10-
REQUISITION_STARTED,
11-
PUBLISHER_STARTED,
12-
SUBSCRIPTION_STARTED,
13-
}
3+
import {Notifications} from './notifications';
144

155
export class NotificationEmitter {
166
private static readonly notificationEmitter = new NotificationEmitter();

src/notifications/notifications.ts

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export enum Notifications {
2+
REQUISITION_FINISHED,
3+
PUBLISHER_FINISHED,
4+
SUBSCRIPTION_FINISHED,
5+
HOOK_FINISHED,
6+
7+
REQUISITION_STARTED,
8+
PUBLISHER_STARTED,
9+
SUBSCRIPTION_STARTED,
10+
}

src/reporters/publishers/publisher-reporter.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ import {EventExecutor} from '../../events/event-executor';
99
import {DefaultHookEvents} from '../../models/events/event';
1010
import {ObjectDecycler} from '../../object-parser/object-decycler';
1111
import {TestModel, testModelIsPassing} from '../../models/outputs/test-model';
12-
import {NotificationEmitter, Notifications} from '../../notifications/notification-emitter';
12+
import {NotificationEmitter} from '../../notifications/notification-emitter';
1313
import {HookModel} from '../../models/outputs/hook-model';
14+
import {Notifications} from '../../notifications/notifications';
1415

1516
export class PublisherReporter {
1617
private readonly report: output.PublisherModel;

src/reporters/requisition-reporter.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import {MultiPublishersReporter} from './publishers/multi-publishers-reporter';
88
import {EventExecutor} from '../events/event-executor';
99
import {DefaultHookEvents} from '../models/events/event';
1010
import {TestModel} from '../models/outputs/test-model';
11-
import {NotificationEmitter, Notifications} from '../notifications/notification-emitter';
11+
import {NotificationEmitter} from '../notifications/notification-emitter';
12+
import {Notifications} from '../notifications/notifications';
1213

1314
export class RequisitionReporter {
1415
public static readonly DEFAULT_TIMEOUT = 5 * 1000;

src/reporters/subscription/subscription-reporter.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ import {TestModel, testModelIsPassing} from '../../models/outputs/test-model';
1414
import Signals = NodeJS.Signals;
1515
import SignalsListener = NodeJS.SignalsListener;
1616
import {HookReporter} from '../hook-reporter';
17-
import {NotificationEmitter, Notifications} from '../../notifications/notification-emitter';
17+
import {NotificationEmitter} from '../../notifications/notification-emitter';
18+
import {Notifications} from '../../notifications/notifications';
1819

1920
export class SubscriptionReporter {
2021

src/requisition-runners/requisition-runner.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ import {IterationsEvaluator} from './iterations-evaluator';
1010
import {ComponentParentBackupper} from '../components/component-parent-backupper';
1111
import {ComponentImporter} from './component-importer';
1212
import {RequisitionAdopter} from '../components/requisition-adopter';
13-
import {NotificationEmitter, Notifications} from '../notifications/notification-emitter';
13+
import {NotificationEmitter} from '../notifications/notification-emitter';
1414
import {testModelIsNotFailing} from '../models/outputs/test-model';
15+
import {Notifications} from '../notifications/notifications';
1516

1617
export class RequisitionRunner {
1718

0 commit comments

Comments
 (0)