UNPKG

angular-dynamic-locale

Version:

A minimal module that adds the ability to dynamically change the locale

733 lines (682 loc) 25.4 kB
(function () { 'use strict'; // Minimal implementation to mock what was removed from Jasmine 1.x function createAsync(doneFn) { function Job() { this.next = []; } Job.prototype.done = function () { return this.runs(doneFn); }; Job.prototype.runs = function (fn) { var newJob = new Job(); this.next.push(function () { fn(); newJob.start(); }); return newJob; }; Job.prototype.waitsFor = function (fn, error, timeout) { var newJob = new Job(); timeout = timeout || 5000; this.next.push(function () { var counter = 0, intervalId = window.setInterval(function () { if (fn()) { window.clearInterval(intervalId); newJob.start(); } counter += 5; if (counter > timeout) { window.clearInterval(intervalId); throw new Error(error); } }, 5); }); return newJob; }; Job.prototype.start = function () { var i; for (i = 0; i < this.next.length; i += 1) { this.next[i](); } }; return new Job(); } describe('dynamicLocale', function() { beforeEach(module('tmh.dynamicLocale')); beforeEach(module(function(tmhDynamicLocaleProvider) { tmhDynamicLocaleProvider.localeLocationPattern('/base/node_modules/angular-i18n/angular-locale_{{locale}}.js'); })); afterEach(function (done) { inject(function($locale, $timeout, tmhDynamicLocale) { var job = createAsync(done); job .runs(function() { tmhDynamicLocale.set('en-us'); }) .waitsFor(function() { $timeout.flush(50); return $locale.id === 'en-us'; }, 'locale not reverted', 2000) .done(); job.start(); }); }); it('should (eventually) be able to change the locale', function(done) { inject(function($locale, $timeout, tmhDynamicLocale) { var job = createAsync(done); job .runs(function() { tmhDynamicLocale.set('es'); }) .waitsFor(function() { $timeout.flush(50); return $locale.id === 'es'; }, 'locale not updated', 2000) .runs(function() { expect($locale.id).toBe('es'); expect($locale.DATETIME_FORMATS.DAY["0"]).toBe("domingo"); }) .done(); job.start(); }); }); it('should be able to change the locale back-and-forward within one digest', function(done) { inject(function($rootScope, $locale, $timeout, tmhDynamicLocale) { var job = createAsync(done); job .runs(function() { $rootScope.$apply(function() { tmhDynamicLocale.set('es'); tmhDynamicLocale.set('en'); tmhDynamicLocale.set('es'); }); }) .waitsFor(function() { $timeout.flush(50); return $locale.id === 'es'; }, 'locale not updated', 2000) .runs(function() { expect($locale.id).toBe('es'); expect($locale.DATETIME_FORMATS.DAY["0"]).toBe("domingo"); }) .done(); job.start(); }); }); it('should trigger an event when there it changes the locale', function(done) { inject(function($timeout, $locale, tmhDynamicLocale, $rootScope) { var callback = jasmine.createSpy(); var job = createAsync(done); job .runs(function() { $rootScope.$apply(); $rootScope.$on('$localeChangeSuccess', callback); tmhDynamicLocale.set('es'); expect(callback.calls.count()).toBe(0); }) .waitsFor(function() { $timeout.flush(50); return $locale.id === 'es'; }, 'locale not updated', 2000) .runs(function() { expect(callback.calls.count()).toBe(1); expect(callback.calls.argsFor(0)[1]).toEqual('es'); expect(callback.calls.argsFor(0)[2]).toEqual($locale); }) .done(); job.start(); }); }); it('should trigger a failure even when the locale change fail', function(done) { inject(function($timeout, $locale, tmhDynamicLocale, $rootScope) { var job = createAsync(done); var callback = jasmine.createSpy(); job .runs(function() { $rootScope.$apply(); $rootScope.$on('$localeChangeError', callback); tmhDynamicLocale.set('invalidLocale'); expect(callback.calls.count()).toBe(0); }) .waitsFor(function() { $timeout.flush(50); return callback.calls.count() !== 0; }, 'error not generated', 2000) .runs(function() { expect(callback.calls.count()).toBe(1); expect(callback.calls.argsFor(0)[1]).toEqual('invalidLocale'); }) .done(); job.start(); }); }); it('should return a promise that has the new locale', function(done) { inject(function($timeout, $locale, tmhDynamicLocale, $rootScope) { var job = createAsync(done); var callback = jasmine.createSpy(); job .runs(function() { tmhDynamicLocale.set('es').then(callback); expect(callback.calls.count()).toBe(0); }) .waitsFor(function() { $timeout.flush(50); return callback.calls.count() !== 0; }, 'locale not updated', 2000) .runs(function() { expect(callback.calls.argsFor(0)[0].id).toEqual('es'); expect(callback.calls.argsFor(0)[0]).toEqual($locale); tmhDynamicLocale.set('it'); }) .waitsFor(function() { $timeout.flush(50); return $locale.id === 'it'; }, 'locale not updated', 2000) .runs(function() { tmhDynamicLocale.set('es').then(callback); expect(callback.calls.count()).toBe(1); $rootScope.$apply(); expect(callback.calls.count()).toBe(2); expect(callback.calls.argsFor(1)[0].id).toBe('es'); expect(callback.calls.argsFor(1)[0]).toBe($locale); }) .done(); job.start(); }); }); it('should reject the returned promise if it fails to load the locale', function(done) { inject(function($timeout, $locale, tmhDynamicLocale, $rootScope) { var callback = jasmine.createSpy(); var errorCallback = jasmine.createSpy(); var job = createAsync(done); job .runs(function() { tmhDynamicLocale.set('invalidLocale').then(callback, errorCallback); }) .waitsFor(function() { $timeout.flush(50); return errorCallback.calls.count(); }, 'promise not rejected', 2000) .runs(function() { expect(callback.calls.count()).toBe(0); expect(errorCallback.calls.count()).toBe(1); expect(errorCallback.calls.argsFor(0)[0]).toBe('invalidLocale'); expect($locale.id).toBe('en-us'); }) .done(); job.start(); }); }); it('should be possible to retrieve the locale to be', function(done) { inject(function($timeout, $locale, tmhDynamicLocale, $rootScope, $compile) { var job = createAsync(done); job .runs(function() { tmhDynamicLocale.set('es'); expect(tmhDynamicLocale.get()).toBe('es'); }) .waitsFor(function() { $timeout.flush(50); return $locale.id === 'es'; }, 'locale not updated', 2000) .runs(function() { expect(tmhDynamicLocale.get()).toBe('es'); }) .done(); job.start(); }); }); it('should revert the configured locale when the new locale does not exist', function(done) { inject(function($timeout, $locale, tmhDynamicLocale, $rootScope) { var job = createAsync(done); var errorCallback = jasmine.createSpy(); job .runs(function() { tmhDynamicLocale.set('es'); }) .waitsFor(function() { $timeout.flush(50); return $locale.id === 'es'; }, 'locale not updated', 2000) .runs(function() { tmhDynamicLocale.set('invalidLocale').then(undefined, errorCallback); expect(tmhDynamicLocale.get()).toBe('invalidLocale'); }) .waitsFor(function() { $timeout.flush(50); return errorCallback.calls.count(); }, 'promise not rejected', 2000) .runs(function() { expect(tmhDynamicLocale.get()).toBe('es'); }) .done(); job.start(); }); }); it('should change the already formatted numbers in the page', function(done) { inject(function($timeout, $locale, tmhDynamicLocale, $rootScope, $compile) { var job = createAsync(done); var element = null; job .runs(function() { element = $compile('<span>{{val | number}}</span>')($rootScope); $rootScope.val = 1234.5678; $rootScope.$apply(); expect(element.text()).toBe('1,234.568'); tmhDynamicLocale.set('es'); }) .waitsFor(function() { $timeout.flush(50); return $locale.id === 'es'; }, 'locale not updated', 2000) .runs(function() { expect(element.text()).toBe('1.234,568'); }) .done(); job.start(); }); }); it('should keep already loaded locales at tmhDynamicLocaleCache', function(done) { inject(function($timeout, $locale, tmhDynamicLocale, tmhDynamicLocaleCache, $rootScope) { var job = createAsync(done); var callback = jasmine.createSpy(); var esLocale = null; job .runs(function() { expect(tmhDynamicLocaleCache.info().size).toBe(0); tmhDynamicLocale.set('es'); expect(tmhDynamicLocaleCache.info().size).toBe(0); }) .waitsFor(function() { $timeout.flush(50); return $locale.id === 'es'; }, 'locale not updated', 2000) .runs(function() { expect(tmhDynamicLocaleCache.info().size).toBe(1); expect(tmhDynamicLocaleCache.get('es')).toEqual($locale); esLocale = angular.copy($locale); tmhDynamicLocale.set('it'); }) .waitsFor(function() { $timeout.flush(50); return $locale.id === 'it'; }, 'locale not updated', 2000) .runs(function() { expect(tmhDynamicLocaleCache.info().size).toBe(2); expect(tmhDynamicLocaleCache.get('es')).toEqual(esLocale); expect(tmhDynamicLocaleCache.get('it')).toEqual($locale); }) .done(); job.start(); }); }); it('should use the cache when possible', function(done) { inject(function($timeout, $locale, tmhDynamicLocale, tmhDynamicLocaleCache, $rootScope) { var job = createAsync(done); var callback = jasmine.createSpy(); job .runs(function() { tmhDynamicLocale.set('es'); }) .waitsFor(function() { $timeout.flush(50); return $locale.id === 'es'; }, 'locale not updated', 2000) .runs(function() { tmhDynamicLocale.set('it'); }) .waitsFor(function() { $timeout.flush(50); return $locale.id === 'it'; }, 'locale not updated', 2000) .runs(function() { tmhDynamicLocaleCache.get('es').DATETIME_FORMATS.DAY["0"] = "Domingo"; $rootScope.$on('$localeChangeSuccess', callback); tmhDynamicLocale.set('es'); // Changing the locale should be done async even when this is done from the cache expect(callback.calls.count()).toBe(0); expect($locale.id).toBe('it'); $rootScope.$apply(); expect($locale.id).toBe('es'); expect($locale.DATETIME_FORMATS.DAY["0"]).toBe("Domingo"); expect(callback.calls.count()).toBe(1); }) .done(); job.start(); }); }); it('should do a deep copy of the locale elements', function(done) { inject(function($timeout, $locale, tmhDynamicLocale, tmhDynamicLocaleCache, $rootScope) { var job = createAsync(done); job .runs(function() { tmhDynamicLocale.set('es'); }) .waitsFor(function() { $timeout.flush(50); return $locale.id === 'es'; }, 'locale not updated', 2000) .runs(function() { $locale.DATETIME_FORMATS.DAY["0"] = "XXX"; expect($locale.DATETIME_FORMATS.DAY["0"]).not.toBe(tmhDynamicLocaleCache.get('es').DATETIME_FORMATS.DAY["0"]); }) .done(); job.start(); }); }); it('should be able to handle locales with extra elements', function(done) { inject(function($timeout, $locale, tmhDynamicLocale, tmhDynamicLocaleCache, $rootScope) { var job = createAsync(done); var weirdLocale; job .runs(function() { tmhDynamicLocale.set('es'); }) .waitsFor(function() { $timeout.flush(50); return $locale.id === 'es'; }, 'locale not updated', 2000) .runs(function() { weirdLocale = angular.copy($locale); weirdLocale.id = "xx"; weirdLocale.EXTRA_PARAMETER = {foo: "FOO"}; weirdLocale.DATETIME_FORMATS.DAY["7"] = "One More Day"; tmhDynamicLocaleCache.put('xx', angular.copy(weirdLocale)); tmhDynamicLocale.set('xx'); }) .waitsFor(function() { $timeout.flush(50); return $locale.id === 'xx'; }, 'locale not updated', 2000) .runs(function() { expect($locale).toEqual(weirdLocale); expect($locale.EXTRA_PARAMETER).toEqual({foo: "FOO"}); tmhDynamicLocale.set('es'); }) .waitsFor(function() { $timeout.flush(50); return $locale.id === 'es'; }, 'locale not updated', 2000) .runs(function() { expect($locale.EXTRA_PARAMETER).toBeUndefined(); expect($locale.DATETIME_FORMATS.DAY["7"]).toBeUndefined(); expect($locale.DATETIME_FORMATS.DAY.length).toBe(7); }) .done(); job.start(); }); }); describe('having a default locale', function() { beforeEach(module(function(tmhDynamicLocaleProvider) { tmhDynamicLocaleProvider.defaultLocale('it'); })); it('should set the locale to the default locale', function(done) { inject(function($timeout, $locale, $rootScope) { var job = createAsync(done); job .runs(function() { expect($locale.id).toBe('en-us'); $rootScope.$apply(); }) .waitsFor(function() { $timeout.flush(50); return $locale.id === 'it'; }, 'locale not updated', 2000) .runs(function() { expect($locale.id).toBe('it'); }) .done(); job.start(); }); }); }); describe('having a cookie storage', function () { beforeEach(module('ngCookies')); beforeEach(module(function(tmhDynamicLocaleProvider) { tmhDynamicLocaleProvider.useCookieStorage(); })); it('should store the change in $cookieStore', function(done) { inject(function ($timeout, $locale, $cookieStore, tmhDynamicLocale) { $cookieStore.remove('tmhDynamicLocale.locale'); var job = createAsync(done); job .runs(function() { tmhDynamicLocale.set('es'); expect($cookieStore.get('tmhDynamicLocale.locale')).toBe(undefined); }) .waitsFor(function() { $timeout.flush(50); return $locale.id === 'es'; }, 'locale not updated', 2000) .runs(function() { expect($cookieStore.get('tmhDynamicLocale.locale')).toBe('es'); }) .done(); job.start(); }); }); it('should store the change in $cookies', function(done) { inject(function ($timeout, $locale, $cookies, tmhDynamicLocale) { $cookies.remove('tmhDynamicLocale.locale'); var job = createAsync(done); job .runs(function() { tmhDynamicLocale.set('es'); expect($cookies.getObject('tmhDynamicLocale.locale')).toBe(undefined); }) .waitsFor(function() { $timeout.flush(50); return $locale.id === 'es'; }, 'locale not updated', 2000) .runs(function() { expect($cookies.getObject('tmhDynamicLocale.locale')).toBe('es'); }) .done(); job.start(); }); }); describe('reading the locale at initialization', function () { beforeEach(inject(function ($cookieStore, $rootScope) { $cookieStore.put('tmhDynamicLocale.locale', 'it'); $rootScope.$apply(); })); it('should load the locale on initialization', function(done) { inject(function ($timeout, $locale, $rootScope) { var job = createAsync(done); job .runs(function() { expect($locale.id).toBe('en-us'); }) .waitsFor(function() { $timeout.flush(50); return $locale.id === 'it'; }, 'locale not updated', 2000) .runs(function() { expect($locale.id).toBe('it'); }) .done(); job.start(); }); }); }); describe('and having a default language', function () { beforeEach(module(function(tmhDynamicLocaleProvider) { tmhDynamicLocaleProvider.defaultLocale('es'); })); beforeEach(inject(function ($cookieStore, $rootScope) { $cookieStore.put('tmhDynamicLocale.locale', 'it'); $rootScope.$apply(); })); it('should load the locale on initialization', function(done) { inject(function ($timeout, $locale, $rootScope) { var job = createAsync(done); job .runs(function() { expect($locale.id).toBe('en-us'); }) .waitsFor(function() { $timeout.flush(50); return $locale.id === 'it'; }, 'locale not updated', 2000) .runs(function() { expect($locale.id).toBe('it'); }) .done(); job.start(); }); }); }); describe('and changing the name of the storageKey', function () { beforeEach(module(function(tmhDynamicLocaleProvider) { tmhDynamicLocaleProvider.storageKey('customStorageKeyName'); })); it('should change the name of the storageKey', function(done) { inject(function ($timeout, $locale, $cookieStore, tmhDynamicLocale) { $cookieStore.remove('tmhDynamicLocale.locale'); $cookieStore.remove('customStorageKeyName'); var job = createAsync(done); job .runs(function() { tmhDynamicLocale.set('es'); expect($cookieStore.get('customStorageKeyName')).toBe(undefined); expect($cookieStore.get('tmhDynamicLocale.locale')).toBe(undefined); }) .waitsFor(function() { $timeout.flush(50); return $locale.id === 'es'; }, 'locale not updated', 2000) .runs(function() { expect($cookieStore.get('tmhDynamicLocale.locale')).toBe(undefined); expect($cookieStore.get('customStorageKeyName')).toBe('es'); }) .done(); job.start(); }); }); }); }); describe('loading locales using <script>', function () { function countLocales(node, localeId) { var count = 0, scripts = node.getElementsByTagName('script'); for (var i = 0; i < scripts.length; ++i) { count += (scripts[i].src === 'http://localhost:9876/base/node_modules/angular-i18n/angular-locale_' + localeId + '.js' ? 1 : 0); } return count; } it('should load the locales using a <script> tag', function(done) { inject(function ($timeout, tmhDynamicLocale, $document, $locale) { var job = createAsync(done); job .runs(function() { tmhDynamicLocale.set('fr'); expect(countLocales($document[0].body, 'fr')).toBe(1); }) .waitsFor(function() { $timeout.flush(50); return $locale.id === 'fr'; }, 'locale not updated', 2000) .runs(function() { expect(countLocales($document[0].body, 'fr')).toBe(0); }) .done(); job.start(); }); }); it('should load the locales in the custom tag (head) using a <script> tag', function(done) { module(function(tmhDynamicLocaleProvider) { tmhDynamicLocaleProvider.appendScriptTo(document.head); }); inject(function ($timeout, tmhDynamicLocale, $document, $locale) { var job = createAsync(done); job .runs(function() { tmhDynamicLocale.set('fr'); expect(countLocales($document[0].head, 'fr')).toBe(1); }).done(); job.start(); }); }); it('should not load the same locale twice', function(done) { inject(function ($timeout, tmhDynamicLocale, $rootScope, $document, $locale) { var job = createAsync(done); job .runs(function() { tmhDynamicLocale.set('ja'); tmhDynamicLocale.set('ja'); expect(countLocales($document[0].body, 'ja')).toBe(1); }) .waitsFor(function() { $timeout.flush(50); return $locale.id === 'ja'; }, 'locale not updated', 2000) .runs(function() { expect(countLocales($document[0].body, 'ja')).toBe(0); tmhDynamicLocale.set('ja'); expect(countLocales($document[0].body, 'ja')).toBe(0); tmhDynamicLocale.set('et'); }) .waitsFor(function() { $timeout.flush(50); return $locale.id === 'et'; }, 'locale not updated', 2000) .runs(function() { $rootScope.$apply(function () { tmhDynamicLocale.set('ja'); expect(countLocales($document[0].body, 'ja')).toBe(0); }); expect(countLocales($document[0].body, 'ja')).toBe(0); }) .done(); job.start(); }); }); it('should return a promise that is resolved when the script is loaded', function(done) { inject(function ($timeout, tmhDynamicLocale, $document, $locale) { var job = createAsync(done); var callback = jasmine.createSpy(); job .runs(function() { tmhDynamicLocale.set('ko').then(callback); tmhDynamicLocale.set('ko').then(callback); expect(callback).not.toHaveBeenCalled(); }) .waitsFor(function() { $timeout.flush(50); return $locale.id === 'ko'; }, 'locale not updated', 2000) .runs(function() { expect(callback.calls.count()).toBe(2); }) .done(); job.start(); }); }); }); it('should be possible to add local properties to the locale location pattern', function(done) { module(function(tmhDynamicLocaleProvider) { tmhDynamicLocaleProvider.localeLocationPattern('/{{base}}/angular-locale_{{locale}}.js'); tmhDynamicLocaleProvider.addLocalePatternValue('base', 'base/node_modules/angular-i18n'); }); inject(function($locale, $timeout, tmhDynamicLocale) { var job = createAsync(done); job .runs(function() { tmhDynamicLocale.set('es'); }) .waitsFor(function() { $timeout.flush(50); return $locale.id === 'es'; }, 'locale not updated', 2000) .runs(function() { expect($locale.id).toBe('es'); expect($locale.DATETIME_FORMATS.DAY["0"]).toBe("domingo"); }) .done(); job.start(); }); }); }); }());