Skip to content

Commit dd52bb5

Browse files
committed
test: add unit tests for Julia updater and strategy
1 parent 382ce4b commit dd52bb5

File tree

3 files changed

+281
-0
lines changed

3 files changed

+281
-0
lines changed

test/strategies/julia.ts

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
import {describe, it, afterEach, beforeEach} from 'mocha';
16+
import {expect} from 'chai';
17+
import {GitHub} from '../../src/github';
18+
import {Julia} from '../../src/strategies/julia';
19+
import * as sinon from 'sinon';
20+
import {
21+
buildGitHubFileContent,
22+
assertHasUpdate,
23+
assertNoHasUpdate,
24+
} from '../helpers';
25+
import {buildMockConventionalCommit} from '../helpers';
26+
import {TagName} from '../../src/util/tag-name';
27+
import {Version} from '../../src/version';
28+
import {JuliaProjectToml} from '../../src/updaters/julia/project-toml';
29+
import {Changelog} from '../../src/updaters/changelog';
30+
import {ChangelogJson} from '../../src/updaters/changelog-json';
31+
import * as snapshot from 'snap-shot-it';
32+
33+
const sandbox = sinon.createSandbox();
34+
const fixturesPath = './test/fixtures/strategies/python';
35+
36+
const UUID_REGEX =
37+
/[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}/g;
38+
const ISO_DATE_REGEX =
39+
/[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]+Z/g; // 2023-01-05T16:42:33.446Z
40+
41+
const COMMITS = [
42+
...buildMockConventionalCommit(
43+
'fix(deps): update dependency com.google.cloud:google-cloud-storage to v1.120.0'
44+
),
45+
...buildMockConventionalCommit(
46+
'fix(deps): update dependency com.google.cloud:google-cloud-spanner to v1.50.0'
47+
),
48+
...buildMockConventionalCommit('chore: update common templates'),
49+
];
50+
51+
describe('Julia', () => {
52+
let github: GitHub;
53+
beforeEach(async () => {
54+
github = await GitHub.create({
55+
owner: 'googleapis',
56+
repo: 'julia-test-repo',
57+
defaultBranch: 'main',
58+
});
59+
});
60+
afterEach(() => {
61+
sandbox.restore();
62+
});
63+
describe('buildReleasePullRequest', () => {
64+
it('returns release PR changes with defaultInitialVersion', async () => {
65+
const expectedVersion = '0.1.0';
66+
const strategy = new Julia({
67+
targetBranch: 'main',
68+
github,
69+
component: 'ReleasePleaseJuliaStrategy',
70+
});
71+
sandbox
72+
.stub(github, 'getFileContentsOnBranch')
73+
.resolves(buildGitHubFileContent(fixturesPath, 'Project.toml'));
74+
sandbox.stub(github, 'findFilesByFilenameAndRef').resolves([]);
75+
const latestRelease = undefined;
76+
const release = await strategy.buildReleasePullRequest(
77+
COMMITS,
78+
latestRelease
79+
);
80+
expect(release!.version?.toString()).to.eql(expectedVersion);
81+
});
82+
it('returns release PR changes with semver patch bump', async () => {
83+
const expectedVersion = '0.123.5';
84+
const strategy = new Julia({
85+
targetBranch: 'main',
86+
github,
87+
component: 'ReleasePleaseJuliaStrategy',
88+
});
89+
sandbox
90+
.stub(github, 'getFileContentsOnBranch')
91+
.resolves(buildGitHubFileContent(fixturesPath, 'Project.toml'));
92+
sandbox.stub(github, 'findFilesByFilenameAndRef').resolves([]);
93+
const latestRelease = {
94+
tag: new TagName(Version.parse('0.123.4'), 'ReleasePleaseJuliaStrategy'),
95+
sha: 'abc123',
96+
notes: 'some notes',
97+
};
98+
const release = await strategy.buildReleasePullRequest(
99+
COMMITS,
100+
latestRelease
101+
);
102+
expect(release!.version?.toString()).to.eql(expectedVersion);
103+
});
104+
});
105+
describe('buildUpdates', () => {
106+
it('builds common files', async () => {
107+
const strategy = new Julia({
108+
targetBranch: 'main',
109+
github,
110+
component: 'google-cloud-automl',
111+
});
112+
sandbox
113+
.stub(github, 'getFileContentsOnBranch')
114+
.resolves(buildGitHubFileContent(fixturesPath, 'setup.py'));
115+
sandbox.stub(github, 'findFilesByFilenameAndRef').resolves([]);
116+
const latestRelease = undefined;
117+
const release = await strategy.buildReleasePullRequest(
118+
COMMITS,
119+
latestRelease
120+
);
121+
const updates = release!.updates;
122+
assertHasUpdate(updates, 'CHANGELOG.md', Changelog);
123+
assertHasUpdate(updates, 'Project.toml', JuliaProjectToml);
124+
});
125+
126+
it('omits changelog if skipChangelog=true', async () => {
127+
const strategy = new Julia({
128+
targetBranch: 'main',
129+
github,
130+
component: 'ReleasePleaseJuliaStrategy',
131+
skipChangelog: true,
132+
});
133+
sandbox
134+
.stub(github, 'getFileContentsOnBranch')
135+
.resolves(buildGitHubFileContent(fixturesPath, 'Project.toml'));
136+
sandbox.stub(github, 'findFilesByFilenameAndRef').resolves([]);
137+
const latestRelease = undefined;
138+
const release = await strategy.buildReleasePullRequest(
139+
COMMITS,
140+
latestRelease
141+
);
142+
const updates = release!.updates;
143+
assertNoHasUpdate(updates, 'CHANGELOG.md');
144+
assertHasUpdate(updates, 'Project.toml', JuliaProjectToml);
145+
});
146+
147+
it('finds and updates a pyproject.toml', async () => {
148+
const strategy = new Julia({
149+
targetBranch: 'main',
150+
github,
151+
component: 'ReleasePleaseJuliaStrategy',
152+
});
153+
sandbox
154+
.stub(github, 'getFileContentsOnBranch')
155+
.resolves(
156+
buildGitHubFileContent('./test/updaters/fixtures', 'Project.toml')
157+
);
158+
sandbox.stub(github, 'findFilesByFilenameAndRef').resolves([]);
159+
const latestRelease = undefined;
160+
const release = await strategy.buildReleasePullRequest(
161+
COMMITS,
162+
latestRelease
163+
);
164+
const updates = release!.updates;
165+
assertHasUpdate(updates, 'Project.toml', JuliaProjectToml);
166+
});
167+
168+
it('updates changelog.json if present', async () => {
169+
const COMMITS = [
170+
...buildMockConventionalCommit(
171+
'fix(deps): update dependency com.google.cloud:google-cloud-storage to v1.120.0'
172+
),
173+
...buildMockConventionalCommit('chore: update deps'),
174+
...buildMockConventionalCommit('chore!: update a very important dep'),
175+
...buildMockConventionalCommit(
176+
'fix(deps): update dependency com.google.cloud:google-cloud-spanner to v1.50.0'
177+
),
178+
...buildMockConventionalCommit('chore: update common templates'),
179+
];
180+
const strategy = new Julia({
181+
targetBranch: 'main',
182+
github,
183+
component: 'ReleasePleaseJuliaStrategy',
184+
});
185+
sandbox.stub(github, 'findFilesByFilenameAndRef').resolves([]);
186+
const getFileContentsStub = sandbox.stub(
187+
github,
188+
'getFileContentsOnBranch'
189+
);
190+
getFileContentsStub
191+
.withArgs('changelog.json', 'main')
192+
.resolves(buildGitHubFileContent(fixturesPath, 'changelog.json'));
193+
getFileContentsStub
194+
.withArgs('Project.toml', 'main')
195+
.resolves(buildGitHubFileContent(fixturesPath, 'Project.toml'));
196+
const latestRelease = undefined;
197+
const release = await strategy.buildReleasePullRequest(
198+
COMMITS,
199+
latestRelease
200+
);
201+
const updates = release!.updates;
202+
assertHasUpdate(updates, 'CHANGELOG.md', Changelog);
203+
const update = assertHasUpdate(updates, 'changelog.json', ChangelogJson);
204+
const newContent = update.updater.updateContent(
205+
JSON.stringify({entries: []})
206+
);
207+
snapshot(
208+
newContent
209+
.replace(/\r\n/g, '\n') // make newline consistent regardless of OS.
210+
.replace(UUID_REGEX, 'abc-123-efd-qwerty')
211+
.replace(ISO_DATE_REGEX, '2023-01-05T16:42:33.446Z')
212+
);
213+
});
214+
});
215+
});
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
name = "ReleasePleaseJuliaStategy"
2+
uuid = "7d294f08-cb76-428f-b375-a2356da1b9f0"
3+
authors = ["Google LLC <[email protected]>>"]
4+
version = "0.5.0"
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
import {readFileSync} from 'fs';
16+
import {resolve} from 'path';
17+
import * as snapshot from 'snap-shot-it';
18+
import {describe, it} from 'mocha';
19+
import {JuliaProjectToml} from '../../src/updaters/julia/project-toml';
20+
import {expect} from 'chai';
21+
import {Version} from '../../src/version';
22+
23+
const fixturesPath = './test/updaters/fixtures';
24+
25+
describe('ProjectToml', () => {
26+
it('refuses to update something that is not a valid project', async () => {
27+
const oldContent = '[woops]\nindeed = true';
28+
const juliaProject = new JuliaProjectToml({
29+
version: Version.parse('0.6.0'),
30+
});
31+
expect(() => {
32+
juliaProject.updateContent(oldContent);
33+
}).to.throw();
34+
});
35+
36+
it('refuses to update when version is missing', async () => {
37+
const oldContent = "[project]\nname = 'project'";
38+
const juliaProject = new JuliaProjectToml({
39+
version: Version.parse('0.6.0'),
40+
});
41+
expect(() => {
42+
juliaProject.updateContent(oldContent);
43+
}).to.throw();
44+
});
45+
});
46+
47+
describe('julia-project.toml', () => {
48+
describe('updateContent', () => {
49+
it('updates version in julia-project.toml', async () => {
50+
const oldContent = readFileSync(
51+
resolve(fixturesPath, './julia-project.toml'),
52+
'utf8'
53+
).replace(/\r\n/g, '\n');
54+
const version = new JuliaProjectToml({
55+
version: Version.parse('0.6.0'),
56+
});
57+
const newContent = version.updateContent(oldContent);
58+
snapshot(newContent);
59+
});
60+
});
61+
});
62+

0 commit comments

Comments
 (0)