describe( '#getGuidedTourState()', () => { useI18n(); it( 'should return an empty object if no state is present', () => { const tourState = getGuidedTourState( { ui: { shouldShow: false, guidedTour: false, } } ); expect( tourState ).to.deep.equal( { shouldShow: false, stepConfig: false, nextStepConfig: false } ); } ); it( 'should include the config of the current tour step', () => { const tourState = getGuidedTourState( { ui: { guidedTour: { stepName: 'sidebar', shouldShow: true, tour: 'main', } } } ); const stepConfig = guidedToursConfig.get().sidebar; expect( tourState ).to.deep.equal( Object.assign( {}, tourState, { stepConfig } ) ); } ); } );
describe( 'AccountRecoveryStore', () => { let AccountRecoveryStore, sandbox, dispatchHandler, testConstants; useI18n(); useSandbox( sandy => sandbox = sandy ); beforeEach( () => { testConstants = require( './fixtures/constants' ); sandbox.spy( Dispatcher, 'register' ); sandbox.stub( undocumentedMe.prototype, 'getAccountRecovery' ) .callsArgWithAsync( 0, null, testConstants.DUMMY_ACCOUNT_RECOVERY_RESPONSE ); delete require.cache[ require.resolve( '../account-recovery-store' ) ]; AccountRecoveryStore = require( '../account-recovery-store' ); dispatchHandler = Dispatcher.register.lastCall.args[ 0 ]; } ); afterEach( () => { sandbox.restore(); } ); describe( 'getEmail()', () => { it( 'should call the WP.com REST API on first request', () => { const data = AccountRecoveryStore.getEmail(); expect( undocumentedMe.prototype.getAccountRecovery ).to.have.been.calledOnce; expect( data ).to.eql( testConstants.DUMMY_STORE_EMAIL_OBJECT_LOADING ); } ); it( 'should only call the WP.com REST API only once', done => { AccountRecoveryStore.getEmail(); process.nextTick( () => { AccountRecoveryStore.getEmail(); process.nextTick( () => { expect( undocumentedMe.prototype.getAccountRecovery ).to.have.been.calledOnce; done(); } ); } ); } ); it( 'should return remote data', done => { AccountRecoveryStore.getEmail(); process.nextTick( () => { const data = AccountRecoveryStore.getEmail(); expect( data ).to.eql( testConstants.DUMMY_STORE_EMAIL_OBJECT ); done(); } ); } ); } ); describe( 'getPhone()', () => { it( 'should call the WP.com REST API on first request', () => { const data = AccountRecoveryStore.getPhone(); expect( undocumentedMe.prototype.getAccountRecovery ).to.have.been.calledOnce; expect( data ).to.eql( testConstants.DUMMY_STORE_PHONE_OBJECT_LOADING ); } ); it( 'should only call the WP.com REST API only once', done => { AccountRecoveryStore.getPhone(); process.nextTick( () => { AccountRecoveryStore.getPhone(); process.nextTick( () => { expect( undocumentedMe.prototype.getAccountRecovery ).to.have.been.calledOnce; done(); } ); } ); } ); it( 'should return remote data', done => { AccountRecoveryStore.getPhone(); process.nextTick( () => { var data = AccountRecoveryStore.getPhone(); expect( data ).to.eql( testConstants.DUMMY_STORE_PHONE_OBJECT ); done(); } ); } ); } ); describe( '.dispatchToken', () => { let dispatch; before( () => { dispatch = action => dispatchHandler( { action } ); } ); it( 'should expose dispatch ID', () => { expect( AccountRecoveryStore.dispatchToken ).to.be.a( 'string' ); } ); it( 'should update email on UPDATE_ACCOUNT_RECOVERY_EMAIL', () => { dispatch( testConstants.DISPATCH_UPDATE_ACCOUNT_RECOVERY_EMAIL ); expect( AccountRecoveryStore.getEmail() ).to.have.deep.property( 'data.email', testConstants.DUMMY_EMAIL ); } ); it( 'should update and set notice on RECEIVE_UPDATED_ACCOUNT_RECOVERY_EMAIL', () => { dispatch( testConstants.DISPATCH_RECEIVE_UPDATED_ACCOUNT_RECOVERY_EMAIL ); expect( AccountRecoveryStore.getEmail() ).to.have.deep.property( 'data.email', testConstants.DUMMY_EMAIL ); expect( AccountRecoveryStore.getEmail() ).to.have.property( 'lastNotice' ).that.is.an( 'object' ); } ); it( 'should delete on DELETE_ACCOUNT_RECOVERY_EMAIL', () => { dispatch( testConstants.DISPATCH_DELETE_ACCOUNT_RECOVERY_EMAIL ); expect( AccountRecoveryStore.getEmail() ).to.have.deep.property( 'data.email', null ); } ); it( 'should delete and update notice on RECEIVE_DELETED_ACCOUNT_RECOVERY_EMAIL', () => { dispatch( testConstants.DISPATCH_RECEIVE_DELETED_ACCOUNT_RECOVERY_EMAIL ); expect( AccountRecoveryStore.getEmail() ).to.have.deep.property( 'data.email', null ); expect( AccountRecoveryStore.getEmail() ).to.have.property( 'lastNotice' ).that.is.an( 'object' ); } ); it( 'should dismiss notice on DISMISS_ACCOUNT_RECOVERY_EMAIL_NOTICE', () => { dispatch( testConstants.DISPATCH_RECEIVE_UPDATED_ACCOUNT_RECOVERY_EMAIL ); dispatch( testConstants.DISPATCH_DISMISS_ACCOUNT_RECOVERY_EMAIL_NOTICE ); expect( AccountRecoveryStore.getEmail() ).to.have.property( 'lastNotice' ).that.is.false; } ); } ); } );
describe( 'utils', function() { var flows, utils; useFilesystemMocks( __dirname ); useI18n(); useMockery( ( mockery ) => { mockery.registerMock( 'lib/abtest', { abtest: () => '' } ); flows = require( 'signup/config/flows' ); utils = require( '../utils' ); } ); describe( 'getLocale', function() { it( 'should find the locale anywhere in the params', function() { assert.equal( utils.getLocale( { lang: 'fr' } ), 'fr' ); assert.equal( utils.getLocale( { stepName: 'fr' } ), 'fr' ); assert.equal( utils.getLocale( { flowName: 'fr' } ), 'fr' ); } ); it( 'should return undefined if no locale is present in the params', function() { assert.equal( utils.getLocale( { stepName: 'theme-selection', flowName: 'flow-one' } ), undefined ); } ); } ); describe( 'getStepName', function() { it( 'should find the step name in either the stepName or flowName fragment', function() { assert.equal( utils.getStepName( { stepName: 'user' } ), 'user' ); assert.equal( utils.getStepName( { flowName: 'user' } ), 'user' ); } ); it( 'should return undefined if no step name is found', function() { assert.equal( utils.getStepName( { flowName: 'account' } ), undefined ); } ); } ); describe( 'getFlowName', function() { afterEach( function() { flows.filterFlowName = null; } ); it( 'should find the flow name in the flowName fragment if present', function() { assert.equal( utils.getFlowName( { flowName: 'other' } ), 'other' ); } ); it( 'should return the default flow if the flow is missing', function() { assert.equal( utils.getFlowName( {} ), 'main' ); } ); it( 'should return the result of filterFlowName if it is a function and the flow is missing', function() { flows.filterFlowName = sinon.stub().returns( 'filtered' ); assert.equal( utils.getFlowName( {} ), 'filtered' ); } ); it( 'should return the result of filterFlowName if it is a function and the flow is not valid', function() { flows.filterFlowName = sinon.stub().returns( 'filtered' ); assert.equal( utils.getFlowName( { flowName: 'invalid' } ), 'filtered' ); } ); it( 'should return the result of filterFlowName if it is a function and the requested flow is present', function() { flows.filterFlowName = sinon.stub().returns( 'filtered' ); assert.equal( utils.getFlowName( { flowName: 'other' } ), 'filtered' ); } ); it( 'should return the passed flow if the result of filterFlowName is not valid', function() { flows.filterFlowName = sinon.stub().returns( 'foobar' ); assert.equal( utils.getFlowName( { flowName: 'other' } ), 'other' ); } ); it( 'should call filterFlowName with the default flow if it is a function and the flow is not valid', function() { flows.filterFlowName = sinon.stub().returns( 'filtered' ); utils.getFlowName( { flowName: 'invalid' } ); assert( flows.filterFlowName.calledWith( 'main' ) ); } ); it( 'should call filterFlowName with the requested flow if it is a function and the flow is valid', function() { flows.filterFlowName = sinon.stub().returns( 'filtered' ); utils.getFlowName( { flowName: 'other' } ); assert( flows.filterFlowName.calledWith( 'other' ) ); } ); } ); describe( 'getValidPath', function() { it( 'should redirect to the default if no flow is present', function() { assert.equal( utils.getValidPath( {} ), '/start/user' ); } ); it( 'should redirect to the current flow default if no step is present', function() { assert.equal( utils.getValidPath( { flowName: 'account' } ), '/start/account/user' ); } ); it( 'should redirect to the default flow if the flow is the default', function() { assert.equal( utils.getValidPath( { flowName: 'main' } ), '/start/user' ); } ); it( 'should redirect invalid steps to the default flow if no flow is present', function() { assert.equal( utils.getValidPath( { stepName: 'fr', stepSectionName: 'fr' } ), '/start/user/fr' ); } ); it( 'should preserve a valid locale to the default flow if one is specified', function() { assert.equal( utils.getValidPath( { stepName: 'fr', stepSectionName: 'abc' } ), '/start/user/abc/fr' ); } ); it( 'should redirect invalid steps to the current flow default', function() { assert.equal( utils.getValidPath( { flowName: 'account', stepName: 'fr', stepSectionName: 'fr' } ), '/start/account/user/fr' ); } ); it( 'should preserve a valid locale if one is specified', function() { assert.equal( utils.getValidPath( { flowName: 'account', stepName: 'fr', stepSectionName: 'abc' } ), '/start/account/user/abc/fr' ); } ); it( 'should handle arbitrary step section names', function() { var randomStepSectionName = 'random-step-section-' + Math.random(); assert.equal( utils.getValidPath( { flowName: 'account', stepName: 'user', stepSectionName: randomStepSectionName, lang: 'fr' } ), '/start/account/user/' + randomStepSectionName + '/fr' ); } ); it( 'should handle arbitrary step section names in the default flow', function() { var randomStepSectionName = 'random-step-section-' + Math.random(); assert.equal( utils.getValidPath( { stepName: 'user', stepSectionName: randomStepSectionName, lang: 'fr' } ), '/start/user/' + randomStepSectionName + '/fr' ); } ); } ); describe( 'getValueFromProgressStore', function() { const testStore = [ { stepName: 'empty' }, { stepName: 'site', site: 'calypso' } ]; const config = { stepName: 'site', fieldName: 'site', signupProgressStore: testStore }; it( 'should return the value of the field if it exists', function() { assert.equal( utils.getValueFromProgressStore( config ), 'calypso' ); } ); it( 'should return null if the field is not present', function() { delete testStore[ 1 ].site; assert.equal( utils.getValueFromProgressStore( config ), null ); } ); } ); describe( 'mergeFormWithValue', function() { const config = { fieldName: 'username', fieldValue: 'calypso' }; it( 'should return the form with the field added if the field doesn\'t have a value', function() { const form = { username: {} }; config.form = form; assert.deepEqual( utils.mergeFormWithValue( config ), { username: { value: 'calypso' } } ); } ); it( 'should return the form unchanged if there is already a value in the form', function() { const form = { username: { value: 'wordpress' } }; config.form = form; assert.equal( utils.mergeFormWithValue( config ), form ); } ); } ); } );
describe( '#accept()', function() { let accept; useFakeDom(); useMockery(); useI18n(); before( function() { mockery.registerSubstitute( 'event', 'component-event' ); mockery.registerSubstitute( 'matches-selector', 'component-matches-selector' ); mockery.registerSubstitute( 'query', 'component-query' ); mockery.registerMock( 'component-classes', function() { return { add: noop, toggle: noop, remove: noop } } ); accept = require( '../' ); } ); beforeEach( function() { document.body.innerHTML = ''; } ); it( 'should render a dialog to the document body', function() { var message = 'Are you sure?', dialog; accept( message, function() {} ); dialog = document.querySelector( '.accept-dialog' ); expect( dialog ).to.be.an.instanceof( window.Element ); expect( dialog.textContent ).to.equal( message ); } ); it( 'should trigger the callback with an accepted prompt', function( done ) { accept( 'Are you sure?', function( accepted ) { expect( accepted ).to.be.be.true; done(); } ); document.querySelector( '.button.is-primary' ).click(); } ); it( 'should trigger the callback with a denied prompt', function( done ) { accept( 'Are you sure?', function( accepted ) { expect( accepted ).to.be.be.false; done(); } ); document.querySelector( '.button:not( .is-primary )' ).click(); } ); it( 'should clean up after itself once the prompt is closed', function( done ) { accept( 'Are you sure?', function() { process.nextTick( function() { expect( document.querySelector( '.accept-dialog' ) ).to.be.null; done(); } ); } ); document.querySelector( '.button.is-primary' ).click(); } ); } );
describe( 'index', function() { let React, ReactDom, ReactInjection, DomainList, TestUtils, noticeTypes, component, sandbox; useSandbox( newSandbox => sandbox = newSandbox ); useFakeDom.withContainer(); useMockery( mockery => { require( 'test/helpers/mocks/component-classes' )( mockery ); require( 'test/helpers/mocks/component-tip' )( mockery ); require( 'test/helpers/mocks/data-poller' )( mockery ); mockery.registerMock( 'components/section-nav', EmptyComponent ); } ); useI18n(); before( () => { React = require( 'react' ); ReactDom = require( 'react-dom' ); TestUtils = require( 'react-addons-test-utils' ); noticeTypes = require( '../constants' ); ReactInjection = require( 'react/lib/ReactInjection' ); ReactInjection.Class.injectMixin( require( 'lib/mixins/i18n' ).mixin ); DomainList = require( '../' ).List; } ); const selectedSite = deepFreeze( { slug: 'example.com', ID: 1 } ); const defaultProps = deepFreeze( { domains: { hasLoadedFromServer: true, list: [ { name: 'domain0.com', isPrimary: false }, { name: 'example.com', isPrimary: true } ] }, cart: {}, context: { path: '' }, products: {}, selectedDomainName: 'example.com', selectedSite: selectedSite, sites: { getSelectedSite() { return selectedSite; } }, sitePlans: {} } ); function renderWithProps( props = defaultProps ) { return ReactDom.render( <DomainList { ...props } />, useFakeDom.getContainer() ); } describe( 'regular cases', function() { beforeEach( function() { component = renderWithProps(); } ); afterEach( function() { ReactDom.unmountComponentAtNode( useFakeDom.getContainer() ); } ); it( 'should list two domains', () => { assert.equal( [].slice.call( ReactDom.findDOMNode( component ).querySelectorAll( '.domain-management-list-item' ) ).length, 2 ); } ); } ); describe( 'setting primary domain', () => { describe( 'when not enabled', () => { beforeEach( () => { component = renderWithProps(); } ); afterEach( function() { ReactDom.unmountComponentAtNode( useFakeDom.getContainer() ); } ); it( 'should show "Change Primary Domain" button', () => { assert( ReactDom.findDOMNode( component ).querySelector( '.domain-management-list__change-primary-button' ) ); } ); it( 'should enable upon clicking the button', () => { const button = ReactDom.findDOMNode( component ).querySelector( '.domain-management-list__change-primary-button' ); TestUtils.Simulate.click( button ); assert( component.state.changePrimaryDomainModeEnabled ); } ); } ); describe( 'when enabled', () => { beforeEach( () => { component = renderWithProps(); const button = ReactDom.findDOMNode( component ).querySelector( '.domain-management-list__change-primary-button' ); TestUtils.Simulate.click( button ); } ); afterEach( function() { ReactDom.unmountComponentAtNode( useFakeDom.getContainer() ); } ); it( 'should show the cancel button', () => { assert( ReactDom.findDOMNode( component.refs.cancelChangePrimaryButton ) ); } ); it( 'should disable upon clicking cancel button', () => { const button = ReactDom.findDOMNode( component.refs.cancelChangePrimaryButton ); TestUtils.Simulate.click( button ); assert( ! component.state.changePrimaryDomainModeEnabled ); } ); it( 'should set the primaryDomainIndex correctly', () => { const primaryDomainIndex = 1; // from data above assert.equal( component.state.primaryDomainIndex, primaryDomainIndex ); } ); describe( '#handleUpdatePrimaryDomain', () => { let setPrimaryDomainStub, setPrimaryDomainResolve, setPrimaryDomainReject; beforeEach( () => { setPrimaryDomainStub = sandbox.stub( component, 'setPrimaryDomain' ).returns( new Promise( ( resolve, reject ) => { setPrimaryDomainResolve = resolve; setPrimaryDomainReject = reject; } ) ); } ); it( 'should not call setPrimaryDomain with on trying to set the already primary domain', () => { component.handleUpdatePrimaryDomain( 1, defaultProps.domains.list[ 1 ] ); setPrimaryDomainResolve(); assert( ! component.state.settingPrimaryDomain ); assert( ! component.state.changePrimaryDomainModeEnabled ); assert( ! setPrimaryDomainStub.called ); } ); it( 'should call setPrimaryDomain with a domain name', ( done ) => { component.handleUpdatePrimaryDomain( 0, defaultProps.domains.list[ 0 ] ); assert( component.state.settingPrimaryDomain ); assert( component.state.primaryDomainIndex === 0 ); assert( setPrimaryDomainStub.calledWith( defaultProps.domains.list[ 0 ].name ), '#setPrimaryDomain should be called with the domain name' ); setPrimaryDomainResolve(); setTimeout( () => { assert( ! component.state.settingPrimaryDomain, 'Setting Primary Domain should be false' ); assert( ! component.changePrimaryDomainModeEnabled ); assert.equal( component.state.notice.type, noticeTypes.PRIMARY_DOMAIN_CHANGE_SUCCESS ); assert.equal( component.state.notice.previousDomainName, defaultProps.domains.list[ 1 ].name ); done(); }, 0 ); } ); it( 'should handle errors and revert the optimistic updates', ( done ) => { component.handleUpdatePrimaryDomain( 0, defaultProps.domains.list[ 0 ] ); setPrimaryDomainReject(); setTimeout( () => { assert( ! component.state.settingPrimaryDomain ); assert( component.state.changePrimaryDomainModeEnabled ); assert.equal( component.state.primaryDomainIndex, 1 ); assert.equal( component.state.notice.type, noticeTypes.PRIMARY_DOMAIN_CHANGE_FAIL ); done(); }, 0 ); } ); } ); } ); describe( 'when less than 2 domains', () => { beforeEach( () => { const oneDomain = deepFreeze( { domains: { hasLoadedFromServer: true, list: [ { name: 'example.com', isPrimary: true } ] } } ); const propsWithOneDomain = deepFreeze( Object.assign( {}, defaultProps, oneDomain ) ); component = renderWithProps( propsWithOneDomain ); } ); it( 'should not show "Change Primary Domain" button', () => { const button = ReactDom.findDOMNode( component ).querySelector( '.domain-management-list__change-primary-button' ); assert( button === null ); } ); } ); } ); } );