diff --git a/apps/files_sharing/js/share.js b/apps/files_sharing/js/share.js
index db770ad150901dc14a823f50d91fdaf6473edacb..9f47e7858217a99324138c53eaf97f9509286bb9 100644
--- a/apps/files_sharing/js/share.js
+++ b/apps/files_sharing/js/share.js
@@ -13,7 +13,7 @@
 		OCA.Sharing = {};
 	}
 	OCA.Sharing.Util = {
-		initialize: function() {
+		initialize: function(fileActions) {
 			if (!_.isUndefined(OC.Share) && !_.isUndefined(OCA.Files)) {
 				// TODO: make a separate class for this or a hook or jQuery event ?
 				if (OCA.Files.FileList) {
@@ -28,6 +28,9 @@
 								tr.attr('data-reshare-permissions', fileData.permissions);
 							}
 						}
+						if (fileData.recipientsDisplayName) {
+							tr.attr('data-share-recipients', fileData.recipientsDisplayName);
+						}
 						return tr;
 					};
 				}
@@ -72,7 +75,7 @@
 					}
 				});
 
-				OCA.Files.fileActions.register(
+				fileActions.register(
 						'all',
 						'Share',
 						OC.PERMISSION_SHARE,
@@ -109,11 +112,7 @@
 						// is called automatically after this event
 						var userShares = ev.itemShares[OC.Share.SHARE_TYPE_USER] || [];
 						var groupShares = ev.itemShares[OC.Share.SHARE_TYPE_GROUP] || [];
-						var linkShares = ev.itemShares[OC.Share.SHARE_TYPE_LINK] || [];
 						var recipients = _.union(userShares, groupShares);
-						if (linkShares.length > 0) {
-							recipients.unshift(t('files_sharing', 'Public'));
-						}
 						// only update the recipients if they existed before
 						// (some file lists don't have them)
 						if (!_.isUndefined($tr.attr('data-share-recipients'))) {
@@ -131,7 +130,7 @@
 		},
 
 		/**
-		 * Formats a recipient array to be displayed.
+		 * Formats a recipients array to be displayed.
 		 * The first four recipients will be shown and the
 		 * other ones will be shown as "+x" where "x" is the number of
 		 * remaining recipients.
@@ -146,7 +145,9 @@
 			if (!_.isNumber(count)) {
 				count = recipients.length;
 			}
-			text = _.first(recipients, maxRecipients).join(', ');
+			// TODO: use natural sort
+			recipients = _.first(recipients, maxRecipients).sort();
+			text = recipients.join(', ');
 			if (count > maxRecipients) {
 				text += ', +' + (count - maxRecipients);
 			}
@@ -156,6 +157,9 @@
 })();
 
 $(document).ready(function() {
-	OCA.Sharing.Util.initialize();
+	// FIXME: HACK: do not init when running unit tests, need a better way
+	if (!window.TESTING) {
+		OCA.Sharing.Util.initialize(OCA.Files.fileActions);
+	}
 });
 
diff --git a/apps/files_sharing/js/sharedfilelist.js b/apps/files_sharing/js/sharedfilelist.js
index 9cf74abf6703505921a8a9c75fa60eb92128b631..8a6c3169f9ea7a75dea1ee5486bca623d1c03607 100644
--- a/apps/files_sharing/js/sharedfilelist.js
+++ b/apps/files_sharing/js/sharedfilelist.js
@@ -48,9 +48,6 @@
 			if (this._sharedWithUser) {
 				$tr.attr('data-share-owner', fileData.shares[0].ownerDisplayName);
 			}
-			if (fileData.recipientsDisplayName) {
-				$tr.attr('data-share-recipients', fileData.recipientsDisplayName);
-			}
 			return $tr;
 		},
 
@@ -201,11 +198,9 @@
 						data.shares.push(file.share);
 					}
 
-					if (file.share.type === OC.Share.SHARE_TYPE_LINK) {
-						data.hasLinkShare = true;
-					} else if (recipient) {
+					if (recipient) {
 						// limit counterparts for output
-						if (data.recipientsCount < 3) {
+						if (data.recipientsCount < 4) {
 							// only store the first ones, they will be the only ones
 							// displayed
 							data.recipients[recipient] = true;
@@ -222,11 +217,7 @@
 				.each(function(data) {
 					// convert the recipients map to a flat
 					// array of sorted names
-					data.recipients = _.chain(data.recipients).keys().sort().value();
-					if (data.hasLinkShare) {
-						data.recipients.unshift(t('files_sharing', 'Public'));
-						delete data.hasLinkShare;
-					}
+					data.recipients = _.keys(data.recipients);
 					data.recipientsDisplayName = OCA.Sharing.Util.formatRecipients(
 						data.recipients,
 						data.recipientsCount
diff --git a/apps/files_sharing/tests/js/shareSpec.js b/apps/files_sharing/tests/js/shareSpec.js
new file mode 100644
index 0000000000000000000000000000000000000000..604a4bb2bb60d1412d8d9b7dd570885ff85016da
--- /dev/null
+++ b/apps/files_sharing/tests/js/shareSpec.js
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2014 Vincent Petry <pvince81@owncloud.com>
+ *
+ * This file is licensed under the Affero General Public License version 3
+ * or later.
+ *
+ * See the COPYING-README file.
+ *
+ */
+
+describe('OCA.Sharing.Util tests', function() {
+	var oldFileListPrototype;
+	var fileList;
+	var testFiles;
+
+	beforeEach(function() {
+		// back up prototype, as it will be extended by
+		// the sharing code
+		oldFileListPrototype = _.extend({}, OCA.Files.FileList.prototype);
+
+		var $content = $('<div id="content"></div>');
+		$('#testArea').append($content);
+		// dummy file list
+		var $div = $(
+			'<div>' +
+			'<table id="filestable">' +
+			'<thead></thead>' +
+			'<tbody id="fileList"></tbody>' +
+			'</table>' +
+			'</div>');
+		$('#content').append($div);
+
+		var fileActions = new OCA.Files.FileActions();
+		OCA.Sharing.Util.initialize(fileActions);
+		fileList = new OCA.Files.FileList(
+			$div, {
+				fileActions : fileActions
+			}
+		);
+
+		testFiles = [{
+			id: 1,
+			type: 'file',
+			name: 'One.txt',
+			path: '/subdir',
+			mimetype: 'text/plain',
+			size: 12,
+			permissions: 31,
+			etag: 'abc',
+			shareOwner: 'User One',
+			isShareMountPoint: false
+		}];
+
+		OCA.Sharing.sharesLoaded = true;
+		OC.Share.statuses = {
+			1: {link: false, path: '/subdir'}
+		};
+	});
+	afterEach(function() {
+		OCA.Files.FileList.prototype = oldFileListPrototype;
+		delete OCA.Sharing.sharesLoaded;
+		OC.Share.statuses = {};
+	});
+
+	describe('Sharing data in table row', function() {
+		// TODO: test data-permissions, data-share-owner, etc
+	});
+	describe('Share action icon', function() {
+		it('do not shows share text when not shared', function() {
+			var $action;
+			OC.Share.statuses = {};
+			fileList.setFiles([{
+				id: 1,
+				type: 'file',
+				name: 'One.txt',
+				path: '/subdir',
+				mimetype: 'text/plain',
+				size: 12,
+				permissions: 31,
+				etag: 'abc'
+			}]);
+			$action = fileList.$el.find('tbody tr:first .action-share');
+			expect($action.hasClass('permanent')).toEqual(false);
+			expect(OC.basename($action.find('img').attr('src'))).toEqual('share.svg');
+		});
+		it('shows simple share text with share icon', function() {
+			var $action;
+			fileList.setFiles([{
+				id: 1,
+				type: 'file',
+				name: 'One.txt',
+				path: '/subdir',
+				mimetype: 'text/plain',
+				size: 12,
+				permissions: 31,
+				etag: 'abc'
+			}]);
+			$action = fileList.$el.find('tbody tr:first .action-share');
+			expect($action.hasClass('permanent')).toEqual(true);
+			expect($action.find('>span').text()).toEqual('Shared');
+			expect(OC.basename($action.find('img').attr('src'))).toEqual('share.svg');
+		});
+		it('shows simple share text with public icon when shared with link', function() {
+			var $action;
+			OC.Share.statuses = {1: {link: true, path: '/subdir'}};
+			fileList.setFiles([{
+				id: 1,
+				type: 'file',
+				name: 'One.txt',
+				path: '/subdir',
+				mimetype: 'text/plain',
+				size: 12,
+				permissions: 31,
+				etag: 'abc'
+			}]);
+			$action = fileList.$el.find('tbody tr:first .action-share');
+			expect($action.hasClass('permanent')).toEqual(true);
+			expect($action.find('>span').text()).toEqual('Shared');
+			expect(OC.basename($action.find('img').attr('src'))).toEqual('public.svg');
+		});
+		it('shows owner name when owner is available', function() {
+			var $action;
+			fileList.setFiles([{
+				id: 1,
+				type: 'file',
+				name: 'One.txt',
+				path: '/subdir',
+				mimetype: 'text/plain',
+				size: 12,
+				permissions: 31,
+				shareOwner: 'User One',
+				etag: 'abc'
+			}]);
+			$action = fileList.$el.find('tbody tr:first .action-share');
+			expect($action.hasClass('permanent')).toEqual(true);
+			expect($action.find('>span').text()).toEqual('Shared by User One');
+			expect(OC.basename($action.find('img').attr('src'))).toEqual('share.svg');
+		});
+		it('shows recipients when recipients are available', function() {
+			var $action;
+			fileList.setFiles([{
+				id: 1,
+				type: 'file',
+				name: 'One.txt',
+				path: '/subdir',
+				mimetype: 'text/plain',
+				size: 12,
+				permissions: 31,
+				recipientsDisplayName: 'User One, User Two',
+				etag: 'abc'
+			}]);
+			$action = fileList.$el.find('tbody tr:first .action-share');
+			expect($action.hasClass('permanent')).toEqual(true);
+			expect($action.find('>span').text()).toEqual('Shared with User One, User Two');
+			expect(OC.basename($action.find('img').attr('src'))).toEqual('share.svg');
+		});
+	});
+	describe('Share action', function() {
+		// TODO: test file action / dropdown trigger
+		it('updates share icon when shares were changed in dropdown', function() {
+			fileList.setFiles(testFiles);
+			fileList.$el.find('tr:first .action-share').click();
+		});
+	});
+	describe('formatRecipients', function() {
+		it('returns a single recipient when one passed', function() {
+			expect(OCA.Sharing.Util.formatRecipients(['User one']))
+				.toEqual('User one');
+		});
+		it('returns two recipients when two passed', function() {
+			expect(OCA.Sharing.Util.formatRecipients(['User one', 'User two']))
+				.toEqual('User one, User two');
+		});
+		it('returns four recipients with plus when five passed', function() {
+			var recipients = [
+				'User one',
+				'User two',
+				'User three',
+				'User four',
+				'User five'
+			];
+			expect(OCA.Sharing.Util.formatRecipients(recipients))
+				.toEqual('User four, User one, User three, User two, +1');
+		});
+		it('returns four recipients with plus when ten passed', function() {
+			var recipients = [
+				'User one',
+				'User two',
+				'User three',
+				'User four',
+				'User five',
+				'User six',
+				'User seven',
+				'User eight',
+				'User nine',
+				'User ten'
+			];
+			expect(OCA.Sharing.Util.formatRecipients(recipients))
+				.toEqual('User four, User one, User three, User two, +6');
+		});
+		it('returns four recipients with plus when four passed with counter', function() {
+			var recipients = [
+				'User one',
+				'User two',
+				'User three',
+				'User four'
+			];
+			expect(OCA.Sharing.Util.formatRecipients(recipients, 10))
+				.toEqual('User four, User one, User three, User two, +6');
+		});
+	});
+	
+});
diff --git a/core/js/share.js b/core/js/share.js
index d80205317630a008368584f0d6d084bb7ad20709..c4ca63908a997d37754d70d240e9dddac285368f 100644
--- a/core/js/share.js
+++ b/core/js/share.js
@@ -48,7 +48,7 @@ OC.Share={
 			currentDir = fileList.getCurrentDirectory();
 		}
 		for (item in OC.Share.statuses){
-			var image = OC.imagePath('core', 'actions/shared');
+			var image = OC.imagePath('core', 'actions/share');
 			var data = OC.Share.statuses[item];
 			var hasLink = data.link;
 			// Links override shared in terms of icon display
@@ -113,7 +113,7 @@ OC.Share={
 					}
 				} else if (OC.Share.itemShares[index].length > 0) {
 					shares = true;
-					image = OC.imagePath('core', 'actions/shared');
+					image = OC.imagePath('core', 'actions/share');
 				}
 			}
 		});
@@ -165,17 +165,7 @@ OC.Share={
 				image = image || OC.imagePath('core', 'actions/share');
 			}
 			if (recipients) {
-				image = image || OC.imagePath('core', 'actions/shared');
-				if (owner) {
-					message = ' ' + t(
-						'files_sharing',
-						'Shared by {owner} with You, {recipients}',
-						{owner: owner, recipients: recipients}
-					);
-				}
-				else {
-					message = t('core', 'Shared with {recipients}', {recipients: recipients});
-				}
+				message = t('core', 'Shared with {recipients}', {recipients: recipients});
 			}
 			action.html(' <span>'+ message + '</span>').prepend(img);
 		}
diff --git a/tests/karma.config.js b/tests/karma.config.js
index 846e8f7be915993d1e19d53abbc86e62bdeb9672..1f903f58210c21075167bcfb560cc041de18414c 100644
--- a/tests/karma.config.js
+++ b/tests/karma.config.js
@@ -52,7 +52,8 @@ module.exports = function(config) {
 					// only test these files, others are not ready and mess
 					// up with the global namespace/classes/state
 					'apps/files_sharing/js/app.js',
-					'apps/files_sharing/js/sharedfilelist.js'
+					'apps/files_sharing/js/sharedfilelist.js',
+					'apps/files_sharing/js/share.js'
 				],
 				testFiles: ['apps/files_sharing/tests/js/*.js']
 			}];