Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions extension.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@
"formats/ext.srf.formats.eventcalendar.tests.js",
"formats/ext.srf.formats.filtered.test.js",
"formats/ext.srf.formats.gallery.test.js",
"formats/ext.srf.formats.gallery.overlay.test.js",
"formats/ext.srf.formats.gallery.redirect.test.js",
"formats/ext.srf.formats.media.test.js",
"formats/ext.srf.formats.tagcloud.test.js",
"widgets/ext.srf.widgets.eventcalendar.tests.js",
Expand Down
2 changes: 1 addition & 1 deletion formats/gallery/resources/ext.srf.gallery.overlay.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@
$this.find( '.gallerybox' ).each( function () {
var $this = $( this ),
h = mw.html,
image = $this.find( 'a.image' ),
image = $this.find( 'a.mw-file-description' ),
imageText = $.trim( $this.find( '.gallerytext p' ).text() );

// Group images
Expand Down
2 changes: 1 addition & 1 deletion formats/gallery/resources/ext.srf.gallery.redirect.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
return context.find( '.gallerybox' ).each( function() {
var $this = $( this ),
h = mw.html,
image = $this.find( 'a.image' );
image = $this.find( 'a.mw-file-description' );

// Avoid undefined error
if ( image.attr( 'href' ) === undefined ) {
Expand Down
2 changes: 1 addition & 1 deletion resources/jquery/fancybox/jquery.fancybox-1.3.4.pack.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

105 changes: 105 additions & 0 deletions tests/qunit/formats/ext.srf.formats.gallery.overlay.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/**
* QUnit tests for the SRF gallery overlay functionality
*
* @file
* @since 5.1.0
*
* @ingroup SRF
*
* @licence GPL-2.0-or-later
* @author GitHub Copilot Assistant
*/

( function ( $, mw, srf ) {
'use strict';

QUnit.module( 'ext.srf.formats.gallery.overlay', QUnit.newMwEnvironment() );

/**
* Test overlay initialization with mw-file-description selector
*/
QUnit.test( 'overlay handles mw-file-description selector', function ( assert ) {
assert.expect( 4 );

// Create mock HTML structure with new MediaWiki gallery format
var mockHtml = $(
'<ul class="gallery mw-gallery-traditional" id="test-gallery">' +
'<li class="gallerybox" style="width: 155px">' +
'<div style="width: 155px">' +
'<div class="thumb" style="width: 150px;">' +
'<div style="margin:15px auto;">' +
'<a class="mw-file-description" href="/wiki/File:Test.jpg" title="Test image">' +
'<img alt="Test image" src="/thumb/Test.jpg/120px-Test.jpg" width="120" height="90" />' +
'</a>' +
'</div>' +
'</div>' +
'<div class="gallerytext">' +
'<p>Test image description</p>' +
'</div>' +
'</div>' +
'</li>' +
'</ul>'
);

$( '#qunit-fixture' ).append( mockHtml );
var context = $( '#test-gallery' );
var gallery = new srf.formats.gallery();

// Test that the overlay function finds the correct selector
gallery.overlay( context, 'File' );

var imageLink = context.find( 'a.mw-file-description' );
assert.ok( imageLink.length > 0, 'Found image link with mw-file-description class' );
assert.equal( imageLink.attr( 'rel' ), 'test-gallery', 'Image link has correct rel attribute for grouping' );
assert.equal( imageLink.attr( 'title' ), 'Test image description', 'Image link has correct title from gallery text' );
assert.ok( imageLink.attr( 'href' ).indexOf( 'File:Test.jpg' ) > -1, 'Image link href points to correct file' );
} );

/**
* Test overlay with empty gallery
*/
QUnit.test( 'overlay handles empty gallery gracefully', function ( assert ) {
assert.expect( 1 );

var emptyGallery = $( '<ul class="gallery mw-gallery-traditional" id="empty-gallery"></ul>' );
$( '#qunit-fixture' ).append( emptyGallery );

var gallery = new srf.formats.gallery();

// Should not throw error with empty gallery
gallery.overlay( emptyGallery, 'File' );

assert.ok( true, 'Overlay handles empty gallery without errors' );
} );

/**
* Test overlay with missing href attribute
*/
QUnit.test( 'overlay handles missing href gracefully', function ( assert ) {
assert.expect( 2 );

var mockHtml = $(
'<ul class="gallery mw-gallery-traditional" id="test-gallery-no-href">' +
'<li class="gallerybox">' +
'<div>' +
'<a class="mw-file-description" title="Test image">' +
'<img alt="Test image" src="/thumb/Test.jpg/120px-Test.jpg" />' +
'</a>' +
'</div>' +
'<div class="gallerytext"><p>Test description</p></div>' +
'</li>' +
'</ul>'
);

$( '#qunit-fixture' ).append( mockHtml );
var context = $( '#test-gallery-no-href' );
var gallery = new srf.formats.gallery();

gallery.overlay( context, 'File' );

var galleryBox = context.find( '.gallerybox' );
assert.ok( galleryBox.find( '.error' ).length > 0, 'Error message displayed for missing href' );
assert.ok( galleryBox.html().indexOf( 'srf-gallery-image-url-error' ) > -1, 'Correct error message key used' );
} );

}( jQuery, mediaWiki, semanticFormats ) );
189 changes: 189 additions & 0 deletions tests/qunit/formats/ext.srf.formats.gallery.redirect.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
/**
* QUnit tests for the SRF gallery redirect functionality
*
* @file
* @since 5.1.0
*
* @ingroup SRF
*
* @licence GPL-2.0-or-later
* @author GitHub Copilot Assistant
*/

( function ( $, mw, srf ) {
'use strict';

QUnit.module( 'ext.srf.formats.gallery.redirect', QUnit.newMwEnvironment() );

/**
* Mock srf.util for testing
*/
var mockUtil = function() {
return {
spinner: {
create: function() {},
replace: function() {}
},
getTitleURL: function( params, callback ) {
// Mock successful URL retrieval
if ( params.title === 'Valid_Title' ) {
callback( '/wiki/Valid_Title' );
} else {
callback( false );
}
}
};
};

// Mock srf.util
var originalUtil = srf.util;
srf.util = mockUtil;

/**
* Test redirect functionality with mw-file-description selector
*/
QUnit.test( 'redirect handles mw-file-description selector', function ( assert ) {
assert.expect( 3 );

var mockHtml = $(
'<div class="srf-redirect" data-redirect-type="_uri">' +
'<ul class="gallery mw-gallery-traditional">' +
'<li class="gallerybox">' +
'<div>' +
'<a class="mw-file-description" href="/wiki/File:Test.jpg">' +
'<img alt="http://example.com/redirect-target" src="/thumb/Test.jpg/120px-Test.jpg" />' +
'</a>' +
'</div>' +
'</li>' +
'</ul>' +
'</div>'
);

$( '#qunit-fixture' ).append( mockHtml );
var context = mockHtml;
var gallery = new srf.formats.gallery();

gallery.redirect( context );

var imageLink = context.find( 'a.mw-file-description' );
var redirectIcon = context.find( '.redirecticon' );

assert.ok( imageLink.length > 0, 'Found image link with mw-file-description class' );
assert.equal( imageLink.attr( 'href' ), 'http://example.com/redirect-target', 'Image href updated to redirect URL from alt attribute' );
assert.ok( redirectIcon.is( ':visible' ), 'Redirect icon is visible for URI type redirect' );
} );

/**
* Test redirect with article title resolution
*/
QUnit.test( 'redirect resolves article titles', function ( assert ) {
var done = assert.async();
assert.expect( 3 );

var mockHtml = $(
'<div class="srf-redirect" data-redirect-type="article">' +
'<ul class="gallery mw-gallery-traditional">' +
'<li class="gallerybox">' +
'<div>' +
'<a class="mw-file-description" href="/wiki/File:Test.jpg">' +
'<img alt="Valid_Title" src="/thumb/Test.jpg/120px-Test.jpg" />' +
'</a>' +
'</div>' +
'</li>' +
'</ul>' +
'</div>'
);

$( '#qunit-fixture' ).append( mockHtml );
var context = mockHtml;
var gallery = new srf.formats.gallery();

gallery.redirect( context );

// Wait for async URL resolution
setTimeout( function() {
var imageLink = context.find( 'a.mw-file-description' );
var redirectIcon = context.find( '.redirecticon' );

assert.ok( imageLink.length > 0, 'Found image link with mw-file-description class' );
assert.equal( imageLink.attr( 'href' ), '/wiki/Valid_Title', 'Image href updated to resolved article URL' );
assert.ok( redirectIcon.is( ':visible' ), 'Redirect icon is visible after successful title resolution' );
done();
}, 100 );
} );

/**
* Test redirect with missing href attribute
*/
QUnit.test( 'redirect handles missing href gracefully', function ( assert ) {
assert.expect( 2 );

var mockHtml = $(
'<div class="srf-redirect" data-redirect-type="_uri">' +
'<ul class="gallery mw-gallery-traditional">' +
'<li class="gallerybox">' +
'<div>' +
'<a class="mw-file-description">' +
'<img alt="http://example.com/redirect" src="/thumb/Test.jpg/120px-Test.jpg" />' +
'</a>' +
'</div>' +
'</li>' +
'</ul>' +
'</div>'
);

$( '#qunit-fixture' ).append( mockHtml );
var context = mockHtml;
var gallery = new srf.formats.gallery();

gallery.redirect( context );

var galleryBox = context.find( '.gallerybox' );
assert.ok( galleryBox.find( '.error' ).length > 0, 'Error message displayed for missing href' );
assert.ok( galleryBox.html().indexOf( 'srf-gallery-image-url-error' ) > -1, 'Correct error message key used' );
} );

/**
* Test redirect with failed title resolution
*/
QUnit.test( 'redirect handles failed title resolution', function ( assert ) {
var done = assert.async();
assert.expect( 2 );

var mockHtml = $(
'<div class="srf-redirect" data-redirect-type="article">' +
'<ul class="gallery mw-gallery-traditional">' +
'<li class="gallerybox">' +
'<div>' +
'<a class="mw-file-description" href="/wiki/File:Test.jpg">' +
'<img alt="Invalid_Title" src="/thumb/Test.jpg/120px-Test.jpg" />' +
'</a>' +
'</div>' +
'</li>' +
'</ul>' +
'</div>'
);

$( '#qunit-fixture' ).append( mockHtml );
var context = mockHtml;
var gallery = new srf.formats.gallery();

gallery.redirect( context );

// Wait for async URL resolution
setTimeout( function() {
var imageLink = context.find( 'a.mw-file-description' );
var redirectIcon = context.find( '.redirecticon' );

assert.equal( imageLink.attr( 'href' ), '', 'Image href cleared on failed title resolution' );
assert.ok( redirectIcon.is( ':hidden' ), 'Redirect icon hidden on failed title resolution' );
done();
}, 100 );
} );

// Restore original srf.util after tests
QUnit.testDone( function() {
srf.util = originalUtil;
} );

}( jQuery, mediaWiki, semanticFormats ) );