Last active
July 27, 2018 19:18
Revisions
-
pbojinov revised this gist
Jul 27, 2018 . 1 changed file with 68 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,68 @@ // https://bitbucket.org/atlassian/confluence-react-components/src/master/src/content-body-rest/content-body-rest.js import React, { Component, PropTypes } from 'react'; import { createElement } from '../facades/document'; export default class ContentBodyRest extends Component { constructor() { super(); this._setScriptContainerRef = this._setScriptContainerRef.bind(this); this._setBodyContainerRef = this._setBodyContainerRef.bind(this); } componentDidMount() { this._updateAnchorTargets(); this._loadJSDependencies(); } componentDidUpdate() { this._updateAnchorTargets(); this._loadJSDependencies(); } _updateAnchorTargets() { const anchors = this._bodyContainer.querySelectorAll('a'); for (let i = 0, anchor; anchor = anchors[i]; i++) { anchor.target = '_top'; } } _loadJSDependencies() { const content = this.props.content; content.jsDependencies.forEach(this._appendScriptToContainer, this); } _appendScriptToContainer(uri) { const scriptElement = createElement('script'); scriptElement.async = true; scriptElement.src = uri; this._scriptContainer.appendChild(scriptElement); } _setBodyContainerRef(node) { this._bodyContainer = node; } _setScriptContainerRef(node) { this._scriptContainer = node; } render() { const { body, cssDependencies } = this.props.content; return ( <div id="content" className="page view"> <div dangerouslySetInnerHTML={{ __html: `${body}${cssDependencies}` }} ref={this._setBodyContainerRef} id="main-content" className="wiki-content"></div> <div ref={this._setScriptContainerRef}></div> </div> ); } } ContentBodyRest.displayName = 'ContentBodyRest'; ContentBodyRest.propTypes = { /** * The ID of the content to render. */ contentId: PropTypes.string }; -
pbojinov revised this gist
Jul 27, 2018 . 1 changed file with 129 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,129 @@ import React from 'react'; import sinon, { spy, stub } from 'sinon'; import sinonChai from 'sinon-chai'; import { shallow, render } from 'enzyme'; import chai, { expect } from 'chai'; import chaiEnzyme from 'chai-enzyme'; import proxyquire from 'proxyquire'; chai.use(chaiEnzyme()); chai.use(sinonChai); const WINDOW = '../facades/window'; const UUID = '../util/uuid'; describe('ContentBodyIframe', () => { let mocks; let ContentBodyIframe; beforeEach(() => { mocks = { [UUID]: { default: sinon.stub() }, [WINDOW]: { addEventListener: sinon.stub(), removeEventListener: sinon.stub() } }; ContentBodyIframe = proxyquire('../content-body-iframe', mocks).default; }); describe('render', () => { let wrapper; const uuid = 'foobar!'; const id = '123'; const props = { baseUrl: 'http://www.atlassian.com', content: {id}, onContentLoaded: sinon.spy() }; beforeEach(() => { mocks[UUID].default.returns(uuid); wrapper = shallow(<ContentBodyIframe {...props} />); }); it('Should render a iframe', () => { expect(wrapper).to.have.descendants('iframe'); const iframe = wrapper.find('iframe'); expect(iframe).to.have.prop('src').equal(`${props.baseUrl}/confluence/content-only/viewpage.action?pageId=${id}&iframeId=${uuid}`); expect(iframe).to.have.prop('onLoad').equal(props.onContentLoaded); }); it('if `contextPath` prop not passed it is "/confluence"', () => { expect(wrapper.find('iframe')).to.have.prop('src').equal(`${props.baseUrl}/confluence/content-only/viewpage.action?pageId=${id}&iframeId=${uuid}`); }); it('use passed `contextPath` for iframe', () => { wrapper.setProps({contextPath: '/wiki'}); expect(wrapper.find('iframe')).to.have.prop('src').equal(`${props.baseUrl}/wiki/content-only/viewpage.action?pageId=${id}&iframeId=${uuid}`); wrapper.setProps({contextPath: ''}); expect(wrapper.find('iframe')).to.have.prop('src').equal(`${props.baseUrl}/content-only/viewpage.action?pageId=${id}&iframeId=${uuid}`); }); }); describe('componentDidMount', () => { let wrapper; let instance; let uuid; beforeEach(() => { uuid = 'barfoo'; mocks[UUID].default.returns(uuid); wrapper = shallow(<ContentBodyIframe baseUrl="" content={{}}/>); instance = wrapper.instance(); instance.componentDidMount(); }); it('Should setup a message event listener', () => { expect(mocks[WINDOW].addEventListener).to.have.been.calledWith('message', instance.receiveMessage); }); describe('receiveMessage handler', () => { let receiveMessage; beforeEach(() => { receiveMessage = mocks[WINDOW].addEventListener.getCall(0).args[1]; }); describe(`When iframeId doesn't match the iframeId of the component`, () => { it('Should return undefined', () => { expect(receiveMessage({ data: { iframeId: 'something', height: 1234 } })).to.equal(); }); }); describe('When event iframeId matches the iframeId of the component', () => { it('Should setState with the height in the message', () => { const height = 599; receiveMessage({ data: { iframeId: uuid, height } }); expect(wrapper).to.have.state('height', `${height}px`); }); }); }); describe('componentWillUnmount', () => { beforeEach(() => { instance.componentWillUnmount(); }); it('Should remove the message event listener', () => { expect(mocks[WINDOW].removeEventListener).to.have.been.calledWith('message', instance.receiveMessage); }); }); }); }); -
pbojinov created this gist
Jul 27, 2018 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,85 @@ import React, { Component, PropTypes } from 'react'; import uuid from '../util/uuid'; import { addEventListener, removeEventListener } from '../facades/window'; const DEFAULT_CONTEXT_PATH = '/confluence'; export default class ContentBodyIframe extends Component { constructor() { super(); this.iframeId = uuid(); this.state = { height: '1000px' }; } componentDidMount() { this.receiveMessage = event => { const { iframeId } = event.data; if (!iframeId || iframeId !== this.iframeId) { return; } const { height } = event.data; this.setState({ height: `${height}px` }); }; addEventListener('message', this.receiveMessage); } componentWillUnmount() { removeEventListener('message', this.receiveMessage); } render() { const { content, baseUrl, onContentLoaded } = this.props; let { contextPath } = this.props; const { height } = this.state; if (typeof contextPath === 'undefined') { contextPath = DEFAULT_CONTEXT_PATH; } const contentUrl = `${baseUrl}${contextPath}/content-only/viewpage.action?pageId=${content.id}&iframeId=${this.iframeId}`; return ( <iframe src={contentUrl} border="0" style={{border:0, width: '100%', height}} onLoad={onContentLoaded} /> ); } } ContentBodyIframe.displayName = 'ContentBodyIframe'; ContentBodyIframe.defaultProps = { baseUrl: '' }; ContentBodyIframe.propTypes = { /** * The ID of the content to render. */ contentId: PropTypes.string, /** * Host of confluence instance for the iframe src attribute */ baseUrl: PropTypes.string, /** * Confluence instance context path */ contextPath: PropTypes.string, /** * Callback when iframe finishes loading. */ onContentLoaded: PropTypes.func };