mirror of
https://github.com/compiler-explorer/compiler-explorer.git
synced 2025-12-27 11:44:09 -05:00
Convert sponsor.js to sponsor.js, update tests to be more targeted. (#4199)
* Convert sponsor.js to sponsor.js, update tests to be more targeted. Co-authored-by: Rubén Rincón Blanco <ruben@rinconblanco.es>
This commit is contained in:
49
lib/sponsors.interfaces.ts
Normal file
49
lib/sponsors.interfaces.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
// Copyright (c) 2022, Compiler Explorer Authors
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
export type Sponsor = {
|
||||
name: string;
|
||||
description?: string;
|
||||
img?: string;
|
||||
icon?: string;
|
||||
icon_dark?: string;
|
||||
url?: string;
|
||||
onclick: string;
|
||||
priority: number;
|
||||
topIcon: boolean;
|
||||
sideBySide: boolean;
|
||||
statsId?: string;
|
||||
};
|
||||
|
||||
export type Level = {
|
||||
name: string;
|
||||
description: string;
|
||||
class?: string;
|
||||
sponsors: Sponsor[];
|
||||
};
|
||||
|
||||
export type Sponsors = {
|
||||
icons: Sponsor[];
|
||||
levels: Level[];
|
||||
};
|
||||
@@ -24,40 +24,39 @@
|
||||
|
||||
import yaml from 'yaml';
|
||||
|
||||
function namify(mapOrString) {
|
||||
if (typeof mapOrString == 'string') return {name: mapOrString};
|
||||
return mapOrString;
|
||||
import {Sponsor, Sponsors} from './sponsors.interfaces';
|
||||
|
||||
export function parse(mapOrString: Record<string, any> | string): Sponsor {
|
||||
if (typeof mapOrString == 'string') mapOrString = {name: mapOrString};
|
||||
return {
|
||||
name: mapOrString.name,
|
||||
description: mapOrString.description,
|
||||
url: mapOrString.url,
|
||||
onclick: mapOrString.url ? `window.onSponsorClick(${JSON.stringify(mapOrString.url)});` : '',
|
||||
img: mapOrString.img,
|
||||
icon: mapOrString.icon || mapOrString.img,
|
||||
icon_dark: mapOrString.icon_dark,
|
||||
topIcon: !!mapOrString.topIcon,
|
||||
sideBySide: !!mapOrString.sideBySide,
|
||||
priority: mapOrString.priority || 0,
|
||||
statsId: mapOrString.statsId,
|
||||
};
|
||||
}
|
||||
|
||||
function clickify(sponsor) {
|
||||
if (sponsor.url) {
|
||||
sponsor.onclick = `window.onSponsorClick(${JSON.stringify(sponsor)});`;
|
||||
}
|
||||
return sponsor;
|
||||
}
|
||||
|
||||
function getIconUrl(sponsor) {
|
||||
const icon = sponsor.icon || sponsor.img;
|
||||
if (icon) {
|
||||
sponsor.icon = icon;
|
||||
}
|
||||
return sponsor;
|
||||
}
|
||||
|
||||
function compareSponsors(lhs, rhs) {
|
||||
const lhsPrio = lhs.priority || 0;
|
||||
const rhsPrio = rhs.priority || 0;
|
||||
function compareSponsors(lhs: Sponsor, rhs: Sponsor): number {
|
||||
const lhsPrio = lhs.priority;
|
||||
const rhsPrio = rhs.priority;
|
||||
if (lhsPrio !== rhsPrio) return rhsPrio - lhsPrio;
|
||||
return lhs.name.localeCompare(rhs.name);
|
||||
}
|
||||
|
||||
export function loadSponsorsFromString(stringConfig) {
|
||||
export function loadSponsorsFromString(stringConfig: string): Sponsors {
|
||||
const sponsorConfig = yaml.parse(stringConfig);
|
||||
sponsorConfig.icons = [];
|
||||
for (const level of sponsorConfig.levels) {
|
||||
for (const required of ['name', 'description'])
|
||||
for (const required of ['name', 'description', 'sponsors'])
|
||||
if (!level[required]) throw new Error(`Level is missing '${required}'`);
|
||||
level.sponsors = level.sponsors.map(namify).map(clickify).map(getIconUrl).sort(compareSponsors);
|
||||
level.sponsors = level.sponsors.map(parse).sort(compareSponsors);
|
||||
sponsorConfig.icons.push(...level.sponsors.filter(sponsor => sponsor.topIcon && sponsor.icon));
|
||||
}
|
||||
return sponsorConfig;
|
||||
@@ -672,15 +672,15 @@ function start() {
|
||||
$('[name="editor-btn-toolbar"]').addClass('d-none');
|
||||
}
|
||||
|
||||
window.onSponsorClick = function (sponsor) {
|
||||
window.onSponsorClick = function (sponsorUrl) {
|
||||
analytics.proxy('send', {
|
||||
hitType: 'event',
|
||||
eventCategory: 'Sponsors',
|
||||
eventAction: 'click',
|
||||
eventLabel: sponsor.url,
|
||||
eventLabel: sponsorUrl,
|
||||
transport: 'beacon',
|
||||
});
|
||||
window.open(sponsor.url);
|
||||
window.open(sponsorUrl);
|
||||
};
|
||||
|
||||
if (options.pageloadUrl) {
|
||||
|
||||
@@ -22,9 +22,54 @@
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import {loadSponsorsFromString} from '../lib/sponsors';
|
||||
import {loadSponsorsFromString, parse} from '../lib/sponsors';
|
||||
|
||||
import {should} from './utils';
|
||||
|
||||
describe('Sponsors', () => {
|
||||
it('should expand names to objects', () => {
|
||||
parse('moo').name.should.eq('moo');
|
||||
});
|
||||
it('should handle just names', () => {
|
||||
parse({name: 'moo'}).name.should.eq('moo');
|
||||
});
|
||||
it('should default empty params', () => {
|
||||
const obj = parse('moo');
|
||||
should.equal(obj.description, undefined);
|
||||
should.equal(obj.url, undefined);
|
||||
obj.onclick.should.eq('');
|
||||
should.equal(obj.img, undefined);
|
||||
should.equal(obj.icon, undefined);
|
||||
should.equal(obj.icon_dark, undefined);
|
||||
obj.topIcon.should.be.false;
|
||||
obj.sideBySide.should.be.false;
|
||||
should.equal(obj.statsId, undefined);
|
||||
});
|
||||
it('should pass through descriptions', () => {
|
||||
parse({name: 'moo', description: 'desc'}).description.should.eq('desc');
|
||||
});
|
||||
it('should pass through icons', () => {
|
||||
parse({name: 'bob', icon: 'icon'}).icon.should.eq('icon');
|
||||
});
|
||||
it('should pick icons over images', () => {
|
||||
parse({name: 'bob', img: 'img', icon: 'icon'}).icon.should.eq('icon');
|
||||
});
|
||||
it('should pick icons if not img', () => {
|
||||
parse({name: 'bob', img: 'img'}).icon.should.eq('img');
|
||||
});
|
||||
it('should pick dark icons if specified', () => {
|
||||
parse({name: 'bob', icon: 'icon', icon_dark: 'icon_dark'}).icon_dark.should.eq('icon_dark');
|
||||
});
|
||||
it('should handle topIcons', () => {
|
||||
parse({name: 'bob', topIcon: true}).topIcon.should.be.true;
|
||||
});
|
||||
it('should handle clicks', () => {
|
||||
parse({
|
||||
name: 'bob',
|
||||
url: 'https://some.host/click',
|
||||
}).onclick.should.eq('window.onSponsorClick("https://some.host/click");');
|
||||
});
|
||||
|
||||
it('should load a simple example', () => {
|
||||
const sample = loadSponsorsFromString(`
|
||||
---
|
||||
@@ -49,19 +94,6 @@ levels:
|
||||
sample.levels[1].name.should.eq('Patreons');
|
||||
});
|
||||
|
||||
it('should expand names to objects', () => {
|
||||
const folks = loadSponsorsFromString(`
|
||||
---
|
||||
levels:
|
||||
- name: a
|
||||
description: d
|
||||
sponsors:
|
||||
- Just a string
|
||||
- name: An object
|
||||
`).levels[0].sponsors;
|
||||
folks.should.deep.equalInAnyOrder([{name: 'An object'}, {name: 'Just a string'}]);
|
||||
});
|
||||
|
||||
it('should sort sponsors by name', () => {
|
||||
const peeps = loadSponsorsFromString(`
|
||||
---
|
||||
@@ -74,7 +106,7 @@ levels:
|
||||
- A
|
||||
- B
|
||||
`).levels[0].sponsors;
|
||||
peeps.should.deep.equals([{name: 'A'}, {name: 'B'}, {name: 'C'}, {name: 'D'}]);
|
||||
peeps.map(sponsor => sponsor.name).should.deep.equals(['A', 'B', 'C', 'D']);
|
||||
});
|
||||
it('should sort sponsors by priority then name', () => {
|
||||
const peeps = loadSponsorsFromString(`
|
||||
@@ -90,44 +122,15 @@ levels:
|
||||
- name: B
|
||||
priority: 50
|
||||
`).levels[0].sponsors;
|
||||
peeps.should.deep.equals([
|
||||
{name: 'D', priority: 100},
|
||||
{name: 'B', priority: 50},
|
||||
{name: 'C', priority: 50},
|
||||
]);
|
||||
});
|
||||
it('should pick icon over img', () => {
|
||||
const things = loadSponsorsFromString(`
|
||||
---
|
||||
levels:
|
||||
- name: a
|
||||
description: d
|
||||
sponsors:
|
||||
- name: one
|
||||
img: image
|
||||
- name: two
|
||||
img: not_an_icon
|
||||
icon: icon
|
||||
`).levels[0].sponsors;
|
||||
things.should.deep.equalInAnyOrder([
|
||||
{name: 'one', icon: 'image', img: 'image'},
|
||||
{name: 'two', icon: 'icon', img: 'not_an_icon'},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should pick up dark icon if set', () => {
|
||||
const things = loadSponsorsFromString(`
|
||||
---
|
||||
levels:
|
||||
- name: a
|
||||
description: d
|
||||
sponsors:
|
||||
- name: batman
|
||||
img: not_an_icon
|
||||
icon: icon
|
||||
icon_dark: dark
|
||||
`).levels[0].sponsors;
|
||||
things.should.deep.equalInAnyOrder([{name: 'batman', icon: 'icon', icon_dark: 'dark', img: 'not_an_icon'}]);
|
||||
peeps
|
||||
.map(sponsor => {
|
||||
return {name: sponsor.name, priority: sponsor.priority};
|
||||
})
|
||||
.should.deep.equals([
|
||||
{name: 'D', priority: 100},
|
||||
{name: 'B', priority: 50},
|
||||
{name: 'C', priority: 50},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should pick out the top level icons', () => {
|
||||
@@ -154,9 +157,6 @@ levels:
|
||||
- name: five
|
||||
topIcon: true
|
||||
`).icons;
|
||||
icons.should.deep.equalInAnyOrder([
|
||||
{name: 'one', icon: 'pick_me', img: 'pick_me', topIcon: true},
|
||||
{name: 'four', icon: 'pick_me_also', img: 'pick_me_also', topIcon: true},
|
||||
]);
|
||||
icons.map(s => s.name).should.deep.equals(['one', 'four']);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user