Skip to content
This repository was archived by the owner on Apr 1, 2020. It is now read-only.

Commit 11a0db1

Browse files
akinshobryphe
authored andcommitted
Feature/auto-prefix browser url if needed (#2016)
* [WIP] prefix browser url * add prefixing of url and associated test * add test for browserview component and snapshots * remove pointless interim assignment * give regex a name for semantic purposes * remove unnecessary lambdas - v. minor but ?possibly cumulative penalty * update tests call navigate in init element move init element to cdm to *try* to move impure fns from render * fix lint error
1 parent 1fdf9b3 commit 11a0db1

File tree

3 files changed

+121
-14
lines changed

3 files changed

+121
-14
lines changed

browser/src/Services/Browser/BrowserView.tsx

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ export interface SneakInfoFromBrowser {
7777

7878
export class BrowserView extends React.PureComponent<IBrowserViewProps, IBrowserViewState> {
7979
private _webviewElement: any
80+
private _elem: HTMLElement
8081
private _disposables: IDisposable[] = []
8182

8283
constructor(props: IBrowserViewProps) {
@@ -135,6 +136,7 @@ export class BrowserView extends React.PureComponent<IBrowserViewProps, IBrowser
135136
})
136137

137138
this._disposables = this._disposables.concat([d1, d2, d3, d4, d5, d6])
139+
this._initializeElement(this._elem)
138140
}
139141

140142
public _triggerSneak(id: string): void {
@@ -156,18 +158,18 @@ export class BrowserView extends React.PureComponent<IBrowserViewProps, IBrowser
156158
return (
157159
<Column key={"test2"}>
158160
<BrowserControlsWrapper>
159-
<BrowserButtonView icon={"chevron-left"} onClick={() => this._goBack()} />
160-
<BrowserButtonView icon={"chevron-right"} onClick={() => this._goForward()} />
161-
<BrowserButtonView icon={"undo"} onClick={() => this._reload()} />
161+
<BrowserButtonView icon={"chevron-left"} onClick={this._goBack} />
162+
<BrowserButtonView icon={"chevron-right"} onClick={this._goForward} />
163+
<BrowserButtonView icon={"undo"} onClick={this._reload} />
162164
<AddressBarView
163165
url={this.state.url}
164166
onAddressChanged={url => this._navigate(url)}
165167
/>
166-
<BrowserButtonView icon={"bug"} onClick={() => this._openDebugger()} />
168+
<BrowserButtonView icon={"bug"} onClick={this._openDebugger} />
167169
</BrowserControlsWrapper>
168170
<BrowserViewWrapper>
169171
<div
170-
ref={elem => this._initializeElement(elem)}
172+
ref={elem => (this._elem = elem)}
171173
style={{
172174
position: "absolute",
173175
top: "0px",
@@ -182,51 +184,62 @@ export class BrowserView extends React.PureComponent<IBrowserViewProps, IBrowser
182184
)
183185
}
184186

185-
private _navigate(url: string): void {
187+
public prefixUrl = (url: string) => {
188+
// Regex Explainer - match at the beginning of the string ^
189+
// brackets to match the selection not partial match like ://
190+
// match http or https, then match ://
191+
const hasValidProtocol = /^(https?:)\/\//i
192+
if (url && !hasValidProtocol.test(url)) {
193+
return `http://${url}`
194+
}
195+
return url
196+
}
197+
198+
private _navigate = (url: string): void => {
186199
if (this._webviewElement) {
187-
this._webviewElement.src = url
200+
this._webviewElement.src = this.prefixUrl(url)
188201

189202
this.setState({
190203
url,
191204
})
192205
}
193206
}
194207

195-
private _goBack(): void {
208+
private _goBack = (): void => {
196209
if (this._webviewElement) {
197210
this._webviewElement.goBack()
198211
}
199212
}
200213

201-
private _goForward(): void {
214+
private _goForward = (): void => {
202215
if (this._webviewElement) {
203216
this._webviewElement.goForward()
204217
}
205218
}
206219

207-
private _openDebugger(): void {
220+
private _openDebugger = (): void => {
208221
if (this._webviewElement) {
209222
this._webviewElement.openDevTools()
210223
}
211224
}
212225

213-
private _reload(): void {
226+
private _reload = (): void => {
214227
if (this._webviewElement) {
215228
this._webviewElement.reload()
216229
}
217230
}
218231

219-
private _getZoomFactor(): number {
232+
private _getZoomFactor = (): number => {
220233
return this.props.configuration.getValue("browser.zoomFactor", 1.0)
221234
}
222235

223-
private _initializeElement(elem: HTMLElement) {
236+
private _initializeElement = (elem: HTMLElement) => {
224237
if (elem && !this._webviewElement) {
225238
const webviewElement = document.createElement("webview")
226239
webviewElement.preload = path.join(__dirname, "lib", "webview_preload", "index.js")
227240
elem.appendChild(webviewElement)
228241
this._webviewElement = webviewElement
229-
this._webviewElement.src = this.props.initialUrl
242+
this._navigate(this.props.initialUrl)
230243

231244
this._webviewElement.addEventListener("dom-ready", () => {
232245
this._webviewElement.setZoomFactor(this._getZoomFactor())

ui-tests/BrowserView.test.tsx

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { shallow } from "enzyme"
2+
import { shallowToJson } from "enzyme-to-json"
3+
import * as React from "react"
4+
5+
import { Event } from "oni-types"
6+
import {
7+
BrowserView,
8+
IBrowserViewProps,
9+
IBrowserViewState,
10+
} from "../browser/src/Services/Browser/BrowserView"
11+
import { Configuration } from "../browser/src/Services/Configuration"
12+
13+
const mockEvent = new Event<void>()
14+
15+
// Using the disable life cycle methods here as the CDM calls sneak which is
16+
// an external dependency I'm not trying to test here
17+
18+
describe("<BrowserView /> Tests", () => {
19+
const component = (
20+
<BrowserView
21+
initialUrl={"test.com"}
22+
configuration={{} as Configuration}
23+
debug={mockEvent}
24+
goBack={mockEvent}
25+
goForward={mockEvent}
26+
reload={mockEvent}
27+
/>
28+
)
29+
it("component to render correctly", () => {
30+
const wrapper = shallow(component, { disableLifecycleMethods: true })
31+
expect(wrapper).toBeDefined()
32+
})
33+
it('Should correctly prefix a url with "https" or "http" if needed', () => {
34+
const wrapper = shallow(component, { disableLifecycleMethods: true })
35+
// can be typed here but the _webviewComponent is expected - TS Error
36+
const instance: any = wrapper.instance()
37+
expect(instance.prefixUrl("apple.com")).toBe("http://apple.com")
38+
})
39+
it('Should NOT prefix a url with "https" or "http" if already present', () => {
40+
const wrapper = shallow(component, { disableLifecycleMethods: true })
41+
const instance: any = wrapper.instance()
42+
// subtle difference here as the function always add https as a prefix not http
43+
expect(instance.prefixUrl("https://www.apple.com")).toBe("https://www.apple.com")
44+
})
45+
46+
it("Should match the recent snapshot - unless an intentional change has occurred ", () => {
47+
const wrapper = shallow(component, { disableLifecycleMethods: true })
48+
expect(shallowToJson(wrapper)).toMatchSnapshot()
49+
})
50+
})
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`<BrowserView /> Tests Should match the recent snapshot - unless an intentional change has occurred 1`] = `
4+
<styled.div
5+
key="test2"
6+
>
7+
<styled.div>
8+
<Component
9+
icon="chevron-left"
10+
onClick={[Function]}
11+
/>
12+
<Component
13+
icon="chevron-right"
14+
onClick={[Function]}
15+
/>
16+
<Component
17+
icon="undo"
18+
onClick={[Function]}
19+
/>
20+
<AddressBarView
21+
onAddressChanged={[Function]}
22+
url="test.com"
23+
/>
24+
<Component
25+
icon="bug"
26+
onClick={[Function]}
27+
/>
28+
</styled.div>
29+
<styled.div>
30+
<div
31+
key="test"
32+
style={
33+
Object {
34+
"bottom": "0px",
35+
"left": "0px",
36+
"position": "absolute",
37+
"right": "0px",
38+
"top": "0px",
39+
}
40+
}
41+
/>
42+
</styled.div>
43+
</styled.div>
44+
`;

0 commit comments

Comments
 (0)