Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows/Linux "About" window #885

Merged
merged 17 commits into from
Jul 7, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
* Fixed critical dependency warning @okwme
* Fixed theme bg bug @okwme
* Fixed sorting bug on staking page @okwme
* "About Cosmos Voyager" menu item is now responsive on Windows and Linux @mappum
* Fixed preference page style bug @okwme
* Fixed missing node-ip in connection indicator @faboweb
* Launch sequence for dev improved @okwme
Expand Down
4 changes: 1 addition & 3 deletions app/src/main/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,9 +169,7 @@ function createWindow() {
webContents.on("will-navigate", handleRedirect)
webContents.on("new-window", handleRedirect)

// addMenu overwrites the default menu to only hold copy/paste actions to not confuse the user
// In development mode we want all the options including switching the devtools
if (!DEV) addMenu()
addMenu(mainWindow)
}

function startProcess(name, args, env) {
Expand Down
9 changes: 7 additions & 2 deletions app/src/main/menu.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
const { app, Menu, shell } = require("electron")

module.exports = function() {
module.exports = function(mainWindow) {
let template = [
{
label: "Cosmos Voyager",
submenu: [
{
label: "About Cosmos Voyager",
selector: "orderFrontStandardAboutPanel:"
selector: "orderFrontStandardAboutPanel:",
click: () => openAboutMenu(mainWindow)
},
{ type: "separator" },
{
Expand Down Expand Up @@ -59,3 +60,7 @@ module.exports = function() {
let menu = Menu.buildFromTemplate(template)
Menu.setApplicationMenu(menu)
}

function openAboutMenu(mainWindow) {
mainWindow.webContents.send("open-about-menu")
}
18 changes: 12 additions & 6 deletions app/src/renderer/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import Raven from "raven-js"
import { ipcRenderer, remote } from "electron"

import App from "./App"
import routes from "./routes"
import routesConstructor from "./routes"
import Node from "./connectors/node"
import Store from "./vuex/store"

Expand All @@ -16,6 +16,7 @@ const config = remote.getGlobal("config")
// exporting this for testing
let store
let node
let router

// Raven serves automatic error reporting. It is turned off by default
Raven.config("").install()
Expand Down Expand Up @@ -43,14 +44,15 @@ async function main() {
console.log("Expecting lcd-server on port:", lcdPort)
node = Node(lcdPort, config.mocked)

const router = new Router({
store = Store({ node })
store.dispatch("loadTheme")

const routes = routesConstructor(store)
router = new Router({
scrollBehavior: () => ({ y: 0 }),
routes
})

store = Store({ node })
store.dispatch("loadTheme")

ipcRenderer.on("error", (event, error) => {
switch (error.code) {
case "NO_NODES_AVAILABLE":
Expand All @@ -65,6 +67,9 @@ async function main() {
console.log(hash)
store.commit("setNodeApprovalRequired", hash)
})
ipcRenderer.on("open-about-menu", event => {
router.push("/about")
})

let firstStart = true
ipcRenderer.on("connected", (event, nodeIP) => {
Expand All @@ -90,7 +95,7 @@ async function main() {

ipcRenderer.send("booted")

new Vue({
return new Vue({
router,
...App,
store
Expand All @@ -102,6 +107,7 @@ main()
// exporting this for testing
module.exports.store = store
module.exports.node = node
module.exports.router = router

function getQueryParameter(name) {
let queryString = window.location.search.substring(1)
Expand Down
151 changes: 83 additions & 68 deletions app/src/renderer/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,76 +8,91 @@ let monitor = r.bind(null, "monitor")
let staking = r.bind(null, "staking")
let wallet = r.bind(null, "wallet")

export default [
{
path: "/proposals",
name: "proposals",
component: govern("Proposals")
},
{ path: "/proposals/new", component: govern("ProposalsNew") },
{ path: "/proposals/new/adjust", component: govern("ProposalsNewAdjust") },
{ path: "/proposals/new/amend", component: govern("ProposalsNewAmend") },
{ path: "/proposals/new/create", component: govern("ProposalsNewCreate") },
{ path: "/proposals/new/text", component: govern("ProposalsNewText") },
{ path: "/proposals/new/upgrade", component: govern("ProposalsNewUpgrade") },
{
path: "/proposals/:proposal",
name: "proposal",
component: govern("Proposal")
},
export default function(store) {
return [
{
path: "/proposals",
name: "proposals",
component: govern("Proposals")
},
{ path: "/proposals/new", component: govern("ProposalsNew") },
{ path: "/proposals/new/adjust", component: govern("ProposalsNewAdjust") },
{ path: "/proposals/new/amend", component: govern("ProposalsNewAmend") },
{ path: "/proposals/new/create", component: govern("ProposalsNewCreate") },
{ path: "/proposals/new/text", component: govern("ProposalsNewText") },
{
path: "/proposals/new/upgrade",
component: govern("ProposalsNewUpgrade")
},
{
path: "/proposals/:proposal",
name: "proposal",
component: govern("Proposal")
},

// MONITOR
{
path: "/blocks",
name: "blocks",
component: monitor("Blocks")
},
{
path: "/blocks/:block",
name: "block",
component: monitor("Block")
},
// MONITOR
{
path: "/blocks",
name: "blocks",
component: monitor("Blocks")
},
{
path: "/blocks/:block",
name: "block",
component: monitor("Block")
},

// STAKE
{
path: "/staking",
name: "staking",
component: staking("Staking")
},
{
path: "/staking/bond",
name: "bond",
component: staking("Bond")
},
{
path: "/staking/delegates/:delegate",
name: "delegate",
component: staking("Delegate")
},
// STAKE
{
path: "/staking",
name: "staking",
component: staking("Staking")
},
{
path: "/staking/bond",
name: "bond",
component: staking("Bond")
},
{
path: "/staking/delegates/:delegate",
name: "delegate",
component: staking("Delegate")
},

{
path: "/preferences",
name: "preferences",
component: common("Preferences")
},
{
path: "/preferences",
name: "preferences",
component: common("Preferences")
},

{
path: "/",
name: "balances",
component: wallet("Wallet")
},
{
path: "/wallet/send/:denom?",
name: "send",
props: true,
component: wallet("Send")
},
{
path: "/wallet/transactions",
name: "transactions",
component: wallet("Transactions")
},
{
path: "/about",
redirect: to => {
store.commit("setAbout", true)

{ path: "/404", component: common("404") },
{ path: "*", component: common("404") }
]
return "/preferences"
},
name: "about"
},

{
path: "/",
name: "balances",
component: wallet("Wallet")
},
{
path: "/wallet/send/:denom?",
name: "send",
props: true,
component: wallet("Send")
},
{
path: "/wallet/transactions",
name: "transactions",
component: wallet("Transactions")
},

{ path: "/404", component: common("404") },
{ path: "*", component: common("404") }
]
}
3 changes: 2 additions & 1 deletion test/unit/helpers/vuex-setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Vuex from "vuex"
import VueRouter from "vue-router"
import { shallow, mount, createLocalVue } from "@vue/test-utils"

import routes from "renderer/routes"
import routesConstructor from "renderer/routes"

const Modules = require("renderer/vuex/modules").default
const Getters = require("renderer/vuex/getters")
Expand All @@ -28,6 +28,7 @@ export default function vuexSetup() {
jest.spyOn(store, "dispatch")
jest.spyOn(store, "commit")

const routes = routesConstructor(store)
let router = new VueRouter({ routes })

return {
Expand Down
26 changes: 26 additions & 0 deletions test/unit/specs/App.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,32 @@ describe("App without analytics", () => {
expect(store.state.node.approvalRequired).toBe("THISISSOMEHASH")
})

it("triggers navigation to About on IPC message", async () => {
jest.resetModules()

let mockPush = jest.fn()
jest.mock(
"vue-router",
() =>
function() {
if (this == null) return
this.push = mockPush
}
)

const { ipcRenderer } = require("electron")
ipcRenderer.on = (type, cb) => {
if (type === "open-about-menu") {
cb(null)
}
}

let app = require("renderer/main.js")
expect(mockPush.mock.calls[0][0]).toBe("/about")

jest.resetModules()
})

it("sends a message to the main thread, that the app has loaded", () => {
const { ipcRenderer } = require("electron")
ipcRenderer.send = jest.fn()
Expand Down
58 changes: 58 additions & 0 deletions test/unit/specs/routes.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/* mocking electron differently in one file apparently didn't work so I had to split the App tests in 2 files */

jest.mock(
"renderer/connectors/node.js",
() => jest.fn(() => require("../helpers/node_mock")) // using jest.fn to be able to spy on the constructor call
)

describe("Routes", () => {
jest.mock("../../../app/src/config", () => ({
google_analytics_uid: "123",
sentry_dsn_public: "456"
}))
jest.mock("raven-js", () => ({
config: dsn => {
return { install: () => {} }
},
captureException: err => console.error(err)
}))
jest.mock("renderer/google-analytics.js", () => uid => {})
jest.mock("electron", () => ({
remote: {
getGlobal: () => ({ mocked: false }),
app: {
getPath: () => {
return "$HOME"
}
}
},
ipcRenderer: {
on: (type, cb) => {},
send: () => {}
}
}))

beforeEach(() => {
Object.defineProperty(window.location, "search", {
writable: true,
value: "?node=localhost&lcd_port=8080"
})
document.body.innerHTML = '<div id="app"></div>'
jest.resetModules()
})

it("activates the about window when navigating to /about", async done => {
const { store, router } = require("renderer/main.js")

router.push(
"/about",
() => {
expect(store.state.config.showAbout).toBe(true)
done()
},
err => {
done.fail(err)
}
)
})
})
2 changes: 0 additions & 2 deletions test/unit/specs/store/user.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ describe("Module: User", () => {
]

beforeEach(() => {
jest.mock("electron", () => ({ ipcRenderer: { send: jest.fn() } }))

let test = instance.shallow()
store = test.store
node = test.node
Expand Down