DEV: show no icon if icon name is missing and log at error level (#31866)

On 1st April 2025, we start showing no icons if the icon name used is a
deprecated one and therefore no longer part of the svg set.

We'll continue showing the messages with the correct icon name to aid
correction of these names.

Console logging will now be done at an error level for such icons.

We retain the behaviour of raising an error for such icons in plugins
from svg_sprite.rb in test environments, but removed this from
icon-library.js as it's harder to test the actual expected behaviour of
returning the original icon now that it's not part of the deprecation
workflow. (sinon.stub doesn't work well here for `isTesting` - the
alternative would be to override the environment.js module with
`proxyquire`) In any case, once we remove the mapping logic, we won't be
raising errors in test environment either for this scenario.
This commit is contained in:
Kelv
2025-04-01 10:54:48 +08:00
committed by GitHub
parent 377a6554b9
commit 1c1d687283
6 changed files with 33 additions and 67 deletions

View File

@ -1,11 +1,7 @@
import { h } from "virtual-dom"; import { h } from "virtual-dom";
import attributeHook from "discourse/lib/attribute-hook"; import attributeHook from "discourse/lib/attribute-hook";
import deprecated from "discourse/lib/deprecated"; import deprecated from "discourse/lib/deprecated";
import { import { isDevelopment } from "discourse/lib/environment";
isDevelopment,
isRailsTesting,
isTesting,
} from "discourse/lib/environment";
import escape from "discourse/lib/escape"; import escape from "discourse/lib/escape";
import { i18n } from "discourse-i18n"; import { i18n } from "discourse-i18n";
@ -146,17 +142,13 @@ function handleDeprecatedIcon(id) {
newId = remapFromFA5(newId); newId = remapFromFA5(newId);
if (newId !== id) { if (newId !== id) {
deprecated( const error_msg = `Missing icon error: The icon name "${id}" has been removed and should be updated to "${newId}" in your code. More info at https://meta.discourse.org/t/325349.`;
`The icon name "${id}" has been updated to "${newId}". Please use the new name in your code. Old names will be removed in Q2 2025.`,
{ // eslint-disable-next-line no-console
id: "discourse.fontawesome-6-upgrade", console.error(error_msg);
url: "https://meta.discourse.org/t/325349",
raiseError: isTesting() || isRailsTesting(),
}
);
} }
return newId; return id;
} }
function warnIfMissing(id) { function warnIfMissing(id) {

View File

@ -19,7 +19,6 @@ export const CRITICAL_DEPRECATIONS = [
"discourse.header-widget-overrides", "discourse.header-widget-overrides",
"discourse.plugin-outlet-tag-name", "discourse.plugin-outlet-tag-name",
"discourse.post-menu-widget-overrides", "discourse.post-menu-widget-overrides",
"discourse.fontawesome-6-upgrade",
"discourse.add-flag-property", "discourse.add-flag-property",
"discourse.breadcrumbs.childCategories", "discourse.breadcrumbs.childCategories",
"discourse.breadcrumbs.firstCategory", "discourse.breadcrumbs.firstCategory",

View File

@ -1,15 +1,10 @@
import { setupTest } from "ember-qunit"; import { setupTest } from "ember-qunit";
import { module, test } from "qunit"; import { module, test } from "qunit";
import { withSilencedDeprecations } from "discourse/lib/deprecated";
import { import {
convertIconClass, convertIconClass,
iconHTML, iconHTML,
iconNode, iconNode,
} from "discourse/lib/icon-library"; } from "discourse/lib/icon-library";
import {
disableRaiseOnDeprecation,
enableRaiseOnDeprecation,
} from "discourse/tests/helpers/raise-on-deprecation";
module("Unit | Utility | icon-library", function (hooks) { module("Unit | Utility | icon-library", function (hooks) {
setupTest(hooks); setupTest(hooks);
@ -52,13 +47,9 @@ module("Unit | Utility | icon-library", function (hooks) {
}); });
test("fa5 remaps", function (assert) { test("fa5 remaps", function (assert) {
withSilencedDeprecations("discourse.fontawesome-6-upgrade", () => {
const adjustIcon = iconHTML("adjust"); const adjustIcon = iconHTML("adjust");
assert.true(adjustIcon.includes("d-icon-adjust"), "class is maintained"); assert.true(adjustIcon.includes("d-icon-adjust"), "class is maintained");
assert.true( assert.true(adjustIcon.includes('href="#adjust"'), "keeps original icon");
adjustIcon.includes('href="#circle-half-stroke"'),
"has remapped icon"
);
const farIcon = iconHTML("far-dot-circle"); const farIcon = iconHTML("far-dot-circle");
assert.true( assert.true(
@ -66,29 +57,8 @@ module("Unit | Utility | icon-library", function (hooks) {
"class is maintained" "class is maintained"
); );
assert.true( assert.true(
farIcon.includes('href="#far-circle-dot"'), farIcon.includes('href="#far-dot-circle"'),
"has remapped icon" "keeps original icon"
); );
}); });
}); });
test("fa5 remaps throws error", function (assert) {
disableRaiseOnDeprecation();
assert.throws(
() => {
iconHTML("adjust");
},
/Deprecation notice: The icon name "adjust" has been updated to "circle-half-stroke".*\[deprecation id: discourse\.fontawesome-6-upgrade\]/,
"throws an error if icon name is deprecated"
);
assert.throws(
() => {
iconHTML("far-dot-circle");
},
/Deprecation notice: The icon name "far-dot-circle" has been updated to "far-circle-dot".*\[deprecation id: discourse\.fontawesome-6-upgrade\]/,
"throws an error if icon name is deprecated"
);
enableRaiseOnDeprecation();
});
});

View File

@ -687,11 +687,12 @@ module DeprecatedIconHandler
new_name = remap_from_fa5(new_name) new_name = remap_from_fa5(new_name)
if icon_name != new_name if icon_name != new_name
Discourse.deprecate( error_msg =
"The icon `#{icon_name}` is deprecated. Use `#{new_name}` instead.", `Missing icon error: The icon name "#{icon_name}" has been removed and should be updated to "#{new_name}" in your code. More info at https://meta.discourse.org/t/325349.`
raise_error: Rails.env.test?,
) Rails.logger.error(error_msg)
return new_name
raise Discourse::MissingIconError.new(error_msg) if Rails.env.test?
end end
icon_name icon_name

View File

@ -117,6 +117,7 @@ module Discourse
class CommandError < RuntimeError class CommandError < RuntimeError
attr_reader :status, :stdout, :stderr attr_reader :status, :stdout, :stderr
def initialize(message, status: nil, stdout: nil, stderr: nil) def initialize(message, status: nil, stdout: nil, stderr: nil)
super(message) super(message)
@status = status @status = status
@ -305,6 +306,9 @@ module Discourse
class Deprecation < StandardError class Deprecation < StandardError
end end
class MissingIconError < StandardError
end
class ScssError < StandardError class ScssError < StandardError
end end

View File

@ -88,18 +88,18 @@ RSpec.describe SvgSprite do
it "strips whitespace when processing icons" do it "strips whitespace when processing icons" do
Fabricate(:badge, name: "Custom Icon Badge", icon: " fab fa-facebook-messenger ") Fabricate(:badge, name: "Custom Icon Badge", icon: " fab fa-facebook-messenger ")
expect(SvgSprite.all_icons).to include("fab-facebook-messenger") expect(SvgSprite.all_icons).to include("fab fa-facebook-messenger")
expect(SvgSprite.all_icons).not_to include(" fab-facebook-messenger ") expect(SvgSprite.all_icons).not_to include(" fab fa-facebook-messenger ")
end end
it "includes Font Awesome 5 icons from badges" do it "includes icons from badges" do
Fabricate(:badge, name: "Custom Icon Badge", icon: "far fa-building") Fabricate(:badge, name: "Custom Icon Badge", icon: "far fa-building")
expect(SvgSprite.all_icons).to include("far-building") expect(SvgSprite.all_icons).to include("far fa-building")
end end
it "raises an error in test for deprecated icons" do it "raises an error in test for deprecated icons" do
allow(Rails.env).to receive(:test?).and_return(true) allow(Rails.env).to receive(:test?).and_return(true)
expect { SvgSprite.search("fa-gamepad") }.to raise_error(Discourse::Deprecation) expect { SvgSprite.search("fa-gamepad") }.to raise_error(Discourse::MissingIconError)
end end
it "includes icons defined in theme settings" do it "includes icons defined in theme settings" do
@ -127,7 +127,7 @@ RSpec.describe SvgSprite do
# FA5 syntax # FA5 syntax
theme.update_setting(:custom_icon, "fab fa-bandcamp") theme.update_setting(:custom_icon, "fab fa-bandcamp")
theme.save! theme.save!
expect(SvgSprite.all_icons(theme.id)).to include("fab-bandcamp") expect(SvgSprite.all_icons(theme.id)).to include("fab fa-bandcamp")
# Internal Discourse syntax + multiple icons # Internal Discourse syntax + multiple icons
theme.update_setting(:custom_icon, "fab-android|dragon") theme.update_setting(:custom_icon, "fab-android|dragon")
@ -227,7 +227,7 @@ RSpec.describe SvgSprite do
DiscoursePluginRegistry.register_svg_icon "fab fa-bandcamp" DiscoursePluginRegistry.register_svg_icon "fab fa-bandcamp"
expect(SvgSprite.all_icons).to include("blender") expect(SvgSprite.all_icons).to include("blender")
expect(SvgSprite.all_icons).to include("fab-bandcamp") expect(SvgSprite.all_icons).to include("fab fa-bandcamp")
end end
it "includes Font Awesome icon from groups" do it "includes Font Awesome icon from groups" do