Skip to content

Commit 7574752

Browse files
feat(GHA): add req header containing file URL (#735)
* feat(GHA): add req header containing file URL * test: fix coverage for ci.name * chore: add eslint rule for importing `ci-info` * chore: add smol jsdoc * chore: another JSdoc * chore: fix whitespace * refactor: separate GHA runner setup/teardown ... into separate functions * chore: rename variable * chore: misc JSDocs * chore: include sanitized headers in debug logs * fix: normalize relative file paths * test: a buttload of tests * test: consolidate some CI tests * chore: fix a JSDoc * revert: restore a test to its original place it's failing now but not sure why 😬 * chore: try different approach to GHA env vars feedback: #735 (comment) https://www.webtips.dev/how-to-mock-processenv-in-jest * refactor: use shorthand Co-Authored-By: Ryan Park <ryan@ryanpark.org> * fix: better approach to normalizing file path feedback: #735 (comment) * chore: fix JSDoc --------- Co-authored-by: Ryan Park <ryan@ryanpark.org>
1 parent 968c653 commit 7574752

File tree

12 files changed

+638
-109
lines changed

12 files changed

+638
-109
lines changed

.eslintrc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@
5555
"name": "node-fetch",
5656
"importNames": ["default"],
5757
"message": "Avoid using `node-fetch` directly and instead use the fetch wrapper located in `lib/fetch.ts`. See CONTRIBUTING.md for more information."
58+
},
59+
{
60+
"name": "ci-info",
61+
"message": "The `ci-info` package is difficult to test because misleading results will appear when running tests in the GitHub Actions runner. Instead of importing this package directly, create a wrapper function in `lib/isCI.ts` and import that instead."
5862
}
5963
]
6064
}

__tests__/cmds/docs/index.test.ts

Lines changed: 133 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import configstore from '../../../src/lib/configstore';
1414
import getAPIMock, { getAPIMockWithVersionHeader } from '../../helpers/get-api-mock';
1515
import { after, before } from '../../helpers/get-gha-setup';
1616
import hashFileContents from '../../helpers/hash-file-contents';
17+
import { after as afterGHAEnv, before as beforeGHAEnv } from '../../helpers/setup-gha-env';
1718

1819
const docs = new DocsCommand();
1920
const guides = new GuidesCommand();
@@ -68,12 +69,6 @@ describe('rdme docs', () => {
6869
jest.resetAllMocks();
6970
});
7071

71-
it('should error in CI if no API key provided', async () => {
72-
process.env.TEST_RDME_CI = 'true';
73-
await expect(docs.run({})).rejects.toStrictEqual(new Error('No project API key provided. Please use `--key`.'));
74-
delete process.env.TEST_RDME_CI;
75-
});
76-
7772
it('should error if no path provided', async () => {
7873
const versionMock = getAPIMock().get(`/api/v1/version/${version}`).basicAuth({ user: key }).reply(200, { version });
7974

@@ -623,6 +618,138 @@ describe('rdme docs', () => {
623618
versionMock.done();
624619
});
625620
});
621+
622+
describe('command execution in GitHub Actions runner', () => {
623+
beforeEach(beforeGHAEnv);
624+
625+
afterEach(afterGHAEnv);
626+
627+
it('should error in CI if no API key provided', () => {
628+
return expect(docs.run({})).rejects.toStrictEqual(new Error('No project API key provided. Please use `--key`.'));
629+
});
630+
631+
it('should sync new docs directory with correct headers', async () => {
632+
const slug = 'new-doc';
633+
const id = '1234';
634+
const doc = frontMatter(fs.readFileSync(path.join(fullFixturesDir, `/new-docs/${slug}.md`)));
635+
const hash = hashFileContents(fs.readFileSync(path.join(fullFixturesDir, `/new-docs/${slug}.md`)));
636+
637+
const getMock = getAPIMockWithVersionHeader(version)
638+
.get(`/api/v1/docs/${slug}`)
639+
.basicAuth({ user: key })
640+
.reply(404, {
641+
error: 'DOC_NOTFOUND',
642+
message: `The doc with the slug '${slug}' couldn't be found`,
643+
suggestion: '...a suggestion to resolve the issue...',
644+
help: 'If you need help, email support@readme.io and mention log "fake-metrics-uuid".',
645+
});
646+
647+
const postMock = getAPIMock({
648+
'x-rdme-ci': 'GitHub Actions (test)',
649+
'x-readme-source': 'cli-gh',
650+
'x-readme-source-url':
651+
'https://github.com/octocat/Hello-World/blob/ffac537e6cbbf934b08745a378932722df287a53/__tests__/__fixtures__/docs/new-docs/new-doc.md',
652+
'x-readme-version': version,
653+
})
654+
.post('/api/v1/docs', { slug, body: doc.content, ...doc.data, lastUpdatedHash: hash })
655+
.basicAuth({ user: key })
656+
.reply(201, { slug, _id: id, body: doc.content, ...doc.data, lastUpdatedHash: hash });
657+
658+
const versionMock = getAPIMock()
659+
.get(`/api/v1/version/${version}`)
660+
.basicAuth({ user: key })
661+
.reply(200, { version });
662+
663+
await expect(docs.run({ filePath: `./__tests__/${fixturesBaseDir}/new-docs`, key, version })).resolves.toBe(
664+
`🌱 successfully created 'new-doc' (ID: 1234) with contents from __tests__/${fixturesBaseDir}/new-docs/new-doc.md`
665+
);
666+
667+
getMock.done();
668+
postMock.done();
669+
versionMock.done();
670+
});
671+
672+
it('should sync existing docs directory with correct headers', () => {
673+
let fileContents = fs.readFileSync(path.join(fullFixturesDir, '/existing-docs/simple-doc.md'));
674+
const simpleDoc = {
675+
slug: 'simple-doc',
676+
doc: frontMatter(fileContents),
677+
hash: hashFileContents(fileContents),
678+
};
679+
680+
fileContents = fs.readFileSync(path.join(fullFixturesDir, '/existing-docs/subdir/another-doc.md'));
681+
const anotherDoc = {
682+
slug: 'another-doc',
683+
doc: frontMatter(fileContents),
684+
hash: hashFileContents(fileContents),
685+
};
686+
687+
expect.assertions(1);
688+
689+
const getMocks = getAPIMockWithVersionHeader(version)
690+
.get('/api/v1/docs/simple-doc')
691+
.basicAuth({ user: key })
692+
.reply(200, { category, slug: simpleDoc.slug, lastUpdatedHash: 'anOldHash' })
693+
.get('/api/v1/docs/another-doc')
694+
.basicAuth({ user: key })
695+
.reply(200, { category, slug: anotherDoc.slug, lastUpdatedHash: 'anOldHash' });
696+
697+
const firstUpdateMock = getAPIMock({
698+
'x-rdme-ci': 'GitHub Actions (test)',
699+
'x-readme-source': 'cli-gh',
700+
'x-readme-source-url':
701+
'https://github.com/octocat/Hello-World/blob/ffac537e6cbbf934b08745a378932722df287a53/__tests__/__fixtures__/docs/existing-docs/simple-doc.md',
702+
'x-readme-version': version,
703+
})
704+
.put('/api/v1/docs/simple-doc', {
705+
body: simpleDoc.doc.content,
706+
lastUpdatedHash: simpleDoc.hash,
707+
...simpleDoc.doc.data,
708+
})
709+
.basicAuth({ user: key })
710+
.reply(200, {
711+
category,
712+
slug: simpleDoc.slug,
713+
body: simpleDoc.doc.content,
714+
});
715+
716+
const secondUpdateMock = getAPIMock({
717+
'x-rdme-ci': 'GitHub Actions (test)',
718+
'x-readme-source': 'cli-gh',
719+
'x-readme-source-url':
720+
'https://github.com/octocat/Hello-World/blob/ffac537e6cbbf934b08745a378932722df287a53/__tests__/__fixtures__/docs/existing-docs/subdir/another-doc.md',
721+
'x-readme-version': version,
722+
})
723+
.put('/api/v1/docs/another-doc', {
724+
body: anotherDoc.doc.content,
725+
lastUpdatedHash: anotherDoc.hash,
726+
...anotherDoc.doc.data,
727+
})
728+
.basicAuth({ user: key })
729+
.reply(200, { category, slug: anotherDoc.slug, body: anotherDoc.doc.content });
730+
731+
const versionMock = getAPIMock()
732+
.get(`/api/v1/version/${version}`)
733+
.basicAuth({ user: key })
734+
.reply(200, { version });
735+
736+
return docs.run({ filePath: `__tests__/${fixturesBaseDir}/existing-docs`, key, version }).then(updatedDocs => {
737+
// All docs should have been updated because their hashes from the GET request were different from what they
738+
// are currently.
739+
expect(updatedDocs).toBe(
740+
[
741+
`✏️ successfully updated 'simple-doc' with contents from __tests__/${fixturesBaseDir}/existing-docs/simple-doc.md`,
742+
`✏️ successfully updated 'another-doc' with contents from __tests__/${fixturesBaseDir}/existing-docs/subdir/another-doc.md`,
743+
].join('\n')
744+
);
745+
746+
getMocks.done();
747+
firstUpdateMock.done();
748+
secondUpdateMock.done();
749+
versionMock.done();
750+
});
751+
});
752+
});
626753
});
627754

628755
describe('rdme guides', () => {

__tests__/cmds/docs/single.test.ts

Lines changed: 104 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import DocsCommand from '../../../src/cmds/docs';
1010
import APIError from '../../../src/lib/apiError';
1111
import getAPIMock, { getAPIMockWithVersionHeader } from '../../helpers/get-api-mock';
1212
import hashFileContents from '../../helpers/hash-file-contents';
13+
import { after as afterGHAEnv, before as beforeGHAEnv } from '../../helpers/setup-gha-env';
1314

1415
const docs = new DocsCommand();
1516

@@ -32,12 +33,6 @@ describe('rdme docs (single)', () => {
3233
consoleInfoSpy.mockRestore();
3334
});
3435

35-
it('should error in CI if no API key provided', async () => {
36-
process.env.TEST_RDME_CI = 'true';
37-
await expect(docs.run({})).rejects.toStrictEqual(new Error('No project API key provided. Please use `--key`.'));
38-
delete process.env.TEST_RDME_CI;
39-
});
40-
4136
it('should error if no file path provided', async () => {
4237
const versionMock = getAPIMock().get(`/api/v1/version/${version}`).basicAuth({ user: key }).reply(200, { version });
4338

@@ -347,4 +342,107 @@ describe('rdme docs (single)', () => {
347342
});
348343
});
349344
});
345+
346+
describe('command execution in GitHub Actions runner', () => {
347+
beforeEach(beforeGHAEnv);
348+
349+
afterEach(afterGHAEnv);
350+
351+
it('should error in CI if no API key provided', () => {
352+
return expect(docs.run({})).rejects.toStrictEqual(new Error('No project API key provided. Please use `--key`.'));
353+
});
354+
355+
it('should sync new doc with correct headers', async () => {
356+
const slug = 'new-doc';
357+
const id = '1234';
358+
const doc = frontMatter(fs.readFileSync(path.join(fullFixturesDir, `/new-docs/${slug}.md`)));
359+
const hash = hashFileContents(fs.readFileSync(path.join(fullFixturesDir, `/new-docs/${slug}.md`)));
360+
361+
const getMock = getAPIMockWithVersionHeader(version)
362+
.get(`/api/v1/docs/${slug}`)
363+
.basicAuth({ user: key })
364+
.reply(404, {
365+
error: 'DOC_NOTFOUND',
366+
message: `The doc with the slug '${slug}' couldn't be found`,
367+
suggestion: '...a suggestion to resolve the issue...',
368+
help: 'If you need help, email support@readme.io and mention log "fake-metrics-uuid".',
369+
});
370+
371+
const postMock = getAPIMock({
372+
'x-rdme-ci': 'GitHub Actions (test)',
373+
'x-readme-source': 'cli-gh',
374+
'x-readme-source-url':
375+
'https://github.com/octocat/Hello-World/blob/ffac537e6cbbf934b08745a378932722df287a53/__tests__/__fixtures__/docs/new-docs/new-doc.md',
376+
'x-readme-version': version,
377+
})
378+
.post('/api/v1/docs', { slug, body: doc.content, ...doc.data, lastUpdatedHash: hash })
379+
.basicAuth({ user: key })
380+
.reply(201, { slug, _id: id, body: doc.content, ...doc.data, lastUpdatedHash: hash });
381+
382+
const versionMock = getAPIMock()
383+
.get(`/api/v1/version/${version}`)
384+
.basicAuth({ user: key })
385+
.reply(200, { version });
386+
387+
await expect(
388+
docs.run({ filePath: `./__tests__/${fixturesBaseDir}/new-docs/new-doc.md`, key, version })
389+
).resolves.toBe(
390+
`🌱 successfully created 'new-doc' (ID: 1234) with contents from ./__tests__/${fixturesBaseDir}/new-docs/new-doc.md`
391+
);
392+
393+
getMock.done();
394+
postMock.done();
395+
versionMock.done();
396+
});
397+
398+
it('should sync existing doc with correct headers', () => {
399+
const fileContents = fs.readFileSync(path.join(fullFixturesDir, '/existing-docs/simple-doc.md'));
400+
const simpleDoc = {
401+
slug: 'simple-doc',
402+
doc: frontMatter(fileContents),
403+
hash: hashFileContents(fileContents),
404+
};
405+
406+
const getMock = getAPIMockWithVersionHeader(version)
407+
.get('/api/v1/docs/simple-doc')
408+
.basicAuth({ user: key })
409+
.reply(200, { category, slug: simpleDoc.slug, lastUpdatedHash: 'anOldHash' });
410+
411+
const updateMock = getAPIMock({
412+
'x-rdme-ci': 'GitHub Actions (test)',
413+
'x-readme-source': 'cli-gh',
414+
'x-readme-source-url':
415+
'https://github.com/octocat/Hello-World/blob/ffac537e6cbbf934b08745a378932722df287a53/__tests__/__fixtures__/docs/existing-docs/simple-doc.md',
416+
'x-readme-version': version,
417+
})
418+
.put('/api/v1/docs/simple-doc', {
419+
body: simpleDoc.doc.content,
420+
lastUpdatedHash: simpleDoc.hash,
421+
...simpleDoc.doc.data,
422+
})
423+
.basicAuth({ user: key })
424+
.reply(200, {
425+
category,
426+
slug: simpleDoc.slug,
427+
body: simpleDoc.doc.content,
428+
});
429+
430+
const versionMock = getAPIMock()
431+
.get(`/api/v1/version/${version}`)
432+
.basicAuth({ user: key })
433+
.reply(200, { version });
434+
435+
return docs
436+
.run({ filePath: `__tests__/${fixturesBaseDir}/existing-docs/simple-doc.md`, key, version })
437+
.then(updatedDocs => {
438+
expect(updatedDocs).toBe(
439+
`✏️ successfully updated 'simple-doc' with contents from __tests__/${fixturesBaseDir}/existing-docs/simple-doc.md`
440+
);
441+
442+
getMock.done();
443+
updateMock.done();
444+
versionMock.done();
445+
});
446+
});
447+
});
350448
});

0 commit comments

Comments
 (0)