Skip to content
Permalink
Browse files

Merge pull request #1423 from input-output-hk/feature/ddw-677-impleme…

…nt-alternative-update-path-for-manual-updates

[DDW-677] Implement alternative update path for manual updates - Improvements
  • Loading branch information...
nikolaglumac committed Jun 12, 2019
2 parents cb09769 + 657019b commit 3601b51e87716be4f194de5e1f0f623e16ed81e6
@@ -5,7 +5,7 @@ Changelog

### Fixes

- Implemented alternative update path for manual updates ([PR 1410](https://github.com/input-output-hk/daedalus/pull/1410))
- Implemented alternative update path for manual updates ([PR 1410](https://github.com/input-output-hk/daedalus/pull/1410), [PR 1423](https://github.com/input-output-hk/daedalus/pull/1423))

## 0.13.1

@@ -1,11 +1,11 @@
Feature: App Version Difference Overlay
Feature: Manual Software Update Overlay

Background:
Given I have completed the basic setup
Scenario: New version available overlay
Given I set app in connecting state
And I check for available app updates
And I get available app version greater than current
Then I should see Manual Update overlay


@reconnectApp
Scenario: Daedalus is unable to connect while there is a new version available
Given There is a newer application version available
And Daedalus is stuck in connecting state
And I should see the "Manual Update" overlay
Then The overlay should accurately display the version info
@@ -1,22 +1,54 @@
import { Given, When, Then } from 'cucumber';
import { expect } from 'chai';
import { environment } from '../../source/main/environment';
import { getVisibleTextsForSelector } from '../support/helpers/shared-helpers';
import i18n from '../support/helpers/i18n-helpers';

Given(/^I set app in connecting state$/, async function () {
await this.client.execute(() => daedalus.api.ada.unsubscribeNode());
});
const SELECTORS = {
MANUAL_UPDATE_VERSION_INFO:
'.ManualUpdateOverlay_content .ManualUpdateOverlay_description p:nth-child(2)',
};

const currentAppVersion = environment.version;
const currentAppVersionChunks = currentAppVersion.split('.');
const nextAppVersion = [
currentAppVersionChunks[0],
parseInt(currentAppVersionChunks[1], 10) + 1,
currentAppVersionChunks[2],
].join('.');

When(/^I check for available app updates$/, async function () {
await this.client.execute(() => daedalus.actions.nodeUpdate.getLatestAvailableAppVersion.trigger());
Given(/^There is a newer application version available$/, async function () {
await this.client.execute(version => {
daedalus.api.ada.setLatestAppVersion(version);
}, nextAppVersion);
});

When(/^I get available app version greater than current$/, async function () {
const availableAppVersion = await this.client.execute(() => (
daedalus.stores.nodeUpdate.availableAppVersion
));
expect(parseFloat(availableAppVersion.value)).to.be.gt(parseFloat(environment.version));
When(/^Daedalus is stuck in connecting state$/, async function () {
await this.client.execute(() => daedalus.api.ada.setSubscriptionStatus({}));
});

Then(/^I should see Manual Update overlay$/, function () {
Then(/^I should see the "Manual Update" overlay$/, function () {
return this.client.waitForVisible('.ManualUpdateOverlay_content');
});

Then(
/^The overlay should accurately display the version info$/,
async function () {
const [renderedText] = await getVisibleTextsForSelector(
this.client,
SELECTORS.MANUAL_UPDATE_VERSION_INFO
);

let expectedText = await i18n.formatMessage(this.client, {
id: 'manualUpdateOverlay.description2',
values: {
currentAppVersion,
availableAppVersion: nextAppVersion,
},
});
// Expected text contains HTML tags so we need to strip them before running comparison
expectedText = expectedText.replace(/<[^>]*>?/gm, '');

expect(renderedText).to.equal(expectedText);
}
);
@@ -100,6 +100,19 @@ After({ tags: '@restartApp' }, async function () {
context.app = await startApp();
});

// this ensures that the reset-backend call successfully executes
// after the app version difference test sets the app to disconnected state
// eslint-disable-next-line prefer-arrow-callback
After({ tags: '@reconnectApp' }, async function () {
await this.client.executeAsync(done => {
daedalus.api.ada
.setSubscriptionStatus(null)
.then(() => daedalus.stores.networkStatus._updateNetworkStatus())
.then(done)
.catch(error => done(error));
});
});

// eslint-disable-next-line prefer-arrow-callback
After(async function ({ sourceLocation, result }) {
scenariosCount++;
@@ -21,7 +21,7 @@ import { applyNodeUpdate } from './nodes/requests/applyNodeUpdate';
import { getNodeInfo } from './nodes/requests/getNodeInfo';
import { getNextNodeUpdate } from './nodes/requests/getNextNodeUpdate';
import { postponeNodeUpdate } from './nodes/requests/postponeNodeUpdate';
import { getLatestAppVersionInfo } from './nodes/requests/getLatestAppVersionInfo';
import { getLatestAppVersion } from './nodes/requests/getLatestAppVersion';

// Transactions requests
import { getTransactionFee } from './transactions/requests/getTransactionFee';
@@ -91,10 +91,11 @@ import type {

// Nodes Types
import type {
LatestAppVersionInfoResponse,
NodeInfo,
NodeSoftware,
GetNetworkStatusResponse,
GetLatestAppVersionInfoResponse,
GetLatestAppVersionResponse,
} from './nodes/types';
import type { NodeQueryParams } from './nodes/requests/getNodeInfo';

@@ -833,16 +834,26 @@ export default class AdaApi {
}
};

getLatestAppVersionInfo = async (): Promise<GetLatestAppVersionInfoResponse> => {
Logger.debug('AdaApi::getLatestAppVersionInfo called');
getLatestAppVersion = async (): Promise<GetLatestAppVersionResponse> => {
Logger.debug('AdaApi::getLatestAppVersion called');
try {
const latestAppVersionInfo = await getLatestAppVersionInfo();
Logger.debug('AdaApi::getLatestAppVersionInfo success', {
const { isWindows, platform } = global.environment;
const latestAppVersionInfo: LatestAppVersionInfoResponse = await getLatestAppVersion();
const latestAppVersionPath = `platforms.${
isWindows ? 'windows' : platform
}.version`;
const latestAppVersion = get(
latestAppVersionInfo,
latestAppVersionPath,
null,
);
Logger.debug('AdaApi::getLatestAppVersion success', {
latestAppVersion,
latestAppVersionInfo,
});
return latestAppVersionInfo;
return { latestAppVersion };
} catch (error) {
Logger.error('AdaApi::getLatestAppVersionInfo error', { error });
Logger.error('AdaApi::getLatestAppVersion error', { error });
throw new GenericApiError();
}
};
@@ -855,7 +866,8 @@ export default class AdaApi {
getLocalTimeDifference: Function;
setLocalTimeDifference: Function;
setNextUpdate: Function;
unsubscribeNode: Function;
setSubscriptionStatus: Function;
setLatestAppVersion: Function;

}

@@ -0,0 +1,17 @@
// @flow
import type { DaedalusLatestVersionResponse } from '../types';
import { externalRequest } from '../../utils/externalRequest';
import { getLatestVersionInfoUrl } from '../../../utils/network';

const { isStaging, isTestnet, network } = global.environment;
const hostname = getLatestVersionInfoUrl(network);
const path = isStaging || isTestnet ? '' : '/update.cardano-mainnet.iohk.io';

export const getLatestAppVersion = (): Promise<DaedalusLatestVersionResponse> => (
externalRequest({
hostname,
path: `${path}/daedalus-latest-version.json`,
method: 'GET',
protocol: 'https',
})
);

This file was deleted.

@@ -51,36 +51,40 @@ export type GetNetworkStatusResponse = {
}
};

export type GetLatestAppVersionResponse = {
latestAppVersion: ?string,
};

export type Platform = {
signature: string,
hash: string,
URL: string,
version: string,
SHA256: string,
signature: string,
version: string,
URL: string,
};

export type Platforms = {
['windows' | 'darwin' | 'linux']: Platform,
};

export type DaedalusLatestVersionResponse = {
platforms: Platforms,
linux: string,
linuxHash: string,
macosSignature: string,
win64: string,
linuxSHA256: string,
linuxSignature: string,
linuxURL: string,
macos: string,
macosHash: string,
macosSHA256: string,
win64Hash: string,
macosSignature: string,
macosURL: string,
win64URL: string,
linuxSHA256: string,
platforms: Platforms,
release_notes: ?string,
macos: string,
win64Signature: string,
linux: string,
macosHash: string,
win64: string,
win64Hash: string,
win64SHA256: string,
win64Signature: string,
win64URL: string,
};

export type GetLatestAppVersionInfoResponse = DaedalusLatestVersionResponse;
export type LatestAppVersionInfoResponse = DaedalusLatestVersionResponse;
@@ -1,6 +1,6 @@
// @flow
import { omit, map } from 'lodash';
import { ALLOWED_EXTERNAL_SOURCES } from '../../config/urlsConfig';
import { omit } from 'lodash';
import { ALLOWED_EXTERNAL_HOSTNAMES } from '../../config/urlsConfig';

export type HttpOptions = {
hostname: string,
@@ -16,15 +16,7 @@ export type HttpOptions = {

export const externalRequest = (httpOptions: HttpOptions): Promise<any> => (
new Promise((resolve, reject) => {
let isAllowed = false;
map(ALLOWED_EXTERNAL_SOURCES, (allowedSource) => {
const allowedHostname = allowedSource.split('/')[2];
if (allowedHostname === httpOptions.hostname) {
isAllowed = true;
}
});

if (!isAllowed) {
if (!ALLOWED_EXTERNAL_HOSTNAMES.includes(httpOptions.hostname)) {
return reject(new Error('Hostname not allowed'));
}

@@ -40,8 +32,13 @@ export const externalRequest = (httpOptions: HttpOptions): Promise<any> => (
});
response.on('error', error => reject(error));
response.on('end', () => {
const parsedBody = JSON.parse(body);
return resolve(parsedBody);
try {
const parsedBody = JSON.parse(body);
resolve(parsedBody);
} catch (error) {
// Handle internal server errors (e.g. HTTP 500 - 'Something went wrong')
reject(new Error(error));
}
});
});
request.on('error', error => reject(error));

0 comments on commit 3601b51

Please sign in to comment.
You can’t perform that action at this time.