Skip to content

Commit e6c1b06

Browse files
Fix collector class singleton pattern
1 parent 6db3071 commit e6c1b06

10 files changed

+82
-20
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { beforeEach, describe, expect, it } from '@jest/globals';
2+
import collector, { EntryType } from '../../metrics/collector';
3+
import * as fs from 'node:fs';
4+
5+
jest.mock('node:fs');
6+
7+
describe('Collector Class', () => {
8+
const expectedOutput = {
9+
violations: [
10+
{ componentId: 'example.component', ruleName: 'rule-1' },
11+
{ componentId: 'example.component', ruleName: 'rule-2' },
12+
],
13+
adoptions: [
14+
{ componentId: 'example.component', ruleName: 'rule-3' },
15+
],
16+
exceptions: [
17+
{ componentId: 'example.component', ruleName: 'rule-4' },
18+
],
19+
};
20+
21+
beforeEach(() => {
22+
collector.entries = {
23+
[EntryType.VIOLATION]: [],
24+
[EntryType.ADOPTION]: [],
25+
[EntryType.EXCEPTION]: [],
26+
};
27+
28+
jest.clearAllMocks();
29+
});
30+
31+
it('should collect violations, adoptions, and exceptions correctly', () => {
32+
collector.add(['example', 'component'], 'rule-1', EntryType.VIOLATION);
33+
collector.add(['example', 'component'], 'rule-2', EntryType.VIOLATION);
34+
collector.add(['example', 'component'], 'rule-3', EntryType.ADOPTION);
35+
collector.add(['example', 'component'], 'rule-4', EntryType.EXCEPTION);
36+
37+
expect(collector.entries).toEqual(expectedOutput);
38+
39+
collector.flushToFile();
40+
const writtenData = JSON.stringify(expectedOutput, null, 2);
41+
expect(fs.writeFileSync).toHaveBeenCalledWith(
42+
'combined.log',
43+
writtenData
44+
);
45+
});
46+
47+
it('should not add invalid entries', () => {
48+
collector.add(null, 'rule-1', EntryType.VIOLATION);
49+
collector.add(['example', 'component'], null, EntryType.ADOPTION);
50+
collector.add(['example', 'component'], 'rule-4', null);
51+
52+
expect(collector.entries).toEqual({
53+
violations: [],
54+
adoptions: [],
55+
exceptions: [],
56+
});
57+
58+
expect(fs.writeFileSync).not.toHaveBeenCalled();
59+
});
60+
});

tools/spectral/ipa/metrics/Collector.js renamed to tools/spectral/ipa/metrics/collector.js

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,31 +7,33 @@ export const EntryType = Object.freeze({
77
});
88

99
class Collector {
10-
static instance;
10+
static instance = null;
11+
12+
static getInstance() {
13+
if (!this.instance) {
14+
this.instance = new Collector();
15+
}
16+
return this.instance;
17+
}
1118

1219
constructor() {
1320
if (Collector.instance) {
14-
return Collector.instance;
21+
throw new Error('Use Collector.getInstance()');
1522
}
1623

1724
this.entries = {
1825
[EntryType.VIOLATION]: [],
1926
[EntryType.ADOPTION]: [],
2027
[EntryType.EXCEPTION]: [],
2128
};
22-
this.fileName = "combined.log"
23-
//this.exceptionFileName = 'exceptions.log';
24-
//this.violationFileName = 'violations.log';
25-
//this.adoptionFileName = 'adoptions.log';
2629

30+
this.fileName = "combined.log"
2731

2832
process.on('exit', () => this.flushToFile());
2933
process.on('SIGINT', () => {
3034
this.flushToFile();
31-
process.exit(); // Ensure process exits on Ctrl+C
35+
process.exit();
3236
});
33-
34-
Collector.instance = this;
3537
}
3638

3739
add(componentId, ruleName, type) {
@@ -52,5 +54,5 @@ class Collector {
5254
}
5355
}
5456

55-
const collector = new Collector();
57+
const collector = Collector.getInstance();
5658
export default collector;

tools/spectral/ipa/rulesets/functions/eachCustomMethodMustBeGetOrPost.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { isCustomMethod } from './utils/resourceEvaluation.js';
22
import { hasException } from './utils/exceptions.js';
3-
import collector, { EntryType } from '../../metrics/Collector.js';
3+
import collector, { EntryType } from '../../metrics/collector.js';
44

55
const RULE_NAME = 'xgen-IPA-109-custom-method-must-be-GET-or-POST';
66
const ERROR_MESSAGE = 'The HTTP method for custom methods must be GET or POST.';

tools/spectral/ipa/rulesets/functions/eachCustomMethodMustUseCamelCase.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { getCustomMethodName, isCustomMethod } from './utils/resourceEvaluation.js';
22
import { hasException } from './utils/exceptions.js';
33
import { casing } from '@stoplight/spectral-functions';
4-
import collector, { EntryType } from '../../metrics/Collector.js';
4+
import collector, { EntryType } from '../../metrics/collector.js';
55

66
const RULE_NAME = 'xgen-IPA-109-custom-method-must-use-camel-case';
77

tools/spectral/ipa/rulesets/functions/eachEnumValueMustBeUpperSnakeCase.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { hasException } from './utils/exceptions.js';
22
import { resolveObject } from './utils/componentUtils.js';
33
import { casing } from '@stoplight/spectral-functions';
4-
import collector, { EntryType } from '../../metrics/Collector.js';
4+
import collector, { EntryType } from '../../metrics/collector.js';
55

66
const RULE_NAME = 'xgen-IPA-123-enum-values-must-be-upper-snake-case';
77
const ERROR_MESSAGE = 'enum value must be UPPER_SNAKE_CASE.';
@@ -35,9 +35,9 @@ export default (input, _, { path, documentInventory }) => {
3535
});
3636

3737
if(errors.length === 0) {
38-
collector.add(path, RULE_NAME, EntryType.ADOPTION);
38+
collector.add(schemaPath, RULE_NAME, EntryType.ADOPTION);
3939
} else {
40-
collector.add(path, RULE_NAME, EntryType.VIOLATION);
40+
collector.add(schemaPath, RULE_NAME, EntryType.VIOLATION);
4141
}
4242

4343
return errors;

tools/spectral/ipa/rulesets/functions/eachPathAlternatesBetweenResourceNameAndPathParam.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { isPathParam } from './utils/componentUtils.js';
22
import { hasException } from './utils/exceptions.js';
3-
import collector, { EntryType } from '../../metrics/Collector.js';
3+
import collector, { EntryType } from '../../metrics/collector.js';
44

55
const RULE_NAME = 'xgen-IPA-102-path-alternate-resource-name-path-param';
66
const ERROR_MESSAGE = 'API paths must alternate between resource name and path params.';

tools/spectral/ipa/rulesets/functions/eachResourceHasGetMethod.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
getResourcePaths,
88
} from './utils/resourceEvaluation.js';
99
import { hasException } from './utils/exceptions.js';
10-
import collector, { EntryType } from '../../metrics/Collector.js';
10+
import collector, { EntryType } from '../../metrics/collector.js';
1111

1212
const RULE_NAME = 'xgen-IPA-104-resource-has-GET';
1313
const ERROR_MESSAGE = 'APIs must provide a get method for resources.';

tools/spectral/ipa/rulesets/functions/exceptionExtensionFormat.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import collector, { EntryType } from '../../metrics/Collector.js';
1+
import collector, { EntryType } from '../../metrics/collector.js';
22

33
const RULE_NAME = 'xgen-IPA-005-exception-extension-format';
44
const ERROR_MESSAGE = 'IPA exceptions must have a valid rule name and a reason.';

tools/spectral/ipa/rulesets/functions/singletonHasNoId.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
} from './utils/resourceEvaluation.js';
88
import { hasException } from './utils/exceptions.js';
99
import { getAllSuccessfulGetResponseSchemas } from './utils/methodUtils.js';
10-
import collector, { EntryType } from '../../metrics/Collector.js';
10+
import collector, { EntryType } from '../../metrics/collector.js';
1111

1212
const RULE_NAME = 'xgen-IPA-113-singleton-must-not-have-id';
1313
const ERROR_MESSAGE = 'Singleton resources must not have a user-provided or system-generated ID.';

tools/spectral/ipa/rulesets/functions/utils/exceptions.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import collector, { EntryType } from '../../../metrics/Collector.js';
1+
import collector, { EntryType } from '../../../metrics/collector.js';
22
const EXCEPTION_EXTENSION = 'x-xgen-IPA-exception';
33

44
/**

0 commit comments

Comments
 (0)