Skip to content

Commit

Permalink
feat(scm): defined the publicly browsable url when hosted on github
Browse files Browse the repository at this point in the history
  • Loading branch information
travi committed Feb 11, 2024
1 parent b6e7ef2 commit 16f0039
Show file tree
Hide file tree
Showing 13 changed files with 136 additions and 42 deletions.
13 changes: 8 additions & 5 deletions src/pom/lifter.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import {promises as fs} from 'node:fs';
import {XMLBuilder, XMLParser} from 'fast-xml-parser';
import {XMLParser} from 'fast-xml-parser';

import {write} from './xml/index.js';
import {getPathTo} from './file.js';
import defineScmDetails from './scm.js';

export default async function ({projectRoot}) {
export default async function ({projectRoot, vcs}) {
const pathToPom = getPathTo(projectRoot);
const parser = new XMLParser();
const builder = new XMLBuilder({format: true});
const existingPomContents = parser.parse(await fs.readFile(pathToPom, 'utf-8'));
existingPomContents.project.scm = {tag: 'HEAD'};
await fs.writeFile(pathToPom, builder.build(existingPomContents));

existingPomContents.project.scm = defineScmDetails(vcs);

await write({path: pathToPom, contents: existingPomContents});

return {};
}
28 changes: 17 additions & 11 deletions src/pom/lifter.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@ import {describe, it, expect, vi, afterEach} from 'vitest';
import any from '@travi/any';
import {when} from 'jest-when';

import {write} from './xml/index.js';
import {getPathTo} from './file.js';
import defineScmDetails from './scm.js';
import liftPom from './lifter.js';

vi.mock('node:fs');
vi.mock('./file.js');
vi.mock('./scm.js');
vi.mock('./xml/index.js');

describe('pom lifter', () => {
afterEach(() => {
Expand All @@ -18,21 +22,23 @@ describe('pom lifter', () => {
it('should define the vcs details', async () => {
const projectRoot = any.string();
const pathToPomFile = any.string();
const vcsDetails = any.simpleObject();
const scmDetails = any.simpleObject();
when(fs.readFile)
.calledWith(pathToPomFile, 'utf-8')
.mockResolvedValue('<project><modelVersion>4.0.0</modelVersion></project>');
when(getPathTo).calledWith(projectRoot).mockReturnValue(pathToPomFile);
when(defineScmDetails).calledWith(vcsDetails).mockReturnValue(scmDetails);

expect(await liftPom({projectRoot})).toEqual({});
expect(fs.writeFile).toHaveBeenCalledWith(
pathToPomFile,
`<project>
<modelVersion>4.0.0</modelVersion>
<scm>
<tag>HEAD</tag>
</scm>
</project>
`
);
expect(await liftPom({projectRoot, vcs: vcsDetails})).toEqual({});
expect(write).toHaveBeenCalledWith({
path: pathToPomFile,
contents: {
project: {
modelVersion: '4.0.0',
scm: scmDetails
}
}
});
});
});
19 changes: 10 additions & 9 deletions src/pom/scaffolder.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import {promises as fs} from 'node:fs';
import {XMLBuilder} from 'fast-xml-parser';

import {write} from './xml/index.js';
import {getPathTo} from './file.js';

export default async function ({projectRoot, projectName}) {
const builder = new XMLBuilder({format: true});

await fs.writeFile(
getPathTo(projectRoot),
builder.build({project: {modelVersion: '4.0.0', artifactId: projectName}})
);
await write({
path: getPathTo(projectRoot),
contents: {
project: {
modelVersion: '4.0.0',
artifactId: projectName
}
}
});
}
24 changes: 12 additions & 12 deletions src/pom/scaffolder.test.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import {promises as fs} from 'node:fs';

import {describe, expect, it, vi, afterEach} from 'vitest';
import any from '@travi/any';
import {when} from 'jest-when';

import {write} from './xml/index.js';
import {getPathTo} from './file.js';
import scaffold from './scaffolder.js';

vi.mock('node:fs');
vi.mock('./file.js');
vi.mock('./xml/index.js');

describe('pom scaffolder', () => {
afterEach(() => {
Expand All @@ -23,14 +22,15 @@ describe('pom scaffolder', () => {

await scaffold({projectRoot, projectName});

expect(fs.writeFile)
.toHaveBeenCalledWith(
pathToPomFile,
`<project>
<modelVersion>4.0.0</modelVersion>
<artifactId>${projectName}</artifactId>
</project>
`
);
expect(write)
.toHaveBeenCalledWith({
path: pathToPomFile,
contents: {
project: {
modelVersion: '4.0.0',
artifactId: projectName
}
}
});
});
});
6 changes: 6 additions & 0 deletions src/pom/scm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export default function ({host, owner, name}) {
return {
tag: 'HEAD',
...'github' === host && {url: `https://github.com/${owner}/${name}`}
};
}
21 changes: 21 additions & 0 deletions src/pom/scm.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import {describe, expect, it} from 'vitest';
import any from '@travi/any';

import defineScmDetails from './scm.js';

describe('pom scm details', () => {
it('should define scm details for a project hosted on github.com', () => {
const owner = any.word();
const name = any.word();

expect(defineScmDetails({owner, name, host: 'github'}))
.toEqual({tag: 'HEAD', url: `https://github.com/${owner}/${name}`});
});

it('should only define the tag for a project not hosted on github.com', () => {
const owner = any.word();
const name = any.word();

expect(defineScmDetails({owner, name, host: any.word()})).toEqual({tag: 'HEAD'});
});
});
1 change: 1 addition & 0 deletions src/pom/xml/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export {default as write} from './writer.js';
8 changes: 8 additions & 0 deletions src/pom/xml/writer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import {promises as fs} from 'node:fs';
import {XMLBuilder} from 'fast-xml-parser';

export default async function ({path, contents}) {
const builder = new XMLBuilder({format: true});

await fs.writeFile(path, builder.build(contents));
}
30 changes: 30 additions & 0 deletions src/pom/xml/writer.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import {promises as fs} from 'node:fs';
import {XMLBuilder} from 'fast-xml-parser';

import {afterEach, describe, expect, it, vi} from 'vitest';
import any from '@travi/any';
import {when} from 'jest-when';

import write from './writer.js';

vi.mock('node:fs');
vi.mock('fast-xml-parser');

describe('xml writer', () => {
afterEach(() => {
vi.clearAllMocks();
});

it('should write the provided data to the xml file', async () => {
const pathToFile = any.string();
const contents = any.simpleObject();
const build = vi.fn();
const renderedXml = any.string();
when(XMLBuilder).calledWith({format: true}).mockReturnValue({build});
when(build).calledWith(contents).mockReturnValue(renderedXml);

await write({path: pathToFile, contents});

expect(fs.writeFile).toHaveBeenCalledWith(pathToFile, renderedXml);
});
});
2 changes: 1 addition & 1 deletion test/integration/features/step_definitions/common-steps.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,5 @@ When('the project is scaffolded', async function () {
});

When('the project is lifted', async function () {
await lift({projectRoot: this.projectRoot});
await lift({projectRoot: this.projectRoot, vcs: this.vcsDetails});
});
11 changes: 10 additions & 1 deletion test/integration/features/step_definitions/pom-steps.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,16 @@ import {assert} from 'chai';

Then('the pom file is created', async function () {
const parser = new XMLParser();
const parsedContent = parser.parse(await fs.readFile(`${this.projectRoot}/pom.xml`, 'utf-8'));
const pomContent = await fs.readFile(`${this.projectRoot}/pom.xml`, 'utf-8');
const parsedContent = parser.parse(pomContent);

assert.deepEqual(parsedContent, {project: {modelVersion: '4.0.0', artifactId: this.projectName}});
assert.deepEqual(
pomContent,
`<project>
<modelVersion>4.0.0</modelVersion>
<artifactId>${this.projectName}</artifactId>
</project>
`
);
});
12 changes: 10 additions & 2 deletions test/integration/features/step_definitions/vcs-steps.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
import {promises as fs} from 'node:fs';
import {XMLParser} from 'fast-xml-parser';

import {Given, Then} from '@cucumber/cucumber';
import {XMLParser} from 'fast-xml-parser';
import {assert} from 'chai';
import any from '@travi/any';

Given('vcs details are not defined in the pom', async function () {
await fs.writeFile(`${this.projectRoot}/pom.xml`, '<project><modelVersion>4.0.0</modelVersion></project>');
});

Given('the repository is hosted on github.com', async function () {
const owner = any.word();
const repositoryName = any.word();
this.vcsDetails = {host: 'github', owner, name: repositoryName};
this.vcsUrl = `https://github.com/${owner}/${repositoryName}`;
});

Then('vcs details are defined in the pom', async function () {
const parser = new XMLParser();
const {project: {scm}} = parser.parse(await fs.readFile(`${this.projectRoot}/pom.xml`, 'utf-8'));

assert.deepEqual(scm, {tag: 'HEAD'});
assert.deepEqual(scm, {tag: 'HEAD', url: this.vcsUrl});
});
3 changes: 2 additions & 1 deletion test/integration/features/vcs.feature
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
Feature: Version Control Details

Scenario: No Details Defined
Scenario: No Details Defined for a repository hosted on github.com
Given vcs details are not defined in the pom
And the repository is hosted on github.com
When the project is lifted
Then vcs details are defined in the pom

0 comments on commit 16f0039

Please sign in to comment.