Example #1
0
	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;
		} );
	} );
} );
Example #3
0
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 );
		} );
	} );
} );
Example #4
0
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();
	} );
} );
Example #5
0
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 );
			} );
		} );
	} );
} );