Skip to content

Commit

Permalink
test: add PublisherERS tests
Browse files Browse the repository at this point in the history
  • Loading branch information
erickzhao committed Mar 23, 2022
1 parent 2ed8ead commit eb0d2d0
Show file tree
Hide file tree
Showing 2 changed files with 209 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,15 @@ export default class PublisherERS extends PublisherBase<PublisherERSConfig> {
fetchAndCheckStatus(api(apiPath), { ...(options || {}), headers: { ...(options || {}).headers, Authorization: `Bearer ${token}` } });

const versions: ERSVersion[] = await (await authFetch('api/version')).json();
const flavor = config.flavor || 'default';

for (const makeResult of makeResults) {
const { packageJSON } = makeResult;
const artifacts = makeResult.artifacts.filter((artifactPath) => path.basename(artifactPath).toLowerCase() !== 'releases');

const existingVersion = versions.find((version) => version.name === packageJSON.version && version.flavor === config.flavor);
const existingVersion = versions.find((version) => {
return version.name === packageJSON.version && (!version.flavor || version.flavor === flavor);
});

let channel = 'stable';
if (config.channel) {
Expand Down
207 changes: 205 additions & 2 deletions packages/publisher/electron-release-server/test/PublisherERS_spec.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,217 @@
import { expect } from 'chai';
import { ForgeConfig } from '@electron-forge/shared-types';
import { ForgeConfig, ForgeMakeResult } from '@electron-forge/shared-types';
import fetchMock from 'fetch-mock';
import proxyquire from 'proxyquire';

describe('PublisherERS', () => {
let fetch: typeof fetchMock;

beforeEach(() => {
fetch = fetchMock.sandbox();
});
it('fail if the server returns 4xx', async () => {

describe('new version', () => {
it('can publish a new version to ERS', async () => {
const baseUrl = 'https://example.com';
const token = 'FAKE_TOKEN';
const flavor = 'lite';
const version = '3.0.0';

// mock login
fetch.postOnce('path:/api/auth/login', { body: { token }, status: 200 });
// mock fetch all existing versions
fetch.getOnce('path:/api/version', { body: [{ name: '2.0.0', assets: [], flavor: 'default' }], status: 200 });
// mock creating a new version
fetch.postOnce('path:/api/version', { status: 200 });
// mock asset upload
fetch.post('path:/api/asset', { status: 200 });
const PublisherERS = proxyquire.noCallThru().load('../src/PublisherERS', {
'node-fetch': fetch,
}).default;

const publisher = new PublisherERS({
baseUrl,
username: 'test',
password: 'test',
flavor,
});

const makeResults: ForgeMakeResult[] = [
{
artifacts: ['/path/to/artifact'],
packageJSON: {
version,
},
platform: 'linux',
arch: 'x64',
},
];

await publisher.publish({ makeResults, dir: '', forgeConfig: {} as ForgeConfig });

const calls = fetch.calls();

// creates a new version with the correct flavor, name, and channel
expect(calls[2][0]).to.equal(`${baseUrl}/api/version`);
expect(calls[2][1]?.body).to.equal(`{"channel":{"name":"stable"},"flavor":"${flavor}","name":"${version}","notes":""}`);

// uploads asset successfully
expect(calls[3][0]).to.equal(`${baseUrl}/api/asset`);
});
});

describe('existing version', () => {
it('can add new assets', async () => {
const baseUrl = 'https://example.com';
const token = 'FAKE_TOKEN';
const channel = 'stable';
const flavor = 'lite';
const version = '2.0.0';

// mock login
fetch.postOnce('path:/api/auth/login', { body: { token }, status: 200 });
// mock fetch all existing versions
fetch.getOnce('path:/api/version', { body: [{ name: '2.0.0', assets: [], flavor: 'lite' }], status: 200 });
// mock asset upload
fetch.post('path:/api/asset', { status: 200 });

const PublisherERS = proxyquire.noCallThru().load('../src/PublisherERS', {
'node-fetch': fetch,
}).default;

const publisher = new PublisherERS({
baseUrl,
username: 'test',
password: 'test',
channel,
flavor,
});

const makeResults: ForgeMakeResult[] = [
{
artifacts: ['/path/to/artifact'],
packageJSON: {
version,
},
platform: 'linux',
arch: 'x64',
},
];

await publisher.publish({ makeResults, dir: '', forgeConfig: {} as ForgeConfig });

const calls = fetch.calls();

// uploads asset successfully
expect(calls[2][0]).to.equal(`${baseUrl}/api/asset`);
});

it('does not replace assets for existing version', async () => {
const baseUrl = 'https://example.com';
const token = 'FAKE_TOKEN';
const channel = 'stable';
const version = '2.0.0';

// mock login
fetch.postOnce('path:/api/auth/login', { body: { token }, status: 200 });
// mock fetch all existing versions
fetch.getOnce('path:/api/version', { body: [{ name: '2.0.0', assets: [{ name: 'existing-artifact' }], flavor: 'default' }], status: 200 });

const PublisherERS = proxyquire.noCallThru().load('../src/PublisherERS', {
'node-fetch': fetch,
}).default;

const publisher = new PublisherERS({
baseUrl,
username: 'test',
password: 'test',
channel,
});

const makeResults: ForgeMakeResult[] = [
{
artifacts: ['/path/to/existing-artifact'],
packageJSON: {
version,
},
platform: 'linux',
arch: 'x64',
},
];

await publisher.publish({ makeResults, dir: '', forgeConfig: {} as ForgeConfig });

const calls = fetch.calls();
expect(calls).to.have.length(2);
});

it('can upload a new flavor for an existing version', async () => {
const baseUrl = 'https://example.com';
const token = 'FAKE_TOKEN';
const version = '2.0.0';
const flavor = 'lite';

// mock login
fetch.postOnce('path:/api/auth/login', { body: { token }, status: 200 });
// mock fetch all existing versions
fetch.getOnce('path:/api/version', { body: [{ name: '2.0.0', assets: [{ name: 'existing-artifact' }], flavor: 'default' }], status: 200 });
// mock creating a new version
fetch.postOnce('path:/api/version', { status: 200 });
// mock asset upload
fetch.post('path:/api/asset', { status: 200 });

const PublisherERS = proxyquire.noCallThru().load('../src/PublisherERS', {
'node-fetch': fetch,
}).default;

const publisher = new PublisherERS({
baseUrl,
username: 'test',
password: 'test',
flavor,
});

const makeResults: ForgeMakeResult[] = [
{
artifacts: ['/path/to/artifact'],
packageJSON: {
version,
},
platform: 'linux',
arch: 'x64',
},
];

await publisher.publish({ makeResults, dir: '', forgeConfig: {} as ForgeConfig });

const calls = fetch.calls();

// creates a new version with the correct flavor, name, and channel
expect(calls[2][0]).to.equal(`${baseUrl}/api/version`);
expect(calls[2][1]?.body).to.equal(`{"channel":{"name":"stable"},"flavor":"${flavor}","name":"${version}","notes":""}`);

// uploads asset successfully
expect(calls[3][0]).to.equal(`${baseUrl}/api/asset`);
});

// TODO: implement edge cases
it('can read the channel from the package.json version');
it('does not upload the RELEASES file');
});

it('fails if username and password are not provided', () => {
const PublisherERS = proxyquire.noCallThru().load('../src/PublisherERS', {
'node-fetch': fetch,
}).default;

const publisher = new PublisherERS({});

expect(publisher.publish({ makeResults: [], dir: '', forgeConfig: {} as ForgeConfig })).to.eventually.be.rejectedWith(
'In order to publish to ERS you must set the "electronReleaseServer.baseUrl", "electronReleaseServer.username" and "electronReleaseServer.password" properties in your Forge config. See the docs for more info'
);
});

it('fails if the server returns 4xx', async () => {
fetch.mock('begin:http://example.com', { body: {}, status: 400 });
const PublisherERS = proxyquire.noCallThru().load('../src/PublisherERS', {
'node-fetch': fetch,
Expand Down

0 comments on commit eb0d2d0

Please sign in to comment.