mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/Echo
synced 2024-09-23 10:22:05 +00:00
Add proper QUnit tests
Change-Id: I7a4abf068a32d9cf65eb464eb036f72f319c54ff
This commit is contained in:
parent
a4296ad768
commit
7b4bb11c2a
|
@ -197,7 +197,8 @@ $wgResourceModules += array(
|
|||
),
|
||||
'dependencies' => array(
|
||||
'oojs',
|
||||
'ext.echo.api'
|
||||
'ext.echo.api', // This is required by the UnreadNotificationCounter
|
||||
'moment',
|
||||
),
|
||||
'messages' => array(
|
||||
'echo-api-failure',
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
this.foreign = true;
|
||||
this.source = null;
|
||||
this.count = config.count || 0;
|
||||
this.modelName = config.modelName || 'xwiki';
|
||||
|
||||
this.list = new mw.echo.dm.NotificationGroupsList();
|
||||
|
||||
|
|
|
@ -56,7 +56,6 @@
|
|||
this.foreign = !!config.foreign;
|
||||
this.bundled = !!config.bundled;
|
||||
this.source = config.source || '';
|
||||
this.modelName = config.modelName || 'local';
|
||||
this.iconType = config.iconType;
|
||||
this.iconURL = config.iconURL;
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
this.name = config.name || 'local';
|
||||
this.source = config.source || 'local';
|
||||
this.sourceURL = config.sourceURL;
|
||||
this.sourceURL = config.sourceURL || '';
|
||||
this.title = config.title || '';
|
||||
this.fallbackTimestamp = config.timestamp || 0;
|
||||
|
||||
|
@ -68,7 +68,7 @@
|
|||
|
||||
/**
|
||||
* @event update
|
||||
* @param {mw.echo.dm.NotificationItem} items Current items in the list
|
||||
* @param {mw.echo.dm.NotificationItem[]} items Current items in the list
|
||||
*
|
||||
* The list has been updated
|
||||
*/
|
||||
|
@ -181,15 +181,6 @@
|
|||
return this.source;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the name associated with this list.
|
||||
*
|
||||
* @return {string} List name
|
||||
*/
|
||||
mw.echo.dm.NotificationsList.prototype.getName = function () {
|
||||
return this.name;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the source article url associated with this list.
|
||||
*
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
OO.EventEmitter.call( this );
|
||||
|
||||
this.pagesContinue = [];
|
||||
this.itemsPerPage = this.itemsPerPage || 25;
|
||||
this.itemsPerPage = config.itemsPerPage || 25;
|
||||
this.currentPageItemCount = config.currentPageItemCount || this.itemsPerPage;
|
||||
|
||||
// Set initial page
|
||||
|
@ -132,7 +132,7 @@
|
|||
* @return {string} Previous page continue value
|
||||
*/
|
||||
mw.echo.dm.PaginationModel.prototype.getPrevPageContinue = function () {
|
||||
return this.pagesContinue[ this.currPageIndex - 1 ];
|
||||
return this.pagesContinue[ this.currPageIndex - 1 ] || '';
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -141,7 +141,7 @@
|
|||
* @return {string} Current page continue value
|
||||
*/
|
||||
mw.echo.dm.PaginationModel.prototype.getCurrPageContinue = function () {
|
||||
return this.pagesContinue[ this.currPageIndex ];
|
||||
return this.pagesContinue[ this.currPageIndex ] || '';
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -150,7 +150,7 @@
|
|||
* @return {string} Next page continue value
|
||||
*/
|
||||
mw.echo.dm.PaginationModel.prototype.getNextPageContinue = function () {
|
||||
return this.pagesContinue[ this.currPageIndex + 1 ];
|
||||
return this.pagesContinue[ this.currPageIndex + 1 ] || '';
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
119
tests/qunit/model/test_mw.echo.dm.BundleNotificationItem.js
Normal file
119
tests/qunit/model/test_mw.echo.dm.BundleNotificationItem.js
Normal file
|
@ -0,0 +1,119 @@
|
|||
( function ( mw ) {
|
||||
QUnit.module( 'ext.echo.dm - mw.echo.dm.BundleNotificationItem' );
|
||||
|
||||
QUnit.test( 'Constructing the model', function ( assert ) {
|
||||
var bundledItems = [
|
||||
new mw.echo.dm.NotificationItem( 0, { read: false, seen: false, timestamp: '201601010000' } ),
|
||||
new mw.echo.dm.NotificationItem( 1, { read: false, seen: false, timestamp: '201601010100' } ),
|
||||
new mw.echo.dm.NotificationItem( 2, { read: false, seen: true, timestamp: '201601010200' } ),
|
||||
new mw.echo.dm.NotificationItem( 3, { read: false, seen: true, timestamp: '201601010300' } ),
|
||||
new mw.echo.dm.NotificationItem( 4, { read: false, seen: true, timestamp: '201601010400' } )
|
||||
],
|
||||
bundle = new mw.echo.dm.BundleNotificationItem(
|
||||
100,
|
||||
bundledItems,
|
||||
{
|
||||
modelName: 'foo'
|
||||
}
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
bundle.getCount(),
|
||||
5,
|
||||
'Bundled items added to internal list'
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
bundle.getName(),
|
||||
'foo',
|
||||
'Bundle name stored'
|
||||
);
|
||||
|
||||
assert.deepEqual(
|
||||
bundle.getAllIds(),
|
||||
[ 4, 3, 2, 1, 0 ],
|
||||
'All ids present'
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
bundle.isRead(),
|
||||
false,
|
||||
'Bundle with all unread items is unread'
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
bundle.hasUnseen(),
|
||||
true,
|
||||
'Bundle has unseen items'
|
||||
);
|
||||
|
||||
assert.deepEqual(
|
||||
( function () {
|
||||
var findItems = bundle.findByIds( [ 1, 4 ] );
|
||||
return findItems.map( function ( item ) {
|
||||
return item.getId();
|
||||
} );
|
||||
} )(),
|
||||
[ 4, 1 ],
|
||||
'findByIds fetches correct items in the default sorting order'
|
||||
);
|
||||
} );
|
||||
|
||||
QUnit.test( 'Managing a list of items', function ( assert ) {
|
||||
var i,
|
||||
bundledItems = [
|
||||
new mw.echo.dm.NotificationItem( 0, { read: false, seen: false, timestamp: '201601010000' } ),
|
||||
new mw.echo.dm.NotificationItem( 1, { read: false, seen: false, timestamp: '201601010100' } ),
|
||||
new mw.echo.dm.NotificationItem( 2, { read: false, seen: true, timestamp: '201601010200' } ),
|
||||
new mw.echo.dm.NotificationItem( 3, { read: false, seen: true, timestamp: '201601010300' } ),
|
||||
new mw.echo.dm.NotificationItem( 4, { read: false, seen: true, timestamp: '201601010400' } )
|
||||
],
|
||||
bundle = new mw.echo.dm.BundleNotificationItem(
|
||||
100,
|
||||
bundledItems,
|
||||
{
|
||||
name: 'foo'
|
||||
}
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
bundle.hasUnseen(),
|
||||
true,
|
||||
'Bundle has unseen'
|
||||
);
|
||||
|
||||
// Mark all items as seen
|
||||
for ( i = 0; i < bundledItems.length; i++ ) {
|
||||
bundledItems[ i ].toggleSeen( true );
|
||||
}
|
||||
|
||||
assert.equal(
|
||||
bundle.hasUnseen(),
|
||||
false,
|
||||
'Bundle does not have unseen after all items marked as seen'
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
bundle.isRead(),
|
||||
false,
|
||||
'Bundle is unread'
|
||||
);
|
||||
// Mark one item as read
|
||||
bundledItems[ 0 ].toggleRead( true );
|
||||
assert.equal(
|
||||
bundle.isRead(),
|
||||
false,
|
||||
'Bundle is still unread if it has some unread items'
|
||||
);
|
||||
|
||||
// Mark all items as read
|
||||
for ( i = 0; i < bundledItems.length; i++ ) {
|
||||
bundledItems[ i ].toggleRead( true );
|
||||
}
|
||||
assert.equal(
|
||||
bundle.isRead(),
|
||||
true,
|
||||
'Bundle is marked as read if all items are read'
|
||||
);
|
||||
} );
|
||||
} )( mediaWiki );
|
311
tests/qunit/model/test_mw.echo.dm.CrossWikiNotificationItem.js
Normal file
311
tests/qunit/model/test_mw.echo.dm.CrossWikiNotificationItem.js
Normal file
|
@ -0,0 +1,311 @@
|
|||
( function ( mw, $ ) {
|
||||
var defaults = {
|
||||
getModelName: 'xwiki',
|
||||
getSourceNames: [],
|
||||
getCount: 0,
|
||||
hasUnseen: false,
|
||||
getItems: [],
|
||||
isEmpty: true
|
||||
};
|
||||
|
||||
QUnit.module( 'ext.echo.dm - mw.echo.dm.CrossWikiNotificationItem' );
|
||||
|
||||
QUnit.test( 'Constructing the model', function ( assert ) {
|
||||
var i, method, model,
|
||||
cases = [
|
||||
{
|
||||
params: {
|
||||
id: -1,
|
||||
config: {}
|
||||
},
|
||||
expected: defaults,
|
||||
msg: 'Default values'
|
||||
},
|
||||
{
|
||||
params: {
|
||||
id: -1,
|
||||
config: { modelName: 'foo' }
|
||||
},
|
||||
expected: $.extend( true, {}, defaults, {
|
||||
getModelName: 'foo'
|
||||
} ),
|
||||
msg: 'Overriding model name'
|
||||
},
|
||||
{
|
||||
params: {
|
||||
id: -1,
|
||||
config: { count: 10 }
|
||||
},
|
||||
expected: $.extend( true, {}, defaults, {
|
||||
getCount: 10
|
||||
} ),
|
||||
msg: 'Overriding model count'
|
||||
}
|
||||
];
|
||||
|
||||
for ( i = 0; i < cases.length; i++ ) {
|
||||
model = new mw.echo.dm.CrossWikiNotificationItem(
|
||||
cases[ i ].params.id,
|
||||
cases[ i ].params.config
|
||||
);
|
||||
|
||||
for ( method in defaults ) {
|
||||
assert.deepEqual(
|
||||
// Method
|
||||
model[ method ](),
|
||||
// Expected value
|
||||
cases[ i ].expected[ method ],
|
||||
cases[ i ].msg + ' (' + method + ')'
|
||||
);
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
QUnit.test( 'Managing notification lists', function ( assert ) {
|
||||
var i, j,
|
||||
model = new mw.echo.dm.CrossWikiNotificationItem( 1 ),
|
||||
groupDefinitions = [
|
||||
{
|
||||
name: 'foo',
|
||||
sourceData: {
|
||||
title: 'Foo Wiki',
|
||||
base: 'http://foo.wiki.sample/$1'
|
||||
},
|
||||
items: [
|
||||
new mw.echo.dm.NotificationItem( 0, { source: 'foo', read: false, seen: false, timestamp: '201601010100' } ),
|
||||
new mw.echo.dm.NotificationItem( 1, { source: 'foo', read: false, seen: false, timestamp: '201601010200' } ),
|
||||
new mw.echo.dm.NotificationItem( 2, { source: 'foo', read: false, seen: false, timestamp: '201601010300' } )
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'bar',
|
||||
sourceData: {
|
||||
title: 'Bar Wiki',
|
||||
base: 'http://bar.wiki.sample/$1'
|
||||
},
|
||||
items: [
|
||||
new mw.echo.dm.NotificationItem( 3, { source: 'bar', read: false, seen: false, timestamp: '201601020000' } ),
|
||||
new mw.echo.dm.NotificationItem( 4, { source: 'bar', read: false, seen: false, timestamp: '201601020100' } ),
|
||||
new mw.echo.dm.NotificationItem( 5, { source: 'bar', read: false, seen: false, timestamp: '201601020200' } ),
|
||||
new mw.echo.dm.NotificationItem( 6, { source: 'bar', read: false, seen: false, timestamp: '201601020300' } )
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'baz',
|
||||
sourceData: {
|
||||
title: 'Baz Wiki',
|
||||
base: 'http://baz.wiki.sample/$1'
|
||||
},
|
||||
items: [
|
||||
new mw.echo.dm.NotificationItem( 7, { source: 'baz', timestamp: '201601050100' } )
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
// Add groups to model
|
||||
for ( i = 0; i < groupDefinitions.length; i++ ) {
|
||||
model.getList().addGroup(
|
||||
groupDefinitions[ i ].name,
|
||||
groupDefinitions[ i ].sourceData,
|
||||
groupDefinitions[ i ].items
|
||||
);
|
||||
}
|
||||
|
||||
assert.deepEqual(
|
||||
model.getSourceNames(),
|
||||
[ 'baz', 'bar', 'foo' ],
|
||||
'Model source names exist in order'
|
||||
);
|
||||
assert.equal(
|
||||
model.hasUnseen(),
|
||||
true,
|
||||
'hasUnseen is true if there are unseen items in any group'
|
||||
);
|
||||
|
||||
// Mark all items as seen except one
|
||||
for ( i = 0; i < groupDefinitions.length; i++ ) {
|
||||
for ( j = 0; j < groupDefinitions[ i ].items.length; j++ ) {
|
||||
groupDefinitions[ i ].items[ j ].toggleSeen( true );
|
||||
}
|
||||
}
|
||||
groupDefinitions[ 0 ].items[ 0 ].toggleSeen( false );
|
||||
assert.equal(
|
||||
model.hasUnseen(),
|
||||
true,
|
||||
'hasUnseen is true even if only one item in one group is unseen'
|
||||
);
|
||||
|
||||
groupDefinitions[ 0 ].items[ 0 ].toggleSeen( true );
|
||||
assert.equal(
|
||||
model.hasUnseen(),
|
||||
false,
|
||||
'hasUnseen is false if there are no unseen items in any of the groups'
|
||||
);
|
||||
|
||||
// Discard group
|
||||
model.getList().removeGroup( 'foo' );
|
||||
assert.deepEqual(
|
||||
model.getSourceNames(),
|
||||
[ 'baz', 'bar' ],
|
||||
'Group discarded successfully'
|
||||
);
|
||||
} );
|
||||
|
||||
QUnit.test( 'Update seen state', function ( assert ) {
|
||||
var i, numUnseenItems, numAllItems,
|
||||
model = new mw.echo.dm.CrossWikiNotificationItem( 1 ),
|
||||
groupDefinitions = [
|
||||
{
|
||||
name: 'foo',
|
||||
sourceData: {
|
||||
title: 'Foo Wiki',
|
||||
base: 'http://foo.wiki.sample/$1'
|
||||
},
|
||||
items: [
|
||||
new mw.echo.dm.NotificationItem( 0, { source: 'foo', read: false, seen: false, timestamp: '201601010100' } ),
|
||||
new mw.echo.dm.NotificationItem( 1, { source: 'foo', read: false, seen: false, timestamp: '201601010200' } ),
|
||||
new mw.echo.dm.NotificationItem( 2, { source: 'foo', read: false, seen: false, timestamp: '201601010300' } )
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'bar',
|
||||
sourceData: {
|
||||
title: 'Bar Wiki',
|
||||
base: 'http://bar.wiki.sample/$1'
|
||||
},
|
||||
items: [
|
||||
new mw.echo.dm.NotificationItem( 3, { source: 'bar', read: false, seen: false, timestamp: '201601020000' } ),
|
||||
new mw.echo.dm.NotificationItem( 4, { source: 'bar', read: false, seen: false, timestamp: '201601020100' } ),
|
||||
new mw.echo.dm.NotificationItem( 5, { source: 'bar', read: false, seen: false, timestamp: '201601020200' } ),
|
||||
new mw.echo.dm.NotificationItem( 6, { source: 'bar', read: false, seen: false, timestamp: '201601020300' } )
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'baz',
|
||||
sourceData: {
|
||||
title: 'Baz Wiki',
|
||||
base: 'http://baz.wiki.sample/$1'
|
||||
},
|
||||
items: [
|
||||
new mw.echo.dm.NotificationItem( 7, { source: 'baz', timestamp: '201601050100' } )
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
// Count all actual items
|
||||
numAllItems = groupDefinitions.reduce( function ( prev, curr ) {
|
||||
return prev + curr.items.length;
|
||||
}, 0 );
|
||||
|
||||
// Add groups to model
|
||||
for ( i = 0; i < groupDefinitions.length; i++ ) {
|
||||
model.getList().addGroup(
|
||||
groupDefinitions[ i ].name,
|
||||
groupDefinitions[ i ].sourceData,
|
||||
groupDefinitions[ i ].items
|
||||
);
|
||||
}
|
||||
|
||||
numUnseenItems = model.getItems().filter( function ( item ) {
|
||||
return !item.isSeen();
|
||||
} ).length;
|
||||
assert.equal(
|
||||
numUnseenItems,
|
||||
numAllItems,
|
||||
'Starting state: all items are unseen'
|
||||
);
|
||||
|
||||
// Update seen time to be bigger than 'foo' but smaller than the other groups
|
||||
model.updateSeenState( '201601010400' );
|
||||
|
||||
numUnseenItems = model.getItems().filter( function ( item ) {
|
||||
return !item.isSeen();
|
||||
} ).length;
|
||||
assert.equal(
|
||||
numUnseenItems,
|
||||
numAllItems - groupDefinitions[ 0 ].items.length,
|
||||
'Only some items are seen'
|
||||
);
|
||||
|
||||
// Update seen time to be bigger than all
|
||||
model.updateSeenState( '201701010000' );
|
||||
|
||||
numUnseenItems = model.getItems().filter( function ( item ) {
|
||||
return !item.isSeen();
|
||||
} ).length;
|
||||
assert.equal(
|
||||
numUnseenItems,
|
||||
0,
|
||||
'All items are seen'
|
||||
);
|
||||
} );
|
||||
|
||||
QUnit.test( 'Emit discard event', function ( assert ) {
|
||||
var i,
|
||||
results = [],
|
||||
model = new mw.echo.dm.CrossWikiNotificationItem( -1 ),
|
||||
groupDefinitions = [
|
||||
{
|
||||
name: 'foo',
|
||||
sourceData: {
|
||||
title: 'Foo Wiki',
|
||||
base: 'http://foo.wiki.sample/$1'
|
||||
},
|
||||
items: [
|
||||
new mw.echo.dm.NotificationItem( 0, { source: 'foo', read: false, seen: false, timestamp: '201601010100' } ),
|
||||
new mw.echo.dm.NotificationItem( 1, { source: 'foo', read: false, seen: false, timestamp: '201601010200' } ),
|
||||
new mw.echo.dm.NotificationItem( 2, { source: 'foo', read: false, seen: false, timestamp: '201601010300' } )
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'bar',
|
||||
sourceData: {
|
||||
title: 'Bar Wiki',
|
||||
base: 'http://bar.wiki.sample/$1'
|
||||
},
|
||||
items: [
|
||||
new mw.echo.dm.NotificationItem( 3, { source: 'bar', read: false, seen: false, timestamp: '201601020000' } ),
|
||||
new mw.echo.dm.NotificationItem( 4, { source: 'bar', read: false, seen: false, timestamp: '201601020100' } ),
|
||||
new mw.echo.dm.NotificationItem( 5, { source: 'bar', read: false, seen: false, timestamp: '201601020200' } ),
|
||||
new mw.echo.dm.NotificationItem( 6, { source: 'bar', read: false, seen: false, timestamp: '201601020300' } )
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'baz',
|
||||
sourceData: {
|
||||
title: 'Baz Wiki',
|
||||
base: 'http://baz.wiki.sample/$1'
|
||||
},
|
||||
items: [
|
||||
new mw.echo.dm.NotificationItem( 7, { source: 'baz', timestamp: '201601050100' } )
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
// Add groups to model
|
||||
for ( i = 0; i < groupDefinitions.length; i++ ) {
|
||||
model.getList().addGroup(
|
||||
groupDefinitions[ i ].name,
|
||||
groupDefinitions[ i ].sourceData,
|
||||
groupDefinitions[ i ].items
|
||||
);
|
||||
}
|
||||
|
||||
// Listen to event
|
||||
model.on( 'discard', function ( name ) {
|
||||
results.push( name );
|
||||
} );
|
||||
|
||||
// Trigger
|
||||
model.getList().removeGroup( 'foo' ); // [ 'foo' ]
|
||||
// Empty a list
|
||||
model.getList().getGroupByName( 'baz' ).discardItems( groupDefinitions[ 2 ].items ); // [ 'foo', 'baz' ]
|
||||
|
||||
assert.deepEqual(
|
||||
results,
|
||||
[ 'foo', 'baz' ],
|
||||
'Discard event emitted'
|
||||
);
|
||||
} );
|
||||
|
||||
} )( mediaWiki, jQuery );
|
110
tests/qunit/model/test_mw.echo.dm.FiltersModel.js
Normal file
110
tests/qunit/model/test_mw.echo.dm.FiltersModel.js
Normal file
|
@ -0,0 +1,110 @@
|
|||
( function ( mw, $ ) {
|
||||
var defaultValues = {
|
||||
getReadState: 'all'
|
||||
};
|
||||
|
||||
QUnit.module( 'ext.echo.dm - mw.echo.dm.FiltersModel' );
|
||||
|
||||
QUnit.test( 'Constructing the model', function ( assert ) {
|
||||
var i, model, method,
|
||||
cases = [
|
||||
{
|
||||
msg: 'Empty config',
|
||||
config: {},
|
||||
expected: defaultValues
|
||||
},
|
||||
{
|
||||
msg: 'Readstate: unread',
|
||||
config: {
|
||||
readState: 'unread'
|
||||
},
|
||||
expected: $.extend( true, {}, defaultValues, {
|
||||
getReadState: 'unread'
|
||||
} )
|
||||
},
|
||||
{
|
||||
msg: 'Readstate: read',
|
||||
config: {
|
||||
readState: 'read'
|
||||
},
|
||||
expected: $.extend( true, {}, defaultValues, {
|
||||
getReadState: 'read'
|
||||
} )
|
||||
}
|
||||
];
|
||||
|
||||
for ( i = 0; i < cases.length; i++ ) {
|
||||
model = new mw.echo.dm.FiltersModel( cases[ i ].config );
|
||||
|
||||
for ( method in cases[ i ].expected ) {
|
||||
assert.deepEqual(
|
||||
// Run the method
|
||||
model[ method ](),
|
||||
// Expected value
|
||||
cases[ i ].expected[ method ],
|
||||
// Message
|
||||
cases[ i ].msg + ' (' + method + ')'
|
||||
);
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
QUnit.test( 'Changing filters', function ( assert ) {
|
||||
var model = new mw.echo.dm.FiltersModel();
|
||||
|
||||
assert.equal(
|
||||
model.getReadState(),
|
||||
'all',
|
||||
'Initial value: all'
|
||||
);
|
||||
|
||||
model.setReadState( 'unread' );
|
||||
assert.equal(
|
||||
model.getReadState(),
|
||||
'unread',
|
||||
'Changing state (unread)'
|
||||
);
|
||||
|
||||
model.setReadState( 'read' );
|
||||
assert.equal(
|
||||
model.getReadState(),
|
||||
'read',
|
||||
'Changing state (read)'
|
||||
);
|
||||
|
||||
model.setReadState( 'foo' );
|
||||
assert.equal(
|
||||
model.getReadState(),
|
||||
'read',
|
||||
'Ignoring invalid state (foo)'
|
||||
);
|
||||
} );
|
||||
|
||||
QUnit.test( 'Emitting update event', function ( assert ) {
|
||||
var results = [],
|
||||
model = new mw.echo.dm.FiltersModel();
|
||||
|
||||
// Listen to update event
|
||||
model.on( 'update', function () {
|
||||
results.push( model.getReadState() );
|
||||
} );
|
||||
|
||||
// Trigger events
|
||||
model.setReadState( 'read' ); // [ 'read' ]
|
||||
model.setReadState( 'unread' ); // [ 'read', 'unread' ]
|
||||
model.setReadState( 'unread' ); // (no change, no event) [ 'read', 'unread' ]
|
||||
model.setReadState( 'all' ); // [ 'read', 'unread', 'all' ]
|
||||
model.setReadState( 'foo' ); // (invalid value, no event) [ 'read', 'unread', 'all' ]
|
||||
model.setReadState( 'unread' ); // [ 'read', 'unread', 'all', 'unread' ]
|
||||
|
||||
assert.deepEqual(
|
||||
// Actual
|
||||
results,
|
||||
// Expected:
|
||||
[ 'read', 'unread', 'all', 'unread' ],
|
||||
// Message
|
||||
'Update events emitted'
|
||||
);
|
||||
} );
|
||||
|
||||
} )( mediaWiki, jQuery );
|
156
tests/qunit/model/test_mw.echo.dm.NotificationGroupsList.js
Normal file
156
tests/qunit/model/test_mw.echo.dm.NotificationGroupsList.js
Normal file
|
@ -0,0 +1,156 @@
|
|||
( function ( mw ) {
|
||||
QUnit.module( 'ext.echo.dm - mw.echo.dm.NotificationGroupsList' );
|
||||
|
||||
QUnit.test( 'Constructing the model', function ( assert ) {
|
||||
var model = new mw.echo.dm.NotificationGroupsList();
|
||||
|
||||
assert.equal(
|
||||
model.getTimestamp(),
|
||||
0,
|
||||
'Empty group has timestamp 0'
|
||||
);
|
||||
} );
|
||||
|
||||
QUnit.test( 'Managing lists', function ( assert ) {
|
||||
var i, group,
|
||||
model = new mw.echo.dm.NotificationGroupsList(),
|
||||
groupDefinitions = [
|
||||
{
|
||||
name: 'foo',
|
||||
sourceData: {
|
||||
title: 'Foo Wiki',
|
||||
base: 'http://foo.wiki.sample/$1'
|
||||
},
|
||||
items: [
|
||||
new mw.echo.dm.NotificationItem( 0 ),
|
||||
new mw.echo.dm.NotificationItem( 1 ),
|
||||
new mw.echo.dm.NotificationItem( 2 )
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'bar',
|
||||
sourceData: {
|
||||
title: 'Bar Wiki',
|
||||
base: 'http://bar.wiki.sample/$1'
|
||||
},
|
||||
items: [
|
||||
new mw.echo.dm.NotificationItem( 3 ),
|
||||
new mw.echo.dm.NotificationItem( 4 ),
|
||||
new mw.echo.dm.NotificationItem( 5 ),
|
||||
new mw.echo.dm.NotificationItem( 6 )
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'baz',
|
||||
sourceData: {
|
||||
title: 'Baz Wiki',
|
||||
base: 'http://baz.wiki.sample/$1'
|
||||
},
|
||||
items: [
|
||||
new mw.echo.dm.NotificationItem( 7 )
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
for ( i = 0; i < groupDefinitions.length; i++ ) {
|
||||
model.addGroup(
|
||||
groupDefinitions[ i ].name,
|
||||
groupDefinitions[ i ].sourceData,
|
||||
groupDefinitions[ i ].items
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
model.getItemCount(),
|
||||
i + 1,
|
||||
'Group number increases after addGroup ("' + groupDefinitions[ i ].name + '")'
|
||||
);
|
||||
|
||||
group = model.getGroupByName( groupDefinitions[ i ].name );
|
||||
assert.equal(
|
||||
group.getName(),
|
||||
groupDefinitions[ i ].name,
|
||||
'Group exists after addGroup ("' + groupDefinitions[ i ].name + '")'
|
||||
);
|
||||
}
|
||||
|
||||
// Remove group
|
||||
model.removeGroup( groupDefinitions[ 0 ].name );
|
||||
|
||||
assert.equal(
|
||||
model.getItemCount(),
|
||||
groupDefinitions.length - 1,
|
||||
'Group number decreased after removeGroup'
|
||||
);
|
||||
assert.equal(
|
||||
model.getGroupByName( groupDefinitions[ 0 ] ),
|
||||
null,
|
||||
'Removed group is no longer in the list'
|
||||
);
|
||||
|
||||
// Removing the last item from a group should remove the group
|
||||
group = model.getGroupByName( 'baz' );
|
||||
group.discardItems( groupDefinitions[ 2 ].items );
|
||||
assert.equal(
|
||||
model.getGroupByName( 'baz' ),
|
||||
null,
|
||||
'Empty group is no longer in the list'
|
||||
);
|
||||
} );
|
||||
|
||||
QUnit.test( 'Emitting discard event', function ( assert ) {
|
||||
var group,
|
||||
results = [],
|
||||
model = new mw.echo.dm.NotificationGroupsList(),
|
||||
groups = {
|
||||
first: [
|
||||
new mw.echo.dm.NotificationItem( 0 ),
|
||||
new mw.echo.dm.NotificationItem( 1 ),
|
||||
new mw.echo.dm.NotificationItem( 2 )
|
||||
],
|
||||
second: [
|
||||
new mw.echo.dm.NotificationItem( 3 ),
|
||||
new mw.echo.dm.NotificationItem( 4 ),
|
||||
new mw.echo.dm.NotificationItem( 5 )
|
||||
],
|
||||
third: [
|
||||
new mw.echo.dm.NotificationItem( 6 ),
|
||||
new mw.echo.dm.NotificationItem( 7 )
|
||||
],
|
||||
fourth: [
|
||||
new mw.echo.dm.NotificationItem( 8 ),
|
||||
new mw.echo.dm.NotificationItem( 9 )
|
||||
]
|
||||
};
|
||||
|
||||
// Listen to the event
|
||||
model
|
||||
.on( 'discard', function ( group ) {
|
||||
results.push( group.getName() );
|
||||
} );
|
||||
|
||||
// Fill the list
|
||||
for ( group in groups ) {
|
||||
model.addGroup( group, {}, groups[ group ] );
|
||||
}
|
||||
|
||||
// Trigger events
|
||||
model.removeGroup( 'first' ); // [ 'first' ]
|
||||
model.removeGroup( 'fourth' ); // [ 'first', 'fourth' ]
|
||||
// Group doesn't exist, no change
|
||||
model.removeGroup( 'first' ); // [ 'first', 'fourth' ]
|
||||
// Discard of an item in a group (no event on the list model)
|
||||
model.getGroupByName( 'third' ).discardItems( groups.third[ 0 ] ); // [ 'first', 'fourth' ]
|
||||
// Discard of the last item in a group (trigger discard event on the list model)
|
||||
model.getGroupByName( 'third' ).discardItems( groups.third[ 1 ] ); // [ 'first', 'fourth', 'third' ]
|
||||
|
||||
assert.deepEqual(
|
||||
// Actual
|
||||
results,
|
||||
// Expected:
|
||||
[ 'first', 'fourth', 'third' ],
|
||||
// Message
|
||||
'Discard events emitted'
|
||||
);
|
||||
} );
|
||||
|
||||
} )( mediaWiki );
|
141
tests/qunit/model/test_mw.echo.dm.NotificationItem.js
Normal file
141
tests/qunit/model/test_mw.echo.dm.NotificationItem.js
Normal file
|
@ -0,0 +1,141 @@
|
|||
( function ( mw, $ ) {
|
||||
/*global moment:false */
|
||||
var fakeData = {
|
||||
type: 'alert',
|
||||
read: true,
|
||||
seen: true,
|
||||
timestamp: '2016-09-14T23:21:56Z',
|
||||
content: {
|
||||
header: 'Your edit on <strong>Moai</strong> was reverted.',
|
||||
compactHeader: 'Your edit on <strong>Moai</strong> was reverted.',
|
||||
body: 'undo'
|
||||
},
|
||||
iconType: 'revert',
|
||||
primaryUrl: 'http://dev.wiki.local.wmftest.net:8080/w/index.php?title=Moai&oldid=prev&diff=1978&markasread=2126',
|
||||
secondaryUrls: [
|
||||
{
|
||||
url: 'http://dev.wiki.local.wmftest.net:8080/wiki/User:RandomUser',
|
||||
label: 'RandomUser',
|
||||
icon: 'userAvatar'
|
||||
},
|
||||
{
|
||||
url: 'http://dev.wiki.local.wmftest.net:8080/wiki/Talk:Moai',
|
||||
label: 'Moai',
|
||||
tooltip: 'Talk:Moai',
|
||||
icon: 'speechBubbles'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
QUnit.module( 'ext.echo.dm - mw.echo.dm.NotificationItem' );
|
||||
|
||||
QUnit.test( 'Constructing items', function ( assert ) {
|
||||
var i, j, itemModel, checkMethods,
|
||||
defaultValues = {
|
||||
getId: undefined,
|
||||
getContentHeader: '',
|
||||
getContentBody: '',
|
||||
getCategory: '',
|
||||
getType: 'message',
|
||||
isRead: false,
|
||||
isSeen: false,
|
||||
isForeign: false,
|
||||
isBundled: false,
|
||||
getTimestamp: moment.utc().format( 'YYYY-MM-DD[T]HH:mm:ss[Z]' ),
|
||||
getPrimaryUrl: undefined,
|
||||
getIconURL: undefined,
|
||||
getIconType: undefined,
|
||||
getSecondaryUrls: [],
|
||||
getModelName: 'local',
|
||||
getAllIds: []
|
||||
},
|
||||
tests = [
|
||||
{
|
||||
msg: 'Empty data',
|
||||
params: { id: 0, config: {} },
|
||||
tests: 'all',
|
||||
expected: $.extend( true, {}, defaultValues, { getId: 0, getAllIds: [ 0 ] } )
|
||||
},
|
||||
{
|
||||
msg: 'Fake data',
|
||||
params: { id: 999, config: fakeData },
|
||||
tests: 'all',
|
||||
expected: $.extend( true, {}, defaultValues, {
|
||||
getId: 999,
|
||||
getAllIds: [ 999 ],
|
||||
getType: 'alert',
|
||||
isRead: true,
|
||||
isSeen: true,
|
||||
getTimestamp: '2016-09-14T23:21:56Z',
|
||||
getContentHeader: 'Your edit on <strong>Moai</strong> was reverted.',
|
||||
getContentBody: 'undo',
|
||||
getIconType: 'revert',
|
||||
getPrimaryUrl: 'http://dev.wiki.local.wmftest.net:8080/w/index.php?title=Moai&oldid=prev&diff=1978&markasread=2126',
|
||||
getSecondaryUrls: [
|
||||
{
|
||||
url: 'http://dev.wiki.local.wmftest.net:8080/wiki/User:RandomUser',
|
||||
label: 'RandomUser',
|
||||
icon: 'userAvatar'
|
||||
},
|
||||
{
|
||||
url: 'http://dev.wiki.local.wmftest.net:8080/wiki/Talk:Moai',
|
||||
label: 'Moai',
|
||||
tooltip: 'Talk:Moai',
|
||||
icon: 'speechBubbles'
|
||||
}
|
||||
]
|
||||
} )
|
||||
}
|
||||
];
|
||||
|
||||
for ( i = 0; i < tests.length; i++ ) {
|
||||
itemModel = new mw.echo.dm.NotificationItem( tests[ i ].params.id, tests[ i ].params.config );
|
||||
|
||||
checkMethods = tests[ i ].tests;
|
||||
if ( tests[ i ].tests === 'all' ) {
|
||||
checkMethods = Object.keys( defaultValues );
|
||||
}
|
||||
|
||||
for ( j = 0; j < checkMethods.length; j++ ) {
|
||||
assert.deepEqual(
|
||||
// Run the method
|
||||
itemModel[ checkMethods[ j ] ](),
|
||||
// Expected result
|
||||
tests[ i ].expected[ checkMethods[ j ] ],
|
||||
// Message
|
||||
tests[ i ].msg + ' (' + checkMethods[ j ] + ')'
|
||||
);
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
QUnit.test( 'Emitting update event', function ( assert ) {
|
||||
var results = [],
|
||||
itemModel = new mw.echo.dm.NotificationItem( 0, $.extend( true, {}, fakeData, { seen: false, read: false } ) );
|
||||
|
||||
// Listen to update event
|
||||
itemModel.on( 'update', function () {
|
||||
results.push( [
|
||||
itemModel.isRead(),
|
||||
itemModel.isSeen()
|
||||
] );
|
||||
} );
|
||||
|
||||
// Trigger events
|
||||
itemModel.toggleSeen( true ); // [ [ false, true ] ]
|
||||
itemModel.toggleSeen( true ); // [ [ false, true ] ] ( No change, event was not emitted )
|
||||
itemModel.toggleRead( true ); // [ [ false, true ], [ true, true ] ]
|
||||
itemModel.toggleRead( true ); // [ [ false, true ], [ true, true ] ] ( No change, event was not emitted )
|
||||
itemModel.toggleRead( false ); // [ [ false, true ], [ true, true ], [ false, true ] ]
|
||||
itemModel.toggleSeen( false ); // [ [ false, true ], [ true, true ], [ false, true ], [ false, false ] ]
|
||||
itemModel.toggleRead( true ); // [ [ false, true ], [ true, true ], [ false, true ], [ false, false ], [ true, false ] ]
|
||||
|
||||
assert.deepEqual(
|
||||
results,
|
||||
// Expected:
|
||||
[ [ false, true ], [ true, true ], [ false, true ], [ false, false ], [ true, false ] ],
|
||||
'Read and seen changes produced "update" events'
|
||||
);
|
||||
} );
|
||||
|
||||
} )( mediaWiki, jQuery );
|
189
tests/qunit/model/test_mw.echo.dm.NotificationsList.js
Normal file
189
tests/qunit/model/test_mw.echo.dm.NotificationsList.js
Normal file
|
@ -0,0 +1,189 @@
|
|||
( function ( mw, $ ) {
|
||||
var defaultValues = {
|
||||
getAllItemIds: [],
|
||||
getAllItemIdsByType: [],
|
||||
getTitle: '',
|
||||
getName: 'local',
|
||||
getSource: 'local',
|
||||
getSourceURL: '',
|
||||
getTimestamp: 0,
|
||||
getCount: 0,
|
||||
hasUnseen: false,
|
||||
isForeign: false
|
||||
};
|
||||
|
||||
QUnit.module( 'ext.echo.dm - mw.echo.dm.NotificationsList' );
|
||||
|
||||
QUnit.test( 'Constructing the model', function ( assert ) {
|
||||
var i, model, method,
|
||||
cases = [
|
||||
{
|
||||
msg: 'Empty config',
|
||||
config: {},
|
||||
expected: defaultValues
|
||||
},
|
||||
{
|
||||
msg: 'Prefilled data',
|
||||
config: {
|
||||
title: 'Some title',
|
||||
name: 'local_demo',
|
||||
source: 'hewiki',
|
||||
sourceURL: 'http://he.wiki.local.wmftest.net:8080/wiki/$1',
|
||||
timestamp: '20160916171300'
|
||||
},
|
||||
expected: $.extend( true, {}, defaultValues, {
|
||||
getTitle: 'Some title',
|
||||
getName: 'local_demo',
|
||||
getSource: 'hewiki',
|
||||
getSourceURL: 'http://he.wiki.local.wmftest.net:8080/wiki/$1',
|
||||
getTimestamp: '20160916171300',
|
||||
isForeign: true
|
||||
} )
|
||||
}
|
||||
];
|
||||
|
||||
for ( i = 0; i < cases.length; i++ ) {
|
||||
model = new mw.echo.dm.NotificationsList( cases[ i ].config );
|
||||
|
||||
for ( method in cases[ i ].expected ) {
|
||||
assert.deepEqual(
|
||||
// Run the method
|
||||
model[ method ](),
|
||||
// Expected value
|
||||
cases[ i ].expected[ method ],
|
||||
// Message
|
||||
cases[ i ].msg + ' (' + method + ')'
|
||||
);
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
QUnit.test( 'Handling notification items', function ( assert ) {
|
||||
var model = new mw.echo.dm.NotificationsList( { timestamp: '200101010000' } ),
|
||||
items = [
|
||||
new mw.echo.dm.NotificationItem( 0, { type: 'alert', timestamp: '201609190000', read: false, seen: false } ),
|
||||
new mw.echo.dm.NotificationItem( 1, { type: 'message', timestamp: '201609190100', read: false, seen: true } ),
|
||||
new mw.echo.dm.NotificationItem( 2, { type: 'alert', timestamp: '201609190200', read: true, seen: true } ),
|
||||
new mw.echo.dm.NotificationItem( 3, { type: 'message', timestamp: '201609190300', read: true, seen: true } ),
|
||||
new mw.echo.dm.NotificationItem( 4, { type: 'alert', timestamp: '201609190400', read: true, seen: true } ),
|
||||
new mw.echo.dm.NotificationItem( 5, { type: 'message', timestamp: '201609190500', read: true, seen: false } )
|
||||
];
|
||||
|
||||
assert.equal(
|
||||
model.getCount(),
|
||||
0,
|
||||
'Model list starts empty'
|
||||
);
|
||||
assert.equal(
|
||||
model.getTimestamp(),
|
||||
'200101010000',
|
||||
'Model timestamp is its default'
|
||||
);
|
||||
|
||||
model.setItems( items );
|
||||
assert.equal(
|
||||
model.getCount(),
|
||||
6,
|
||||
'Item list setup'
|
||||
);
|
||||
assert.equal(
|
||||
model.getTimestamp(),
|
||||
'201609190100',
|
||||
'Model timestamp is the latest unread item\'s timestamp'
|
||||
);
|
||||
assert.deepEqual(
|
||||
model.getAllItemIds(),
|
||||
[ 1, 0, 5, 4, 3, 2 ],
|
||||
'getAllItemIds (sorted)'
|
||||
);
|
||||
assert.deepEqual(
|
||||
[
|
||||
model.getAllItemIdsByType( 'alert' ),
|
||||
model.getAllItemIdsByType( 'message' )
|
||||
],
|
||||
[
|
||||
[ 0, 4, 2 ],
|
||||
[ 1, 5, 3 ]
|
||||
],
|
||||
'getAllItemIdsByType (sorted)'
|
||||
);
|
||||
assert.deepEqual(
|
||||
model.findByIds( [ 1, 2 ] ),
|
||||
[ items[ 1 ], items[ 2 ] ],
|
||||
'findByIds'
|
||||
);
|
||||
|
||||
// Change item state (trigger resort)
|
||||
items[ 1 ].toggleRead( true );
|
||||
items[ 3 ].toggleRead( false );
|
||||
items[ 5 ].toggleSeen( true ); // Will not affect sorting order of the item
|
||||
assert.deepEqual(
|
||||
model.getAllItemIds(),
|
||||
[ 3, 0, 5, 4, 2, 1 ],
|
||||
'getAllItemIds (re-sorted)'
|
||||
);
|
||||
|
||||
// Discard items
|
||||
model.discardItems( [ items[ 5 ], items[ 2 ] ] );
|
||||
|
||||
assert.deepEqual(
|
||||
model.getAllItemIds(),
|
||||
[ 3, 0, 4, 1 ],
|
||||
'getAllItemIds (discarded items)'
|
||||
);
|
||||
assert.deepEqual(
|
||||
[
|
||||
model.getAllItemIdsByType( 'alert' ),
|
||||
model.getAllItemIdsByType( 'message' )
|
||||
],
|
||||
[
|
||||
[ 0, 4 ],
|
||||
[ 3, 1 ]
|
||||
],
|
||||
'getAllItemIdsByType (discarded items)'
|
||||
);
|
||||
|
||||
} );
|
||||
|
||||
QUnit.test( 'Intercepting events', function ( assert ) {
|
||||
var model = new mw.echo.dm.NotificationsList(),
|
||||
result = [],
|
||||
items = [
|
||||
new mw.echo.dm.NotificationItem( 0, { timestamp: '201609190000', read: false, seen: false } ),
|
||||
new mw.echo.dm.NotificationItem( 1, { timestamp: '201609190100', read: false, seen: true } ),
|
||||
new mw.echo.dm.NotificationItem( 2, { timestamp: '201609190200', read: true, seen: true } ),
|
||||
new mw.echo.dm.NotificationItem( 3, { timestamp: '201609190300', read: true, seen: true } ),
|
||||
new mw.echo.dm.NotificationItem( 4, { timestamp: '201609190400', read: true, seen: true } ),
|
||||
new mw.echo.dm.NotificationItem( 5, { timestamp: '201609190500', read: true, seen: true } )
|
||||
];
|
||||
|
||||
// Listen to events
|
||||
model
|
||||
.on( 'update', function ( items ) {
|
||||
result.push( 'update:' + items.length );
|
||||
} )
|
||||
.on( 'discard', function ( item ) {
|
||||
result.push( 'discard:' + item.getId() );
|
||||
} )
|
||||
.on( 'itemUpdate', function ( item ) {
|
||||
result.push( 'itemUpdate:' + item.getId() );
|
||||
} );
|
||||
|
||||
// Set up and trigger events
|
||||
model
|
||||
.setItems( items ); // [ 'update:6' ]
|
||||
model.discardItems( items[ items.length - 1 ] ); // [ 'update:6', 'discard:5' ]
|
||||
items[ 0 ].toggleSeen( true ); // [ 'update:6', 'discard:5', 'itemUpdate:0' ]
|
||||
items[ 1 ].toggleRead( true ); // [ 'update:6', 'discard:5', 'itemUpdate:0', 'itemUpdate:1' ]
|
||||
|
||||
assert.deepEqual(
|
||||
// Actual
|
||||
result,
|
||||
// Expected:
|
||||
[ 'update:6', 'discard:5', 'itemUpdate:0', 'itemUpdate:1' ],
|
||||
// Message
|
||||
'Events emitted correctly'
|
||||
);
|
||||
} );
|
||||
|
||||
} )( mediaWiki, jQuery );
|
91
tests/qunit/model/test_mw.echo.dm.PaginationModel.js
Normal file
91
tests/qunit/model/test_mw.echo.dm.PaginationModel.js
Normal file
|
@ -0,0 +1,91 @@
|
|||
( function ( mw, $ ) {
|
||||
var defaultValues = {
|
||||
getPageContinue: undefined,
|
||||
getCurrPageIndex: 0,
|
||||
getPrevPageContinue: '',
|
||||
getCurrPageContinue: '',
|
||||
getNextPageContinue: '',
|
||||
hasPrevPage: false,
|
||||
hasNextPage: false,
|
||||
getCurrentPageItemCount: 25,
|
||||
getItemsPerPage: 25
|
||||
};
|
||||
|
||||
QUnit.module( 'ext.echo.dm - mw.echo.dm.PaginationModel' );
|
||||
|
||||
QUnit.test( 'Constructing the model', function ( assert ) {
|
||||
var i, model, method,
|
||||
cases = [
|
||||
{
|
||||
msg: 'Empty config',
|
||||
config: {},
|
||||
expected: defaultValues
|
||||
},
|
||||
{
|
||||
msg: 'Overridng defaults',
|
||||
config: {
|
||||
pageNext: 'continueValNext|123',
|
||||
itemsPerPage: 10
|
||||
},
|
||||
expected: $.extend( true, {}, defaultValues, {
|
||||
getNextPageContinue: 'continueValNext|123',
|
||||
hasNextPage: true,
|
||||
getItemsPerPage: 10,
|
||||
getCurrentPageItemCount: 10
|
||||
} )
|
||||
}
|
||||
];
|
||||
|
||||
for ( i = 0; i < cases.length; i++ ) {
|
||||
model = new mw.echo.dm.PaginationModel( cases[ i ].config );
|
||||
|
||||
for ( method in cases[ i ].expected ) {
|
||||
assert.deepEqual(
|
||||
// Run the method
|
||||
model[ method ](),
|
||||
// Expected value
|
||||
cases[ i ].expected[ method ],
|
||||
// Message
|
||||
cases[ i ].msg + ' (' + method + ')'
|
||||
);
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
QUnit.test( 'Emitting update event', function ( assert ) {
|
||||
var results = [],
|
||||
model = new mw.echo.dm.PaginationModel();
|
||||
|
||||
// Listen to update event
|
||||
model.on( 'update', function () {
|
||||
results.push( [
|
||||
model.getCurrPageIndex(),
|
||||
model.hasNextPage()
|
||||
] );
|
||||
} );
|
||||
|
||||
// Trigger events
|
||||
|
||||
// Set up initial pages (first page is 0)
|
||||
model.setPageContinue( 1, 'page2|2' ); // [ [ 0, true ] ]
|
||||
model.setPageContinue( 2, 'page3|3' ); // [ [ 0, true ], [ 0, true ] ]
|
||||
model.setPageContinue( 3, 'page4|4' ); // [ [ 0, true ], [ 0, true ], [ 0, true ] ]
|
||||
|
||||
model.forwards(); // [ [ 0, true ], [ 0, true ], [ 0, true ], [ 1, true ] ]
|
||||
model.forwards(); // [ [ 0, true ], [ 0, true ], [ 0, true ], [ 1, true ], [ 2, true ] ]
|
||||
model.forwards(); // [ [ 0, true ], [ 0, true ], [ 0, true ], [ 1, true ], [ 2, true ], [ 3, false ] ]
|
||||
model.backwards(); // [ [ 0, true ], [ 0, true ], [ 0, true ], [ 1, true ], [ 2, true ], [ 3, false ], [ 2, true ] ]
|
||||
model.setCurrentPageItemCount(); // [ [ 0, true ], [ 0, true ], [ 0, true ], [ 1, true ], [ 2, true ], [ 3, false ], [ 2, true ], [ 2, true ] ]
|
||||
model.reset(); // [ [ 0, true ], [ 0, true ], [ 0, true ], [ 1, true ], [ 2, true ], [ 3, false ], [ 2, true ], [ 2, true ], [ 0, false ] ]
|
||||
|
||||
assert.deepEqual(
|
||||
// Actual
|
||||
results,
|
||||
// Expected:
|
||||
[ [ 0, true ], [ 0, true ], [ 0, true ], [ 1, true ], [ 2, true ], [ 3, false ], [ 2, true ], [ 2, true ], [ 0, false ] ],
|
||||
// Message
|
||||
'Update events emitted'
|
||||
);
|
||||
} );
|
||||
|
||||
} )( mediaWiki, jQuery );
|
56
tests/qunit/model/test_mw.echo.dm.SeenTimeModel.js
Normal file
56
tests/qunit/model/test_mw.echo.dm.SeenTimeModel.js
Normal file
|
@ -0,0 +1,56 @@
|
|||
( function ( mw ) {
|
||||
QUnit.module( 'ext.echo.dm - mw.echo.dm.SeenTimeModel' );
|
||||
|
||||
QUnit.test( 'Constructing the model', function ( assert ) {
|
||||
var model = new mw.echo.dm.SeenTimeModel();
|
||||
|
||||
assert.deepEqual(
|
||||
model.getTypes(),
|
||||
[ 'alert', 'message' ],
|
||||
'Default model has both types'
|
||||
);
|
||||
} );
|
||||
|
||||
QUnit.test( 'Handling seenTime', function ( assert ) {
|
||||
var model;
|
||||
|
||||
model = new mw.echo.dm.SeenTimeModel();
|
||||
model.setSeenTime( '20160101010000' );
|
||||
|
||||
assert.deepEqual(
|
||||
model.getSeenTime(),
|
||||
'20160101010000',
|
||||
'Model sets seen time for both types'
|
||||
);
|
||||
|
||||
model = new mw.echo.dm.SeenTimeModel( { types: 'alert' } );
|
||||
model.setSeenTime( '20160101010001' );
|
||||
|
||||
assert.deepEqual(
|
||||
model.getSeenTime(),
|
||||
'20160101010001',
|
||||
'Alerts seen time model returns correct time'
|
||||
);
|
||||
} );
|
||||
|
||||
QUnit.test( 'Emitting update event', function ( assert ) {
|
||||
var results = [],
|
||||
model = new mw.echo.dm.SeenTimeModel();
|
||||
|
||||
// Attach a listener
|
||||
model.on( 'update', function ( time ) {
|
||||
results.push( time );
|
||||
} );
|
||||
|
||||
// Trigger events
|
||||
model.setSeenTime( '1' ); // [ '1' ]
|
||||
model.setSeenTime( '2' ); // [ '1', '2' ]
|
||||
model.setSeenTime( '2' ); // (no change, no event) [ '1', '2' ]
|
||||
|
||||
assert.deepEqual(
|
||||
results,
|
||||
[ '1', '2' ],
|
||||
'Update event emitted'
|
||||
);
|
||||
} );
|
||||
} )( mediaWiki );
|
172
tests/qunit/model/test_mw.echo.dm.SourcePagesModel.js
Normal file
172
tests/qunit/model/test_mw.echo.dm.SourcePagesModel.js
Normal file
|
@ -0,0 +1,172 @@
|
|||
( function ( mw ) {
|
||||
// Mock partial API response we feed into the model
|
||||
var sources = {
|
||||
local: {
|
||||
pages: [
|
||||
{
|
||||
ns: 2,
|
||||
title: 'User:Admin',
|
||||
unprefixed: 'Admin',
|
||||
pages: [
|
||||
'User:Admin',
|
||||
'User talk:Admin',
|
||||
null
|
||||
],
|
||||
count: 24
|
||||
},
|
||||
{
|
||||
ns: 2,
|
||||
title: 'User:RandomUser',
|
||||
unprefixed: 'RandomUser',
|
||||
pages: [
|
||||
'User:RandomUser',
|
||||
'User talk:RandomUser'
|
||||
],
|
||||
count: 6
|
||||
},
|
||||
{
|
||||
ns: 0,
|
||||
title: 'Moai',
|
||||
unprefixed: 'Moai',
|
||||
pages: [
|
||||
'Moai',
|
||||
'Talk:Moai'
|
||||
],
|
||||
count: 3
|
||||
}
|
||||
],
|
||||
totalCount: 33,
|
||||
source: {
|
||||
title: 'LocalWiki',
|
||||
url: 'http://dev.wiki.local.wmftest.net:8080/w/api.php',
|
||||
base: 'http://dev.wiki.local.wmftest.net:8080/wiki/$1'
|
||||
}
|
||||
},
|
||||
hewiki: {
|
||||
pages: [
|
||||
{
|
||||
ns: 2,
|
||||
title: 'Foo',
|
||||
unprefixed: 'Foo',
|
||||
pages: [
|
||||
'Foo',
|
||||
'Talk:Foo',
|
||||
null
|
||||
],
|
||||
count: 10
|
||||
},
|
||||
{
|
||||
ns: 0,
|
||||
title: 'User:Bar',
|
||||
unprefixed: 'Bar',
|
||||
pages: [
|
||||
'User:Bar',
|
||||
'User talk:Bar'
|
||||
],
|
||||
count: 5
|
||||
}
|
||||
],
|
||||
totalCount: 15,
|
||||
source: {
|
||||
title: 'Hebrew Wikipedia',
|
||||
url: 'http://he.wiki.local.wmftest.net:8080/w/api.php',
|
||||
base: 'http://he.wiki.local.wmftest.net:8080/wiki/$1'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
QUnit.module( 'ext.echo.dm - mw.echo.dm.SourcePagesModel' );
|
||||
|
||||
QUnit.test( 'Creating source-page map', function ( assert ) {
|
||||
var model = new mw.echo.dm.SourcePagesModel();
|
||||
|
||||
model.setAllSources( sources );
|
||||
|
||||
assert.equal(
|
||||
model.getCurrentSource(),
|
||||
'local',
|
||||
'Default source is local'
|
||||
);
|
||||
assert.equal(
|
||||
model.getCurrentPage(),
|
||||
null,
|
||||
'Default page is null'
|
||||
);
|
||||
assert.deepEqual(
|
||||
model.getSourcesArray(),
|
||||
[ 'local', 'hewiki' ],
|
||||
'Source array includes all sources'
|
||||
);
|
||||
assert.equal(
|
||||
model.getSourceTitle( 'hewiki' ),
|
||||
'Hebrew Wikipedia',
|
||||
'Source title'
|
||||
);
|
||||
assert.equal(
|
||||
model.getSourceTotalCount( 'hewiki' ),
|
||||
15,
|
||||
'Source total count'
|
||||
);
|
||||
assert.deepEqual(
|
||||
model.getSourcePages( 'local' ),
|
||||
{
|
||||
Moai: {
|
||||
count: 3,
|
||||
ns: 0,
|
||||
pages: [
|
||||
'Moai',
|
||||
'Talk:Moai'
|
||||
],
|
||||
title: 'Moai',
|
||||
unprefixed: 'Moai'
|
||||
},
|
||||
'User:Admin': {
|
||||
count: 24,
|
||||
ns: 2,
|
||||
pages: [
|
||||
'User:Admin',
|
||||
'User talk:Admin',
|
||||
null
|
||||
],
|
||||
title: 'User:Admin',
|
||||
unprefixed: 'Admin'
|
||||
},
|
||||
'User:RandomUser': {
|
||||
count: 6,
|
||||
ns: 2,
|
||||
pages: [
|
||||
'User:RandomUser',
|
||||
'User talk:RandomUser'
|
||||
],
|
||||
title: 'User:RandomUser',
|
||||
unprefixed: 'RandomUser'
|
||||
}
|
||||
},
|
||||
'Outputting source pages'
|
||||
);
|
||||
assert.deepEqual(
|
||||
model.getGroupedPagesForTitle( 'local', 'User:Admin' ),
|
||||
[
|
||||
'User:Admin',
|
||||
'User talk:Admin',
|
||||
null
|
||||
],
|
||||
'Grouped pages per title'
|
||||
);
|
||||
|
||||
// Change source
|
||||
model.setCurrentSourcePage( 'hewiki', 'User:Bar' );
|
||||
|
||||
assert.equal(
|
||||
model.getCurrentSource(),
|
||||
'hewiki',
|
||||
'Source changed successfully'
|
||||
);
|
||||
assert.equal(
|
||||
model.getCurrentPage(),
|
||||
'User:Bar',
|
||||
'Page changed successfully'
|
||||
);
|
||||
|
||||
} );
|
||||
} )( mediaWiki );
|
|
@ -1,256 +0,0 @@
|
|||
( function ( mw, $ ) {
|
||||
var echoApi,
|
||||
mockCounter,
|
||||
noop = function () {};
|
||||
|
||||
QUnit.module( 'ext.echo.dm mw.echo.dm.NotificationsModel' );
|
||||
|
||||
function runPreparation( model, testPrepare ) {
|
||||
var j, jlen;
|
||||
|
||||
for ( j = 0, jlen = testPrepare.length; j < jlen; j++ ) {
|
||||
model[ testPrepare[ j ].method ].apply( model, testPrepare[ j ].params );
|
||||
}
|
||||
}
|
||||
|
||||
// Helper method to get an array of item ids for testing
|
||||
function getIdArray( arr ) {
|
||||
return arr.map( function ( item ) {
|
||||
return item.getId();
|
||||
} );
|
||||
}
|
||||
|
||||
// Set up a dummy API handler to avoid sending requests to the API during tests
|
||||
function TestApiHandler() {
|
||||
// Parent constructor
|
||||
TestApiHandler.parent.call( this );
|
||||
}
|
||||
/* Setup */
|
||||
OO.inheritClass( TestApiHandler, mw.echo.api.APIHandler );
|
||||
// Override api call
|
||||
TestApiHandler.prototype.markItemsRead = function () {
|
||||
return $.Deferred().resolve( 0 );
|
||||
};
|
||||
|
||||
mockCounter = { estimateChange: noop, update: noop };
|
||||
|
||||
// Create an Echo API instance
|
||||
echoApi = new mw.echo.api.EchoApi();
|
||||
// HACK: Reach into the EchoAPI to create a test handler
|
||||
echoApi.network.setApiHandler( 'test', new TestApiHandler() );
|
||||
|
||||
QUnit.test( 'Adding notifications', function ( assert ) {
|
||||
var initialItems = [
|
||||
new mw.echo.dm.NotificationItem( 0, { timestamp: '20150828173000', read: false } ),
|
||||
new mw.echo.dm.NotificationItem( 1, { timestamp: '20150828173100', read: false } ),
|
||||
new mw.echo.dm.NotificationItem( 2, { timestamp: '20150828173200', read: false } )
|
||||
],
|
||||
cases = [
|
||||
{
|
||||
items: initialItems,
|
||||
expected: [ 2, 1, 0 ],
|
||||
msg: 'Inserting items in timestamp order.'
|
||||
},
|
||||
{
|
||||
items: [
|
||||
initialItems[ 0 ],
|
||||
initialItems[ 1 ],
|
||||
initialItems[ 2 ],
|
||||
initialItems[ 0 ]
|
||||
],
|
||||
expected: [ 2, 1, 0 ],
|
||||
msg: 'Reinserting an item to its rightful position.'
|
||||
},
|
||||
{
|
||||
items: [
|
||||
new mw.echo.dm.NotificationItem( 0, { timestamp: '20150828173000', read: false } ),
|
||||
new mw.echo.dm.NotificationItem( 1, { timestamp: '20150828173100', read: false } ),
|
||||
new mw.echo.dm.NotificationItem( 2, { timestamp: '20150828173200', read: false } )
|
||||
],
|
||||
run: [
|
||||
{
|
||||
item: 0,
|
||||
method: 'setTimestamp',
|
||||
args: [ '20150830173000' ] // Newer timestamp
|
||||
}
|
||||
],
|
||||
expected: [ 0, 2, 1 ],
|
||||
msg: 'Changing timestamp on an item.'
|
||||
},
|
||||
{
|
||||
items: [
|
||||
new mw.echo.dm.NotificationItem( 0, { timestamp: '20150828173000', read: false } ),
|
||||
new mw.echo.dm.NotificationItem( 1, { timestamp: '20150828173100', read: false } ),
|
||||
new mw.echo.dm.NotificationItem( 2, { timestamp: '20150828173200', read: false } )
|
||||
],
|
||||
run: [
|
||||
{
|
||||
item: 1,
|
||||
method: 'toggleRead',
|
||||
args: [ true ] // Item is read
|
||||
}
|
||||
],
|
||||
expected: [ 2, 0, 1 ],
|
||||
msg: 'Changing read status of an item.'
|
||||
}
|
||||
];
|
||||
|
||||
QUnit.expect( cases.length );
|
||||
|
||||
cases.forEach( function ( test ) {
|
||||
var r, runCase, runItem,
|
||||
model = new mw.echo.dm.NotificationsModel( echoApi, mockCounter, {
|
||||
type: 'alert',
|
||||
source: 'test',
|
||||
limit: 25,
|
||||
userLang: 'en'
|
||||
} );
|
||||
|
||||
model.addItems( test.items );
|
||||
|
||||
if ( test.add ) {
|
||||
model.addItems( test.add.items );
|
||||
}
|
||||
if ( test.run ) {
|
||||
for ( r = 0; r < test.run.length; r++ ) {
|
||||
runCase = test.run[ r ];
|
||||
runItem = test.items[ runCase.item ];
|
||||
runItem[ runCase.method ].apply( runItem, runCase.args );
|
||||
}
|
||||
}
|
||||
|
||||
assert.deepEqual( getIdArray( model.getItems() ), test.expected, test.msg );
|
||||
}, this );
|
||||
} );
|
||||
|
||||
QUnit.test( 'Deleting notifications', 2, function ( assert ) {
|
||||
var model = new mw.echo.dm.NotificationsModel( echoApi, mockCounter, {
|
||||
type: 'alert',
|
||||
source: 'test',
|
||||
limit: 25,
|
||||
userLang: 'en'
|
||||
} ),
|
||||
items = [
|
||||
new mw.echo.dm.NotificationItem( 1, { content: '1', timestamp: '20150828172900' } ),
|
||||
new mw.echo.dm.NotificationItem( 2, { content: '2', timestamp: '20150828172900' } ),
|
||||
new mw.echo.dm.NotificationItem( 3, { content: '3', timestamp: '20150828172900' } ),
|
||||
new mw.echo.dm.NotificationItem( 4, { content: '4', timestamp: '20150828172900' } ),
|
||||
new mw.echo.dm.NotificationItem( 5, { content: '5', timestamp: '20150828172900' } ),
|
||||
new mw.echo.dm.NotificationItem( 6, { content: '6', timestamp: '20150828172900' } ),
|
||||
new mw.echo.dm.NotificationItem( 7, { content: '7', timestamp: '20150828172900' } ),
|
||||
new mw.echo.dm.NotificationItem( 8, { content: '8', timestamp: '20150828172900' } ),
|
||||
new mw.echo.dm.NotificationItem( 9, { content: '9', timestamp: '20150828172900' } ),
|
||||
new mw.echo.dm.NotificationItem( 10, { content: '10', timestamp: '20150828172900' } )
|
||||
];
|
||||
|
||||
// Add initial notifications
|
||||
model.addItems( items );
|
||||
|
||||
// Verify we have the correct number initially
|
||||
assert.equal( model.getItemCount(), 10, 'Added initial number of notifications' );
|
||||
|
||||
// Remove notifications
|
||||
model.removeItems( [ items[ 0 ], items[ 1 ], items[ 5 ] ] );
|
||||
|
||||
// Test
|
||||
assert.equal( model.getItemCount(), 7, 'Successfully deleted notifications' );
|
||||
} );
|
||||
|
||||
QUnit.test( 'Clearing notifications', function ( assert ) {
|
||||
var i, ilen, model, actual, test,
|
||||
cases = [
|
||||
{
|
||||
prepare: [
|
||||
{
|
||||
method: 'addItems',
|
||||
params: [
|
||||
[
|
||||
new mw.echo.dm.NotificationItem( 1, {
|
||||
content: '1',
|
||||
timestamp: '20150828172900'
|
||||
} ),
|
||||
new mw.echo.dm.NotificationItem( 2, { content: '2', timestamp: '20150828172900' } )
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
method: 'clearItems'
|
||||
}
|
||||
],
|
||||
run: {
|
||||
method: 'getItemCount'
|
||||
},
|
||||
expect: 0,
|
||||
message: 'Clearing notifications'
|
||||
}
|
||||
];
|
||||
|
||||
assert.expect( cases.length );
|
||||
|
||||
for ( i = 0, ilen = cases.length; i < ilen; i++ ) {
|
||||
model = new mw.echo.dm.NotificationsModel( echoApi, mockCounter, {
|
||||
type: 'alert',
|
||||
source: 'test',
|
||||
limit: 25,
|
||||
userLang: 'en'
|
||||
} );
|
||||
|
||||
test = cases[ i ];
|
||||
|
||||
// Run preparation
|
||||
runPreparation( model, test.prepare );
|
||||
|
||||
// Test
|
||||
actual = model[ test.run.method ].apply( model, cases[ i ].run.params );
|
||||
assert.equal( actual, cases[ i ].expect, cases[ i ].message );
|
||||
}
|
||||
} );
|
||||
|
||||
QUnit.test( 'Changing read/unread status', function ( assert ) {
|
||||
var i,
|
||||
initialItems = [
|
||||
new mw.echo.dm.NotificationItem( 0, { timestamp: '20150828173000', read: false } ),
|
||||
new mw.echo.dm.NotificationItem( 1, { timestamp: '20150828173100', read: false } ),
|
||||
new mw.echo.dm.NotificationItem( 2, { timestamp: '20150828173200', read: false } ),
|
||||
new mw.echo.dm.NotificationItem( 3, { timestamp: '20150828173300', read: false } ),
|
||||
// Notice that in item 4 the timestamp is earlier
|
||||
new mw.echo.dm.NotificationItem( 4, { timestamp: '20150828172900', read: true } ),
|
||||
new mw.echo.dm.NotificationItem( 5, { timestamp: '20150828173500', read: true } )
|
||||
],
|
||||
cases = [
|
||||
{
|
||||
items: initialItems,
|
||||
expected: [ 3, 2, 1, 0, 5, 4 ],
|
||||
msg: 'Items organized by read/unread groups'
|
||||
},
|
||||
{
|
||||
items: initialItems,
|
||||
markRead: [ initialItems[ 1 ], initialItems[ 3 ] ],
|
||||
expected: [ 2, 0, 5, 3, 1, 4 ],
|
||||
msg: 'Items marked as read are pushed to the end'
|
||||
}
|
||||
];
|
||||
|
||||
QUnit.expect( cases.length );
|
||||
|
||||
cases.forEach( function ( test ) {
|
||||
var model = new mw.echo.dm.NotificationsModel( echoApi, mockCounter, {
|
||||
type: 'alert',
|
||||
source: 'test',
|
||||
limit: 25,
|
||||
userLang: 'en'
|
||||
} );
|
||||
|
||||
model.addItems( test.items );
|
||||
|
||||
if ( test.markRead ) {
|
||||
for ( i = 0; i < test.markRead.length; i++ ) {
|
||||
test.markRead[ i ].toggleRead( true );
|
||||
}
|
||||
}
|
||||
|
||||
assert.deepEqual( getIdArray( model.getItems() ), test.expected, test.msg );
|
||||
}, this );
|
||||
} );
|
||||
|
||||
} )( mediaWiki, jQuery );
|
Loading…
Reference in a new issue