@opentermsarchive/engine 1.2.0 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +5 -5
- package/scripts/declarations/lint/index.mocha.js +3 -3
- package/scripts/declarations/validate/index.mocha.js +5 -5
- package/scripts/history/migrate-services.js +1 -1
- package/scripts/import/index.js +1 -1
- package/src/api/routes/docs.test.js +2 -2
- package/src/api/routes/versions.test.js +1 -1
- package/src/archivist/extract/index.test.js +1 -1
- package/src/archivist/fetcher/fullDomFetcher.js +5 -5
- package/src/archivist/fetcher/index.test.js +5 -5
- package/src/archivist/index.test.js +16 -16
- package/src/archivist/recorder/index.js +4 -4
- package/src/archivist/recorder/index.test.js +29 -29
- package/src/archivist/recorder/repositories/git/git.js +6 -6
- package/src/archivist/recorder/repositories/git/index.js +4 -2
- package/src/archivist/recorder/repositories/git/index.test.js +65 -44
- package/src/archivist/recorder/repositories/interface.js +3 -0
- package/src/archivist/recorder/repositories/mongo/index.js +3 -3
- package/src/archivist/recorder/repositories/mongo/index.test.js +36 -36
- package/src/archivist/recorder/snapshot.test.js +4 -4
- package/src/archivist/recorder/version.test.js +4 -4
- package/src/archivist/services/index.test.js +16 -16
- package/src/archivist/services/sourceDocument.test.js +11 -11
- package/src/archivist/services/terms.test.js +2 -2
- package/src/notifier/index.js +2 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opentermsarchive/engine",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"description": "Tracks and makes visible changes to the terms of online services",
|
|
5
5
|
"homepage": "https://opentermsarchive.org",
|
|
6
6
|
"bugs": {
|
|
@@ -71,6 +71,7 @@
|
|
|
71
71
|
"eslint-plugin-chai-friendly": "^0.7.2",
|
|
72
72
|
"eslint-plugin-import": "^2.29.0",
|
|
73
73
|
"eslint-plugin-json-format": "^2.0.1",
|
|
74
|
+
"eslint-plugin-no-only-tests": "^3.1.0",
|
|
74
75
|
"express": "^4.18.2",
|
|
75
76
|
"express-async-errors": "^3.1.1",
|
|
76
77
|
"fs-extra": "^10.0.0",
|
|
@@ -90,9 +91,9 @@
|
|
|
90
91
|
"node-fetch": "^3.1.0",
|
|
91
92
|
"octokit": "^1.7.0",
|
|
92
93
|
"pdfjs-dist": "^2.9.359",
|
|
93
|
-
"puppeteer": "
|
|
94
|
-
"puppeteer-extra": "^3.
|
|
95
|
-
"puppeteer-extra-plugin-stealth": "^2.
|
|
94
|
+
"puppeteer": "^22.8.1",
|
|
95
|
+
"puppeteer-extra": "^3.3.6",
|
|
96
|
+
"puppeteer-extra-plugin-stealth": "^2.11.2",
|
|
96
97
|
"sib-api-v3-sdk": "^8.2.1",
|
|
97
98
|
"simple-git": "^3.8.0",
|
|
98
99
|
"swagger-jsdoc": "^6.2.8",
|
|
@@ -103,7 +104,6 @@
|
|
|
103
104
|
"devDependencies": {
|
|
104
105
|
"@commitlint/cli": "^19.0.3",
|
|
105
106
|
"dir-compare": "^4.0.0",
|
|
106
|
-
"eslint-plugin-no-only-tests": "^3.1.0",
|
|
107
107
|
"keep-a-changelog": "^2.5.3",
|
|
108
108
|
"nock": "^13.2.1",
|
|
109
109
|
"node-stream-zip": "^1.15.0",
|
|
@@ -36,7 +36,7 @@ export default async options => {
|
|
|
36
36
|
|
|
37
37
|
const lintFile = lintAndFixFile(options.fix);
|
|
38
38
|
|
|
39
|
-
describe('Service declarations lint validation',
|
|
39
|
+
describe('Service declarations lint validation', function () {
|
|
40
40
|
this.timeout(30000);
|
|
41
41
|
|
|
42
42
|
servicesToValidate.forEach(serviceId => {
|
|
@@ -46,8 +46,8 @@ export default async options => {
|
|
|
46
46
|
const filtersFilePath = path.join(declarationsPath, `${serviceId}.filters.js`);
|
|
47
47
|
const filtersHistoryFilePath = path.join(declarationsPath, `${serviceId}.filters.history.js`);
|
|
48
48
|
|
|
49
|
-
context(serviceId,
|
|
50
|
-
before(
|
|
49
|
+
context(serviceId, () => {
|
|
50
|
+
before(function () {
|
|
51
51
|
if (!service) {
|
|
52
52
|
console.log(' (Tests skipped as declaration has been archived)');
|
|
53
53
|
this.skip();
|
|
@@ -40,7 +40,7 @@ export default async options => {
|
|
|
40
40
|
({ services: servicesToValidate, servicesTermsTypes } = await declarationUtils.getModifiedServicesAndTermsTypes());
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
describe('Service declarations validation',
|
|
43
|
+
describe('Service declarations validation', function () {
|
|
44
44
|
this.timeout(60000);
|
|
45
45
|
this.slow(SLOW_DOCUMENT_THRESHOLD);
|
|
46
46
|
|
|
@@ -53,8 +53,8 @@ export default async options => {
|
|
|
53
53
|
|
|
54
54
|
after(stopHeadlessBrowser);
|
|
55
55
|
|
|
56
|
-
context(serviceId,
|
|
57
|
-
before(
|
|
56
|
+
context(serviceId, () => {
|
|
57
|
+
before(function () {
|
|
58
58
|
if (!service) {
|
|
59
59
|
console.log(' (Tests skipped as declaration has been archived)');
|
|
60
60
|
this.skip();
|
|
@@ -100,7 +100,7 @@ export default async options => {
|
|
|
100
100
|
let filteredContent;
|
|
101
101
|
|
|
102
102
|
context(sourceDocument.location, () => {
|
|
103
|
-
before(
|
|
103
|
+
before(function () {
|
|
104
104
|
if (!terms) {
|
|
105
105
|
console.log(' (Tests skipped as declaration has been archived)');
|
|
106
106
|
this.skip();
|
|
@@ -129,7 +129,7 @@ export default async options => {
|
|
|
129
129
|
expect(filteredContent).to.not.be.empty;
|
|
130
130
|
});
|
|
131
131
|
|
|
132
|
-
it(`filtered content has at least ${MIN_DOC_LENGTH} characters`,
|
|
132
|
+
it(`filtered content has at least ${MIN_DOC_LENGTH} characters`, function checkContentLength() {
|
|
133
133
|
if (!sourceDocument.content) {
|
|
134
134
|
console.log(' [Tests skipped as URL is not fetchable]');
|
|
135
135
|
this.skip();
|
|
@@ -198,7 +198,7 @@ async function initialize(migration) {
|
|
|
198
198
|
]);
|
|
199
199
|
}
|
|
200
200
|
|
|
201
|
-
|
|
201
|
+
function finalize(migration) {
|
|
202
202
|
return Promise.all([
|
|
203
203
|
migration.from.snapshots.source.finalize(),
|
|
204
204
|
migration.from.snapshots.destination.finalize(),
|
package/scripts/import/index.js
CHANGED
|
@@ -26,7 +26,7 @@ describe('Docs API', () => {
|
|
|
26
26
|
describe('body response defines', () => {
|
|
27
27
|
let subject;
|
|
28
28
|
|
|
29
|
-
before(
|
|
29
|
+
before(() => {
|
|
30
30
|
subject = response.body;
|
|
31
31
|
});
|
|
32
32
|
|
|
@@ -39,7 +39,7 @@ describe('Docs API', () => {
|
|
|
39
39
|
});
|
|
40
40
|
|
|
41
41
|
describe('with endpoints', () => {
|
|
42
|
-
before(
|
|
42
|
+
before(() => {
|
|
43
43
|
subject = response.body.paths;
|
|
44
44
|
});
|
|
45
45
|
|
|
@@ -525,7 +525,7 @@ describe('Extract', () => {
|
|
|
525
525
|
|
|
526
526
|
context('when PDF contains no text', () => {
|
|
527
527
|
it('throws an ExtractDocumentError error', async () => {
|
|
528
|
-
await expect(extract({ content: await fs.readFile(path.resolve(__dirname, '../../../test/fixtures/
|
|
528
|
+
await expect(extract({ content: await fs.readFile(path.resolve(__dirname, '../../../test/fixtures/termsWithoutText.pdf')), mimeType: mime.getType('pdf') })).to.be.rejectedWith(ExtractDocumentError, /contains no text/);
|
|
529
529
|
});
|
|
530
530
|
});
|
|
531
531
|
});
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import { TimeoutError } from 'puppeteer';
|
|
2
|
+
import puppeteer from 'puppeteer-extra';
|
|
3
3
|
import stealthPlugin from 'puppeteer-extra-plugin-stealth';
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
puppeteer.use(stealthPlugin());
|
|
6
6
|
|
|
7
7
|
let browser;
|
|
8
8
|
|
|
@@ -51,7 +51,7 @@ export default async function fetch(url, cssSelectors, config) {
|
|
|
51
51
|
content: await page.content(),
|
|
52
52
|
};
|
|
53
53
|
} catch (error) {
|
|
54
|
-
if (error instanceof
|
|
54
|
+
if (error instanceof TimeoutError) {
|
|
55
55
|
throw new Error(`Timed out after ${config.navigationTimeout / 1000} seconds when trying to fetch '${url}'`);
|
|
56
56
|
}
|
|
57
57
|
throw new Error(error.message);
|
|
@@ -67,7 +67,7 @@ export async function launchHeadlessBrowser() {
|
|
|
67
67
|
return browser;
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
browser = await
|
|
70
|
+
browser = await puppeteer.launch({ headless: true });
|
|
71
71
|
|
|
72
72
|
return browser;
|
|
73
73
|
}
|
|
@@ -70,7 +70,7 @@ describe('Fetcher', function () {
|
|
|
70
70
|
|
|
71
71
|
context('when expected selectors are present', () => {
|
|
72
72
|
before(async () => {
|
|
73
|
-
({ content, mimeType } = await fetch({ url,
|
|
73
|
+
({ content, mimeType } = await fetch({ url, cssSelectors: 'body' }));
|
|
74
74
|
});
|
|
75
75
|
|
|
76
76
|
it('returns the web page content of the given URL', () => {
|
|
@@ -83,7 +83,7 @@ describe('Fetcher', function () {
|
|
|
83
83
|
|
|
84
84
|
context('with client script enabled', () => {
|
|
85
85
|
before(async () => {
|
|
86
|
-
({ content, mimeType } = await fetch({ url,
|
|
86
|
+
({ content, mimeType } = await fetch({ url, cssSelectors: 'body', executeClientScripts: true }));
|
|
87
87
|
});
|
|
88
88
|
|
|
89
89
|
it('returns the web page content of the given URL', () => {
|
|
@@ -100,7 +100,7 @@ describe('Fetcher', function () {
|
|
|
100
100
|
const NOT_PRESENT_SELECTOR = 'h2';
|
|
101
101
|
|
|
102
102
|
before(async () => {
|
|
103
|
-
({ content, mimeType } = await fetch({ url,
|
|
103
|
+
({ content, mimeType } = await fetch({ url, cssSelectors: NOT_PRESENT_SELECTOR }));
|
|
104
104
|
});
|
|
105
105
|
|
|
106
106
|
it('returns the web page content of the given URL', () => {
|
|
@@ -113,7 +113,7 @@ describe('Fetcher', function () {
|
|
|
113
113
|
|
|
114
114
|
context('with client script enabled', () => {
|
|
115
115
|
before(async () => {
|
|
116
|
-
({ content, mimeType } = await fetch({ url,
|
|
116
|
+
({ content, mimeType } = await fetch({ url, cssSelectors: NOT_PRESENT_SELECTOR, executeClientScripts: true }));
|
|
117
117
|
});
|
|
118
118
|
|
|
119
119
|
it('returns the web page content of the given URL', () => {
|
|
@@ -133,7 +133,7 @@ describe('Fetcher', function () {
|
|
|
133
133
|
|
|
134
134
|
context('when expected selectors are present', () => {
|
|
135
135
|
before(async () => {
|
|
136
|
-
({ content } = await fetch({ url,
|
|
136
|
+
({ content } = await fetch({ url, cssSelectors: 'body' }));
|
|
137
137
|
});
|
|
138
138
|
|
|
139
139
|
it('returns the web page content of the given URL', () => {
|
|
@@ -28,7 +28,7 @@ const FETCH_DATE = new Date('2000-01-02T12:00:00.000Z');
|
|
|
28
28
|
let gitVersion;
|
|
29
29
|
let app;
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
function resetGitRepositories() {
|
|
32
32
|
return Promise.all([ app.recorder.snapshotsRepository.removeAll(), app.recorder.versionsRepository.removeAll() ]);
|
|
33
33
|
}
|
|
34
34
|
|
|
@@ -79,7 +79,7 @@ describe('Archivist', function () {
|
|
|
79
79
|
});
|
|
80
80
|
|
|
81
81
|
context('when everything works fine', () => {
|
|
82
|
-
before(
|
|
82
|
+
before(() => app.track({ services }));
|
|
83
83
|
|
|
84
84
|
after(resetGitRepositories);
|
|
85
85
|
|
|
@@ -118,11 +118,11 @@ describe('Archivist', function () {
|
|
|
118
118
|
|
|
119
119
|
after(resetGitRepositories);
|
|
120
120
|
|
|
121
|
-
it('records no snapshot for service A',
|
|
121
|
+
it('records no snapshot for service A', () => {
|
|
122
122
|
expect(fsApi.existsSync(path.resolve(__dirname, SERVICE_A_EXPECTED_SNAPSHOT_FILE_PATH))).to.be.false;
|
|
123
123
|
});
|
|
124
124
|
|
|
125
|
-
it('records no version for service A',
|
|
125
|
+
it('records no version for service A', () => {
|
|
126
126
|
expect(fsApi.existsSync(path.resolve(__dirname, SERVICE_A_EXPECTED_VERSION_FILE_PATH))).to.be.false;
|
|
127
127
|
});
|
|
128
128
|
|
|
@@ -182,11 +182,11 @@ describe('Archivist', function () {
|
|
|
182
182
|
expect(serviceAContent).to.equal('Terms of service with UTF-8 \'çhãràčtęrs"\n========================================');
|
|
183
183
|
});
|
|
184
184
|
|
|
185
|
-
it('generates a new version id',
|
|
185
|
+
it('generates a new version id', () => {
|
|
186
186
|
expect(reExtractedVersionId).to.not.equal(firstVersionId);
|
|
187
187
|
});
|
|
188
188
|
|
|
189
|
-
it('mentions the snapshot id in the changelog',
|
|
189
|
+
it('mentions the snapshot id in the changelog', () => {
|
|
190
190
|
expect(reExtractedVersionMessageBody).to.include(originalSnapshotId);
|
|
191
191
|
});
|
|
192
192
|
|
|
@@ -233,11 +233,11 @@ describe('Archivist', function () {
|
|
|
233
233
|
|
|
234
234
|
after(resetGitRepositories);
|
|
235
235
|
|
|
236
|
-
it('emits an inaccessibleContent event',
|
|
236
|
+
it('emits an inaccessibleContent event', () => {
|
|
237
237
|
expect(inaccessibleContentSpy).to.have.been.called;
|
|
238
238
|
});
|
|
239
239
|
|
|
240
|
-
it('still extracts the terms of other services',
|
|
240
|
+
it('still extracts the terms of other services', () => {
|
|
241
241
|
expect(versionNotChangedSpy).to.have.been.calledWith(versionB);
|
|
242
242
|
});
|
|
243
243
|
});
|
|
@@ -355,10 +355,10 @@ describe('Archivist', function () {
|
|
|
355
355
|
let terms;
|
|
356
356
|
let snapshot;
|
|
357
357
|
|
|
358
|
-
before(
|
|
358
|
+
before(() => {
|
|
359
359
|
terms = app.services.service·A.getTerms({ type: SERVICE_A_TYPE });
|
|
360
360
|
terms.fetchDate = FETCH_DATE;
|
|
361
|
-
terms.sourceDocuments.forEach(
|
|
361
|
+
terms.sourceDocuments.forEach(sourceDocument => {
|
|
362
362
|
sourceDocument.content = serviceASnapshotExpectedContent;
|
|
363
363
|
sourceDocument.mimeType = MIME_TYPE;
|
|
364
364
|
});
|
|
@@ -376,7 +376,7 @@ describe('Archivist', function () {
|
|
|
376
376
|
return resetGitRepositories();
|
|
377
377
|
});
|
|
378
378
|
|
|
379
|
-
it('emits "firstSnapshotRecorded" event',
|
|
379
|
+
it('emits "firstSnapshotRecorded" event', () => {
|
|
380
380
|
expect(spies.onFirstSnapshotRecorded).to.have.been.calledWith(snapshot);
|
|
381
381
|
});
|
|
382
382
|
|
|
@@ -424,7 +424,7 @@ describe('Archivist', function () {
|
|
|
424
424
|
return resetGitRepositories();
|
|
425
425
|
});
|
|
426
426
|
|
|
427
|
-
it('emits "snapshotNotChanged" event',
|
|
427
|
+
it('emits "snapshotNotChanged" event', () => {
|
|
428
428
|
expect(spies.onSnapshotNotChanged).to.have.been.calledWith(snapshot);
|
|
429
429
|
});
|
|
430
430
|
|
|
@@ -472,7 +472,7 @@ describe('Archivist', function () {
|
|
|
472
472
|
before(async () => {
|
|
473
473
|
await app.recordVersion(terms);
|
|
474
474
|
resetSpiesHistory();
|
|
475
|
-
terms.sourceDocuments.forEach(
|
|
475
|
+
terms.sourceDocuments.forEach(sourceDocument => {
|
|
476
476
|
sourceDocument.content = serviceBSnapshotExpectedContent;
|
|
477
477
|
});
|
|
478
478
|
changedVersion = await app.recordVersion(terms);
|
|
@@ -484,7 +484,7 @@ describe('Archivist', function () {
|
|
|
484
484
|
return resetGitRepositories();
|
|
485
485
|
});
|
|
486
486
|
|
|
487
|
-
it('emits "versionRecorded" event',
|
|
487
|
+
it('emits "versionRecorded" event', () => {
|
|
488
488
|
expect(spies.onVersionRecorded).to.have.been.calledWith(changedVersion);
|
|
489
489
|
});
|
|
490
490
|
|
|
@@ -506,7 +506,7 @@ describe('Archivist', function () {
|
|
|
506
506
|
return resetGitRepositories();
|
|
507
507
|
});
|
|
508
508
|
|
|
509
|
-
it('emits "versionNotChanged" event',
|
|
509
|
+
it('emits "versionNotChanged" event', () => {
|
|
510
510
|
expect(spies.onVersionNotChanged).to.have.been.calledWith(version);
|
|
511
511
|
});
|
|
512
512
|
|
|
@@ -516,7 +516,7 @@ describe('Archivist', function () {
|
|
|
516
516
|
});
|
|
517
517
|
|
|
518
518
|
context('when tracking changes on new services', () => {
|
|
519
|
-
before(
|
|
519
|
+
before(() => {
|
|
520
520
|
nock('https://www.servicea.example').get('/tos').reply(200, serviceASnapshotExpectedContent, { 'Content-Type': 'text/html' });
|
|
521
521
|
nock('https://www.serviceb.example').get('/privacy').reply(200, serviceBSnapshotExpectedContent, { 'Content-Type': 'application/pdf' });
|
|
522
522
|
|
|
@@ -8,19 +8,19 @@ export default class Recorder {
|
|
|
8
8
|
this.snapshotsRepository = RepositoryFactory.create(config.snapshots.storage);
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
initialize() {
|
|
12
12
|
return Promise.all([ this.versionsRepository.initialize(), this.snapshotsRepository.initialize() ]);
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
finalize() {
|
|
16
16
|
return Promise.all([ this.versionsRepository.finalize(), this.snapshotsRepository.finalize() ]);
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
getLatestSnapshot(terms, sourceDocumentId) {
|
|
20
20
|
return this.snapshotsRepository.findLatest(terms.service.id, terms.type, terms.hasMultipleSourceDocuments && sourceDocumentId);
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
record(record) {
|
|
24
24
|
record.validate();
|
|
25
25
|
|
|
26
26
|
switch (record.constructor) { // eslint-disable-line default-case
|
|
@@ -30,7 +30,7 @@ describe('Recorder', () => {
|
|
|
30
30
|
await recorder.initialize();
|
|
31
31
|
});
|
|
32
32
|
|
|
33
|
-
after(
|
|
33
|
+
after(() => recorder.finalize());
|
|
34
34
|
|
|
35
35
|
context('Snapshot', () => {
|
|
36
36
|
describe('#record', () => {
|
|
@@ -41,7 +41,7 @@ describe('Recorder', () => {
|
|
|
41
41
|
let record;
|
|
42
42
|
|
|
43
43
|
context('when a required param is missing', () => {
|
|
44
|
-
after(
|
|
44
|
+
after(() => recorder.snapshotsRepository.removeAll());
|
|
45
45
|
|
|
46
46
|
Snapshot.REQUIRED_PARAMS.forEach(testedRequiredParam => {
|
|
47
47
|
context(`when "${testedRequiredParam}" is missing`, () => {
|
|
@@ -82,17 +82,17 @@ describe('Recorder', () => {
|
|
|
82
82
|
record = await recorder.snapshotsRepository.findLatest(SERVICE_ID, TYPE);
|
|
83
83
|
});
|
|
84
84
|
|
|
85
|
-
after(
|
|
85
|
+
after(() => recorder.snapshotsRepository.removeAll());
|
|
86
86
|
|
|
87
87
|
it('records the snapshot with the proper content', async () => {
|
|
88
88
|
expect(await record.content).to.equal(CONTENT);
|
|
89
89
|
});
|
|
90
90
|
|
|
91
|
-
it('returns the record id',
|
|
91
|
+
it('returns the record id', () => {
|
|
92
92
|
expect(record.id).to.include(id);
|
|
93
93
|
});
|
|
94
94
|
|
|
95
|
-
it('states that it is the first record',
|
|
95
|
+
it('states that it is the first record', () => {
|
|
96
96
|
expect(isFirstRecord).to.be.true;
|
|
97
97
|
});
|
|
98
98
|
});
|
|
@@ -120,17 +120,17 @@ describe('Recorder', () => {
|
|
|
120
120
|
record = await recorder.snapshotsRepository.findLatest(SERVICE_ID, TYPE);
|
|
121
121
|
});
|
|
122
122
|
|
|
123
|
-
after(
|
|
123
|
+
after(() => recorder.snapshotsRepository.removeAll());
|
|
124
124
|
|
|
125
125
|
it('records the snapshot with the proper content', async () => {
|
|
126
126
|
expect(await record.content).to.equal(UPDATED_CONTENT);
|
|
127
127
|
});
|
|
128
128
|
|
|
129
|
-
it('returns the record id',
|
|
129
|
+
it('returns the record id', () => {
|
|
130
130
|
expect(record.id).to.include(id);
|
|
131
131
|
});
|
|
132
132
|
|
|
133
|
-
it('states that it is not the first record',
|
|
133
|
+
it('states that it is not the first record', () => {
|
|
134
134
|
expect(isFirstRecord).to.be.false;
|
|
135
135
|
});
|
|
136
136
|
});
|
|
@@ -156,9 +156,9 @@ describe('Recorder', () => {
|
|
|
156
156
|
record = await recorder.snapshotsRepository.findLatest(SERVICE_ID, TYPE);
|
|
157
157
|
});
|
|
158
158
|
|
|
159
|
-
after(
|
|
159
|
+
after(() => recorder.snapshotsRepository.removeAll());
|
|
160
160
|
|
|
161
|
-
it('does not record the snapshot',
|
|
161
|
+
it('does not record the snapshot', () => {
|
|
162
162
|
expect(id).to.not.be.ok;
|
|
163
163
|
});
|
|
164
164
|
});
|
|
@@ -175,7 +175,7 @@ describe('Recorder', () => {
|
|
|
175
175
|
let record;
|
|
176
176
|
|
|
177
177
|
context('when a required param is missing', () => {
|
|
178
|
-
after(
|
|
178
|
+
after(() => recorder.versionsRepository.removeAll());
|
|
179
179
|
|
|
180
180
|
Version.REQUIRED_PARAMS.forEach(testedRequiredParam => {
|
|
181
181
|
context(`when "${testedRequiredParam}" is missing`, () => {
|
|
@@ -216,17 +216,17 @@ describe('Recorder', () => {
|
|
|
216
216
|
record = await recorder.versionsRepository.findLatest(SERVICE_ID, TYPE);
|
|
217
217
|
});
|
|
218
218
|
|
|
219
|
-
after(
|
|
219
|
+
after(() => recorder.versionsRepository.removeAll());
|
|
220
220
|
|
|
221
221
|
it('records the version with the proper content', async () => {
|
|
222
222
|
expect(await record.content).to.equal(CONTENT);
|
|
223
223
|
});
|
|
224
224
|
|
|
225
|
-
it('returns the record id',
|
|
225
|
+
it('returns the record id', () => {
|
|
226
226
|
expect(record.id).to.include(id);
|
|
227
227
|
});
|
|
228
228
|
|
|
229
|
-
it('states that it is the first record',
|
|
229
|
+
it('states that it is the first record', () => {
|
|
230
230
|
expect(isFirstRecord).to.be.true;
|
|
231
231
|
});
|
|
232
232
|
});
|
|
@@ -254,21 +254,21 @@ describe('Recorder', () => {
|
|
|
254
254
|
record = await recorder.versionsRepository.findLatest(SERVICE_ID, TYPE);
|
|
255
255
|
});
|
|
256
256
|
|
|
257
|
-
after(
|
|
257
|
+
after(() => recorder.versionsRepository.removeAll());
|
|
258
258
|
|
|
259
259
|
it('records the version with the proper content', async () => {
|
|
260
260
|
expect(await record.content).to.equal(UPDATED_CONTENT);
|
|
261
261
|
});
|
|
262
262
|
|
|
263
|
-
it('records in the version that it is not an extracted only version',
|
|
263
|
+
it('records in the version that it is not an extracted only version', () => {
|
|
264
264
|
expect(record.isExtractOnly).to.equal(false);
|
|
265
265
|
});
|
|
266
266
|
|
|
267
|
-
it('returns the record id',
|
|
267
|
+
it('returns the record id', () => {
|
|
268
268
|
expect(record.id).to.include(id);
|
|
269
269
|
});
|
|
270
270
|
|
|
271
|
-
it('states that it is not the first record',
|
|
271
|
+
it('states that it is not the first record', () => {
|
|
272
272
|
expect(isFirstRecord).to.be.false;
|
|
273
273
|
});
|
|
274
274
|
});
|
|
@@ -294,9 +294,9 @@ describe('Recorder', () => {
|
|
|
294
294
|
record = await recorder.versionsRepository.findLatest(SERVICE_ID, TYPE);
|
|
295
295
|
});
|
|
296
296
|
|
|
297
|
-
after(
|
|
297
|
+
after(() => recorder.versionsRepository.removeAll());
|
|
298
298
|
|
|
299
|
-
it('does not record any version',
|
|
299
|
+
it('does not record any version', () => {
|
|
300
300
|
expect(id).to.not.be.ok;
|
|
301
301
|
});
|
|
302
302
|
});
|
|
@@ -323,17 +323,17 @@ describe('Recorder', () => {
|
|
|
323
323
|
record = await recorder.versionsRepository.findLatest(SERVICE_ID, TYPE);
|
|
324
324
|
});
|
|
325
325
|
|
|
326
|
-
after(
|
|
326
|
+
after(() => recorder.versionsRepository.removeAll()); after(() => recorder.versionsRepository.removeAll());
|
|
327
327
|
|
|
328
328
|
it('records the version with the proper content', async () => {
|
|
329
329
|
expect(await record.content).to.equal(CONTENT);
|
|
330
330
|
});
|
|
331
331
|
|
|
332
|
-
it('returns the record id',
|
|
332
|
+
it('returns the record id', () => {
|
|
333
333
|
expect(record.id).to.include(id);
|
|
334
334
|
});
|
|
335
335
|
|
|
336
|
-
it('states that it is the first record',
|
|
336
|
+
it('states that it is the first record', () => {
|
|
337
337
|
expect(isFirstRecord).to.be.true;
|
|
338
338
|
});
|
|
339
339
|
});
|
|
@@ -362,21 +362,21 @@ describe('Recorder', () => {
|
|
|
362
362
|
record = await recorder.versionsRepository.findLatest(SERVICE_ID, TYPE);
|
|
363
363
|
});
|
|
364
364
|
|
|
365
|
-
after(
|
|
365
|
+
after(() => recorder.versionsRepository.removeAll());
|
|
366
366
|
|
|
367
367
|
it('records the version with the proper content', async () => {
|
|
368
368
|
expect(await record.content).to.equal(UPDATED_CONTENT);
|
|
369
369
|
});
|
|
370
370
|
|
|
371
|
-
it('records in the version that it is an extracted only version',
|
|
371
|
+
it('records in the version that it is an extracted only version', () => {
|
|
372
372
|
expect(record.isExtractOnly).to.equal(true);
|
|
373
373
|
});
|
|
374
374
|
|
|
375
|
-
it('returns the record id',
|
|
375
|
+
it('returns the record id', () => {
|
|
376
376
|
expect(record.id).to.include(id);
|
|
377
377
|
});
|
|
378
378
|
|
|
379
|
-
it('states that it is not the first record',
|
|
379
|
+
it('states that it is not the first record', () => {
|
|
380
380
|
expect(isFirstRecord).to.be.false;
|
|
381
381
|
});
|
|
382
382
|
});
|
|
@@ -403,9 +403,9 @@ describe('Recorder', () => {
|
|
|
403
403
|
record = await recorder.versionsRepository.findLatest(SERVICE_ID, TYPE);
|
|
404
404
|
});
|
|
405
405
|
|
|
406
|
-
after(
|
|
406
|
+
after(() => recorder.versionsRepository.removeAll());
|
|
407
407
|
|
|
408
|
-
it('does not record any version',
|
|
408
|
+
it('does not record any version', () => {
|
|
409
409
|
expect(id).to.not.be.ok;
|
|
410
410
|
});
|
|
411
411
|
});
|
|
@@ -30,7 +30,7 @@ export default class Git {
|
|
|
30
30
|
.addConfig('core.quotePath', false); // disable Git's encoding of special characters in pathnames. For example, `service·A` will be encoded as `service\302\267A` without this setting, leading to issues. See https://git-scm.com/docs/git-config#Documentation/git-config.txt-corequotePath
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
add(filePath) {
|
|
34
34
|
return this.git.add(this.relativePath(filePath));
|
|
35
35
|
}
|
|
36
36
|
|
|
@@ -55,11 +55,11 @@ export default class Git {
|
|
|
55
55
|
return summary.commit;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
pushChanges() {
|
|
59
59
|
return this.git.push();
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
listCommits(options = []) {
|
|
63
63
|
return this.log([ '--reverse', '--no-merges', '--name-only', ...options ]);
|
|
64
64
|
}
|
|
65
65
|
|
|
@@ -89,11 +89,11 @@ export default class Git {
|
|
|
89
89
|
return Boolean(result);
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
|
|
92
|
+
checkout(options) {
|
|
93
93
|
return this.git.checkout(options);
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
|
|
96
|
+
show(options) {
|
|
97
97
|
return this.git.show(options);
|
|
98
98
|
}
|
|
99
99
|
|
|
@@ -107,7 +107,7 @@ export default class Git {
|
|
|
107
107
|
return (await this.git.show([ shortHash, '--pretty=%H', '-s' ])).trim();
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
|
|
110
|
+
restore(path, commit) {
|
|
111
111
|
return this.git.raw([ 'restore', '-s', commit, '--', path ]);
|
|
112
112
|
}
|
|
113
113
|
|
|
@@ -100,7 +100,7 @@ export default class GitRepository extends RepositoryInterface {
|
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
|
|
103
|
+
removeAll() {
|
|
104
104
|
return this.git.destroyHistory();
|
|
105
105
|
}
|
|
106
106
|
|
|
@@ -129,7 +129,9 @@ export default class GitRepository extends RepositoryInterface {
|
|
|
129
129
|
|
|
130
130
|
async #getCommits() {
|
|
131
131
|
return (await this.git.listCommits())
|
|
132
|
-
.filter(
|
|
132
|
+
.filter(commit => // Skip non-record commits (e.g., README or LICENSE updates)
|
|
133
|
+
DataMapper.COMMIT_MESSAGE_PREFIXES_REGEXP.test(commit.message) // Commits generated by the engine have messages that match predefined prefixes
|
|
134
|
+
&& path.dirname(commit.diff.files[0].file) !== '.') // Assumes one record per commit; records must be in a serviceId folder, not root
|
|
133
135
|
.sort((commitA, commitB) => new Date(commitA.date) - new Date(commitB.date)); // Make sure that the commits are sorted in ascending chronological order
|
|
134
136
|
}
|
|
135
137
|
|