๐Ÿ“ฆ ljharb / repo-report

๐Ÿ“„ blocksDestructivePushes.js ยท 143 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143/* eslint-disable no-shadow */

'use strict';

const test = require('tape');
const Metrics = require('../config/metrics');

// Execute the tests
test('BlocksDestructivePushes metric - Configuration', (t) => {
	const metric = Metrics.BlocksDestructivePushes;

	t.test('should be properly configured', (t) => {
		t.equal(typeof metric.extract, 'function', 'extract should be a function');
		t.deepEqual(metric.permissions, ['ADMIN'], 'should require ADMIN permissions');
		t.end();
	});
	t.end();
});

test('BlocksDestructivePushes metric - Null cases', (t) => {
	const metric = Metrics.BlocksDestructivePushes;

	t.test('should return null when no branch protection rule exists', (t) => {
		const mockRepo = {
			defaultBranchRef: null,
		};

		const result = metric.extract(mockRepo);
		t.equal(result, null, 'should return null for no defaultBranchRef');

		const mockRepoNoBPR = {
			defaultBranchRef: {
				name: 'main',
				branchProtectionRule: null,
			},
		};

		const result2 = metric.extract(mockRepoNoBPR);
		t.equal(result2, null, 'should return null when branchProtectionRule is null');

		t.end();
	});

	t.test('should handle missing defaultBranchRef', (t) => {
		const mockRepoMissingRef = {};

		const result = metric.extract(mockRepoMissingRef);
		t.equal(result, null, 'should return null when defaultBranchRef is missing entirely');
		t.end();
	});
	t.end();
});

test('BlocksDestructivePushes metric - Blocking cases', (t) => {
	const metric = Metrics.BlocksDestructivePushes;

	t.test('should return true when destructive pushes are blocked', (t) => {
		const mockRepo = {
			defaultBranchRef: {
				name: 'main',
				branchProtectionRule: {
					allowsForcePushes: false,
					allowsDeletions: false,
				},
			},
		};

		const result = metric.extract(mockRepo);
		t.equal(result, true, 'should return true when both force pushes and deletions are disabled');
		t.end();
	});

	t.test('should handle undefined as falsy', (t) => {
		const mockRepo = {
			defaultBranchRef: {
				name: 'main',
				branchProtectionRule: {
					// allowsForcePushes and allowsDeletions are undefined
					requiredStatusChecks: [],
				},
			},
		};

		const result = metric.extract(mockRepo);
		t.equal(result, true, 'should return true when allowsForcePushes and allowsDeletions are undefined (treated as false)');
		t.end();
	});
	t.end();
});

test('BlocksDestructivePushes metric - Allowing cases', (t) => {
	const metric = Metrics.BlocksDestructivePushes;

	t.test('should return false when force pushes are allowed', (t) => {
		const mockRepo = {
			defaultBranchRef: {
				name: 'main',
				branchProtectionRule: {
					allowsForcePushes: true,
					allowsDeletions: false,
				},
			},
		};

		const result = metric.extract(mockRepo);
		t.equal(result, false, 'should return false when force pushes are allowed');
		t.end();
	});

	t.test('should return false when deletions are allowed', (t) => {
		const mockRepo = {
			defaultBranchRef: {
				name: 'main',
				branchProtectionRule: {
					allowsForcePushes: false,
					allowsDeletions: true,
				},
			},
		};

		const result = metric.extract(mockRepo);
		t.equal(result, false, 'should return false when deletions are allowed');
		t.end();
	});

	t.test('should return false when both are allowed', (t) => {
		const mockRepo = {
			defaultBranchRef: {
				name: 'main',
				branchProtectionRule: {
					allowsForcePushes: true,
					allowsDeletions: true,
				},
			},
		};

		const result = metric.extract(mockRepo);
		t.equal(result, false, 'should return false when both force pushes and deletions are allowed');
		t.end();
	});
	t.end();
});