diff --git a/products.d/agama-products.changes b/products.d/agama-products.changes index afc802050b..ff8fe5409e 100644 --- a/products.d/agama-products.changes +++ b/products.d/agama-products.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Fri Jan 24 06:45:45 UTC 2025 - Imobach Gonzalez Sosa + +- Change the registration property in a product's definition to a + boolean (gh#agama-project/agama#1938). + ------------------------------------------------------------------- Thu Jan 23 10:43:32 UTC 2025 - Josef Reidinger diff --git a/products.d/sles_160.yaml b/products.d/sles_160.yaml index 821d1228cc..94f1da8670 100644 --- a/products.d/sles_160.yaml +++ b/products.d/sles_160.yaml @@ -1,6 +1,6 @@ id: SLES name: SUSE Linux Enterprise Server 16.0 Beta -registration: "mandatory" +registration: true version: "16-0" license: "license.beta" # ------------------------------------------------------------------------------ diff --git a/products.d/sles_sap_160.yaml b/products.d/sles_sap_160.yaml index 9218767354..305603c58d 100644 --- a/products.d/sles_sap_160.yaml +++ b/products.d/sles_sap_160.yaml @@ -1,7 +1,7 @@ id: SLES_SAP name: SUSE Linux Enterprise Server for SAP Applications 16.0 Beta archs: x86_64,aarch64,ppc -registration: "mandatory" +registration: true version: "16-0" license: "license.beta" # ------------------------------------------------------------------------------ diff --git a/rust/agama-lib/src/product/client.rs b/rust/agama-lib/src/product/client.rs index d125961217..4eac5e5e33 100644 --- a/rust/agama-lib/src/product/client.rs +++ b/rust/agama-lib/src/product/client.rs @@ -1,4 +1,4 @@ -// Copyright (c) [2024] SUSE LLC +// Copyright (c) [2024-2025] SUSE LLC // // All Rights Reserved. // @@ -43,7 +43,7 @@ pub struct Product { /// Product icon (e.g., "default.svg") pub icon: String, /// Registration requirement - pub registration: RegistrationRequirement, + pub registration: bool, /// License ID pub license: Option, } @@ -80,9 +80,7 @@ impl<'a> ProductClient<'a> { None => "default.svg", }; - let registration = get_property::(&data, "registration") - .map(|r| RegistrationRequirement::from_str(&r).unwrap_or_default()) - .unwrap_or_default(); + let registration = get_property::(&data, "registration").unwrap_or(false); let license = get_optional_property::(&data, "license").unwrap_or_default(); diff --git a/rust/agama-lib/src/proxies/issues.rs b/rust/agama-lib/src/proxies/issues.rs index 9d3ca0402f..87505aeb62 100644 --- a/rust/agama-lib/src/proxies/issues.rs +++ b/rust/agama-lib/src/proxies/issues.rs @@ -23,5 +23,5 @@ use zbus::proxy; pub trait Issues { /// All property #[zbus(property)] - fn all(&self) -> zbus::Result>; + fn all(&self) -> zbus::Result>; } diff --git a/rust/agama-server/src/web/common.rs b/rust/agama-server/src/web/common.rs index 332a798a48..5ceb5b799f 100644 --- a/rust/agama-server/src/web/common.rs +++ b/rust/agama-server/src/web/common.rs @@ -1,4 +1,4 @@ -// Copyright (c) [2024] SUSE LLC +// Copyright (c) [2024-2025] SUSE LLC // // All Rights Reserved. // @@ -325,11 +325,12 @@ pub struct Issue { details: Option, source: u32, severity: u32, + kind: String, } impl Issue { pub fn from_tuple( - (description, details, source, severity): (String, String, u32, u32), + (description, kind, details, source, severity): (String, String, String, u32, u32), ) -> Self { let details = if details.is_empty() { None @@ -339,6 +340,7 @@ impl Issue { Self { description, + kind, details, source, severity, diff --git a/rust/package/agama.changes b/rust/package/agama.changes index 77ea5d61e3..f40bf411c1 100644 --- a/rust/package/agama.changes +++ b/rust/package/agama.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Fri Jan 24 06:43:05 UTC 2025 - Imobach Gonzalez Sosa + +- Change the registration property in a product's definition to a + boolean (gh#agama-project/agama#1938). + ------------------------------------------------------------------- Wed Jan 22 14:49:56 UTC 2025 - Ladislav Slezák diff --git a/rust/package/agama.spec b/rust/package/agama.spec index 1a60b5f61d..a569ff0ff2 100644 --- a/rust/package/agama.spec +++ b/rust/package/agama.spec @@ -15,12 +15,6 @@ # Please submit bugfixes or comments via https://bugs.opensuse.org/ # -# Require at least 1.3GB RAM per each parallel job (the size is in MB) -%global _smp_tasksize_proc 1300 - -# Redefine the _smp_mflags macro so it takes the amount of RAM into account -%define _smp_mflags "-j%{getncpus:proc}" - Name: agama # This will be set by osc services, that will run after this. Version: 0 @@ -135,9 +129,6 @@ package contains a systemd service to run scripts when booting the installed sys # find vendor -type f -name \*.rs -exec chmod -x '{}' \; %build -# just for debugging failures with low memory -cat /proc/meminfo | head -n 3 - %{cargo_build} cargo run --package xtask -- manpages gzip out/man/* diff --git a/service/lib/agama/dbus/clients/with_issues.rb b/service/lib/agama/dbus/clients/with_issues.rb index cc7ba3ea4e..c4243dd80e 100644 --- a/service/lib/agama/dbus/clients/with_issues.rb +++ b/service/lib/agama/dbus/clients/with_issues.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -# Copyright (c) [2023] SUSE LLC +# Copyright (c) [2023-2025] SUSE LLC # # All Rights Reserved. # @@ -52,9 +52,10 @@ def issues_from(dbus_object) dbus_object[ISSUES_IFACE]["All"].map do |dbus_issue| Issue.new(dbus_issue[0], - details: dbus_issue[1], - source: sources[dbus_issue[2]], - severity: severities[dbus_issue[3]]) + kind: dbus_issue[1].to_sym, + details: dbus_issue[2], + source: sources[dbus_issue[3]], + severity: severities[dbus_issue[4]]) end end end diff --git a/service/lib/agama/dbus/interfaces/issues.rb b/service/lib/agama/dbus/interfaces/issues.rb index 09ccc17d9a..007a402b63 100644 --- a/service/lib/agama/dbus/interfaces/issues.rb +++ b/service/lib/agama/dbus/interfaces/issues.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -# Copyright (c) [2023] SUSE LLC +# Copyright (c) [2023-2025] SUSE LLC # # All Rights Reserved. # @@ -48,9 +48,9 @@ def dbus_issues else 0 end - severity = issue.severity == Agama::Issue::Severity::WARN ? 0 : 1 + severity = (issue.severity == Agama::Issue::Severity::WARN) ? 0 : 1 - [issue.description, issue.details.to_s, source, severity] + [issue.description, issue.kind.to_s, issue.details.to_s, source, severity] end end @@ -64,7 +64,7 @@ def self.included(base) base.class_eval do dbus_interface ISSUES_INTERFACE do # @see {#dbus_issues} - dbus_reader :dbus_issues, "a(ssuu)", dbus_name: "All" + dbus_reader :dbus_issues, "a(sssuu)", dbus_name: "All" end end end diff --git a/service/lib/agama/dbus/software/product.rb b/service/lib/agama/dbus/software/product.rb index 1642d49501..966f10dbca 100644 --- a/service/lib/agama/dbus/software/product.rb +++ b/service/lib/agama/dbus/software/product.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -# Copyright (c) [2023] SUSE LLC +# Copyright (c) [2023-2025] SUSE LLC # # All Rights Reserved. # @@ -180,7 +180,7 @@ def register(reg_code, email: nil) [1, "Product not selected yet"] elsif backend.registration.reg_code [2, "Product already registered"] - elsif backend.registration.requirement == Agama::Registration::Requirement::NO + elsif !backend.product.registration [3, "Product does not require registration"] else connect_result(first_error_code: 4) do @@ -254,6 +254,7 @@ def register_callbacks # software related issues. backend.registration.on_change { issues_properties_changed } backend.registration.on_change { registration_properties_changed } + backend.on_issues_change { issues_properties_changed } end def registration_properties_changed diff --git a/service/lib/agama/issue.rb b/service/lib/agama/issue.rb index 18630a4d29..0e698c0dae 100644 --- a/service/lib/agama/issue.rb +++ b/service/lib/agama/issue.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -# Copyright (c) [2023] SUSE LLC +# Copyright (c) [2023-2025] SUSE LLC # # All Rights Reserved. # @@ -55,6 +55,12 @@ class Issue # @return [Symbol] attr_reader :severity + # Kind of error + # + # It helps to identify the error without having to rely on the message + # @return [Symbol] + attr_reader :kind + # Defines possible sources module Source SYSTEM = :system @@ -73,8 +79,9 @@ module Severity # @param details [String, nil] # @param source [symbol, nil] # @param severity [symbol] - def initialize(description, details: "", source: nil, severity: Severity::WARN) + def initialize(description, kind: :generic, details: "", source: nil, severity: Severity::WARN) @description = description + @kind = kind @details = details @source = source @severity = severity diff --git a/service/lib/agama/software/manager.rb b/service/lib/agama/software/manager.rb index ddd415a735..b03cfc74f2 100644 --- a/service/lib/agama/software/manager.rb +++ b/service/lib/agama/software/manager.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -# Copyright (c) [2021-2024] SUSE LLC +# Copyright (c) [2021-2025] SUSE LLC # # All Rights Reserved. # @@ -589,6 +589,7 @@ def missing_product_issue # @return [Agama::Issue] def missing_registration_issue Issue.new(_("Product must be registered"), + kind: :missing_registration, source: Issue::Source::SYSTEM, severity: Issue::Severity::ERROR) end @@ -597,8 +598,17 @@ def missing_registration_issue # # @return [Boolean] def missing_registration? - registration.reg_code.nil? && - registration.requirement == Agama::Registration::Requirement::MANDATORY + return false unless product + + product.registration && missing_base_product? + end + + # Whether the base product is missing + # + # @return [Boolean] + def missing_base_product? + products = Y2Packager::Resolvable.find(kind: :product, name: product.name) + products.empty? end def pattern_exist?(pattern_name) diff --git a/service/lib/agama/software/product.rb b/service/lib/agama/software/product.rb index 2cd87acaca..615cd3e7dd 100644 --- a/service/lib/agama/software/product.rb +++ b/service/lib/agama/software/product.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -# Copyright (c) [2023] SUSE LLC +# Copyright (c) [2023-2025] SUSE LLC # # All Rights Reserved. # @@ -92,10 +92,9 @@ class Product # @return [Array] attr_accessor :user_patterns - # Determines if the product should be registered. + # Whether the registration is enabled for the product. # - # @see Agama::Registration::Requirement - # @return [String] + # @return [boolean] attr_accessor :registration # Product translations. @@ -126,7 +125,7 @@ def initialize(id) @optional_patterns = [] # nil = display all visible patterns, [] = display no patterns @user_patterns = nil - @registration = Agama::Registration::Requirement::NO + @registration = false @license = nil @translations = {} end diff --git a/service/lib/agama/software/product_builder.rb b/service/lib/agama/software/product_builder.rb index 34fb5f0a47..1f1888ee24 100644 --- a/service/lib/agama/software/product_builder.rb +++ b/service/lib/agama/software/product_builder.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -# Copyright (c) [2023] SUSE LLC +# Copyright (c) [2023-2025] SUSE LLC # # All Rights Reserved. # @@ -65,7 +65,7 @@ def initialize_product(id, data, attrs) product.name = data[:name] product.version = data[:version] product.icon = attrs["icon"] if attrs["icon"] - product.registration = attrs["registration"] if attrs["registration"] + product.registration = !!attrs["registration"] product.license = attrs["license"] if attrs["license"] product.version = attrs["version"] if attrs["version"] end diff --git a/service/package/rubygem-agama-yast.changes b/service/package/rubygem-agama-yast.changes index 475c103329..5a4202b075 100644 --- a/service/package/rubygem-agama-yast.changes +++ b/service/package/rubygem-agama-yast.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Fri Jan 24 06:42:00 UTC 2025 - Imobach Gonzalez Sosa + +- Use the availability of the base product to determine whether a + product requires to be registered (gh#agama-project/agama#1938). + ------------------------------------------------------------------- Tue Jan 21 19:11:04 UTC 2025 - Imobach Gonzalez Sosa diff --git a/service/test/agama/dbus/clients/with_issues_examples.rb b/service/test/agama/dbus/clients/with_issues_examples.rb index d409970358..508de6425a 100644 --- a/service/test/agama/dbus/clients/with_issues_examples.rb +++ b/service/test/agama/dbus/clients/with_issues_examples.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -# Copyright (c) [2023] SUSE LLC +# Copyright (c) [2023-2025] SUSE LLC # # All Rights Reserved. # @@ -37,36 +37,36 @@ end let(:root_node) do - instance_double(::DBus::Node, descendant_objects: [dbus_object1, dbus_object2, dbus_object3]) + instance_double(DBus::Node, descendant_objects: [dbus_object1, dbus_object2, dbus_object3]) end let(:dbus_object1) do - instance_double(::DBus::ProxyObject, + instance_double(DBus::ProxyObject, interfaces: ["org.opensuse.Agama1.Test", "org.opensuse.Agama1.Issues"]) end let(:dbus_object2) do - instance_double(::DBus::ProxyObject, interfaces: ["org.opensuse.Agama1.Test"]) + instance_double(DBus::ProxyObject, interfaces: ["org.opensuse.Agama1.Test"]) end let(:dbus_object3) do - instance_double(::DBus::ProxyObject, interfaces: ["org.opensuse.Agama1.Issues"]) + instance_double(DBus::ProxyObject, interfaces: ["org.opensuse.Agama1.Issues"]) end - let(:issues_interface1) { instance_double(::DBus::ProxyObjectInterface) } + let(:issues_interface1) { instance_double(DBus::ProxyObjectInterface) } - let(:issues_interface3) { instance_double(::DBus::ProxyObjectInterface) } + let(:issues_interface3) { instance_double(DBus::ProxyObjectInterface) } let(:issues1) do [ - ["Issue 1", "Details 1", 1, 0], - ["Issue 2", "Details 2", 2, 1] + ["Issue 1", "generic", "Details 1", 1, 0], + ["Issue 2", "generic", "Details 2", 2, 1] ] end let(:issues3) do [ - ["Issue 3", "Details 3", 1, 0] + ["Issue 3", "generic", "Details 3", 1, 0] ] end diff --git a/service/test/agama/dbus/interfaces/issues_test.rb b/service/test/agama/dbus/interfaces/issues_test.rb index 146e579d6d..6e10c3620d 100644 --- a/service/test/agama/dbus/interfaces/issues_test.rb +++ b/service/test/agama/dbus/interfaces/issues_test.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -# Copyright (c) [2023] SUSE LLC +# Copyright (c) [2023-2025] SUSE LLC # # All Rights Reserved. # @@ -24,7 +24,7 @@ require "agama/dbus/interfaces/issues" require "agama/issue" -class DBusObjectWithIssuesInterface < ::DBus::Object +class DBusObjectWithIssuesInterface < DBus::Object include Agama::DBus::Interfaces::Issues def initialize @@ -40,7 +40,8 @@ def issues Agama::Issue.new("Issue 2", details: "Details 2", source: Agama::Issue::Source::CONFIG, - severity: Agama::Issue::Severity::ERROR) + severity: Agama::Issue::Severity::ERROR, + kind: :missing_product) ] end end @@ -59,8 +60,8 @@ def issues result = subject.dbus_issues expect(result).to contain_exactly( - ["Issue 1", "Details 1", 1, 0], - ["Issue 2", "Details 2", 2, 1] + ["Issue 1", "generic", "Details 1", 1, 0], + ["Issue 2", "missing_product", "Details 2", 2, 1] ) end end diff --git a/service/test/agama/dbus/software/product_test.rb b/service/test/agama/dbus/software/product_test.rb index cadcdf8dae..dff355ab20 100644 --- a/service/test/agama/dbus/software/product_test.rb +++ b/service/test/agama/dbus/software/product_test.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -# Copyright (c) [2023] SUSE LLC +# Copyright (c) [2023-2025] SUSE LLC # # All Rights Reserved. # @@ -198,6 +198,7 @@ backend.select_product("Tumbleweed") allow(backend.product).to receive(:repositories).and_return(repositories) + allow(backend.product).to receive(:registration).and_return(true) end let(:repositories) { [] } @@ -215,6 +216,10 @@ context "if the product does not require registration" do let(:repositories) { ["https://repo"] } + before do + allow(backend.product).to receive(:registration).and_return(false) + end + it "returns result code 3 and description" do expect(subject.register("123XX432")).to contain_exactly(3, /not require registration/i) end diff --git a/service/test/agama/software/manager_test.rb b/service/test/agama/software/manager_test.rb index d090f027ce..e5583c017c 100644 --- a/service/test/agama/software/manager_test.rb +++ b/service/test/agama/software/manager_test.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -# Copyright (c) [2022-2024] SUSE LLC +# Copyright (c) [2022-2025] SUSE LLC # # All Rights Reserved. # @@ -543,28 +543,37 @@ context "and the product requires registration" do let(:product_id) { "test1" } + let(:product) do + Agama::Software::Product.new("test1").tap do |p| + p.registration = true + p.name = "test1" + end + end before do - allow(subject.registration).to receive(:reg_code).and_return(reg_code) + allow(subject).to receive(:product).and_return(product) + allow(Y2Packager::Resolvable).to receive(:find) + .with(kind: :product, name: product.name) + .and_return(resolvables) end - context "and the product is not registered" do - let(:reg_code) { nil } + context "and the base product is not available" do + let(:resolvables) { [] } it "contains a missing registration issue" do expect(subject.product_issues).to contain_exactly( an_object_having_attributes( - description: /product must be registered/i + kind: :missing_registration ) ) end - end - context "and the product is registered" do - let(:reg_code) { "1234XX5678" } + context "and the base product is available" do + let(:resolvables) { [instance_double("Product")] } - it "does not contain issues" do - expect(subject.product_issues).to be_empty + it "does not contain issues" do + expect(subject.product_issues).to be_empty + end end end end diff --git a/service/test/agama/software/product_builder_test.rb b/service/test/agama/software/product_builder_test.rb index 267d940141..560aef47a7 100644 --- a/service/test/agama/software/product_builder_test.rb +++ b/service/test/agama/software/product_builder_test.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -# Copyright (c) [2023] SUSE LLC +# Copyright (c) [2023-2025] SUSE LLC # # All Rights Reserved. # @@ -42,7 +42,7 @@ "name" => "Product Test 1", "description" => "This is a test product named Test 1", "version" => "1.0", - "registration" => "mandatory", + "registration" => true, "license" => "suse", "translations" => { "description" => { @@ -96,7 +96,7 @@ "description" => "This is a test product named Test 2", "archs" => "x86_64,aarch64", "version" => "2.0", - "registration" => "optional", + "registration" => true, "software" => { "mandatory_patterns" => ["pattern2-1"], "base_product" => "Test2" @@ -146,7 +146,7 @@ description: "This is a test product named Test 1", name: "Test1", version: "1.0", - registration: "mandatory", + registration: true, license: "suse", repositories: ["https://repos/test1/x86_64/product/"], mandatory_patterns: ["pattern1-1", "pattern1-2"], @@ -205,7 +205,7 @@ description: "This is a test product named Test 2", name: "Test2", version: "2.0", - registration: "optional", + registration: true, repositories: [], mandatory_patterns: ["pattern2-1"], optional_patterns: [], diff --git a/web/package/agama-web-ui.changes b/web/package/agama-web-ui.changes index 1195aab852..3fd2a18a68 100644 --- a/web/package/agama-web-ui.changes +++ b/web/package/agama-web-ui.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Fri Jan 24 06:43:52 UTC 2025 - Imobach Gonzalez Sosa + +- Use the "missing_registration" issue to determine whether to show + the registration alert (gh#agama-project/agama#1938). + ------------------------------------------------------------------- Tue Jan 21 09:44:08 UTC 2025 - Imobach Gonzalez Sosa diff --git a/web/src/App.test.tsx b/web/src/App.test.tsx index b106985e13..5984c42a9e 100644 --- a/web/src/App.test.tsx +++ b/web/src/App.test.tsx @@ -1,5 +1,5 @@ /* - * Copyright (c) [2022-2024] SUSE LLC + * Copyright (c) [2022-2025] SUSE LLC * * All Rights Reserved. * @@ -40,8 +40,8 @@ jest.mock("~/api/l10n", () => ({ updateConfig: jest.fn(), })); -const tumbleweed: Product = { id: "openSUSE", name: "openSUSE Tumbleweed", registration: "no" }; -const microos: Product = { id: "Leap Micro", name: "openSUSE Micro", registration: "no" }; +const tumbleweed: Product = { id: "openSUSE", name: "openSUSE Tumbleweed", registration: false }; +const microos: Product = { id: "Leap Micro", name: "openSUSE Micro", registration: false }; // list of available products let mockProducts: Product[]; diff --git a/web/src/components/core/ChangeProductLink.test.tsx b/web/src/components/core/ChangeProductLink.test.tsx index da97510ccd..7cd2368ada 100644 --- a/web/src/components/core/ChangeProductLink.test.tsx +++ b/web/src/components/core/ChangeProductLink.test.tsx @@ -1,5 +1,5 @@ /* - * Copyright (c) [2024] SUSE LLC + * Copyright (c) [2024-2025] SUSE LLC * * All Rights Reserved. * @@ -33,14 +33,14 @@ const tumbleweed: Product = { name: "openSUSE Tumbleweed", icon: "tumbleweed.svg", description: "Tumbleweed description...", - registration: "no", + registration: false, }; const microos: Product = { id: "MicroOS", name: "openSUSE MicroOS", icon: "MicroOS.svg", description: "MicroOS description", - registration: "no", + registration: false, }; let mockUseProduct: { products: Product[]; selectedProduct?: Product }; diff --git a/web/src/components/core/InstallButton.test.tsx b/web/src/components/core/InstallButton.test.tsx index 405be9e851..3aed25d65a 100644 --- a/web/src/components/core/InstallButton.test.tsx +++ b/web/src/components/core/InstallButton.test.tsx @@ -1,5 +1,5 @@ /* - * Copyright (c) [2022-2024] SUSE LLC + * Copyright (c) [2022-2025] SUSE LLC * * All Rights Reserved. * @@ -56,6 +56,7 @@ describe("InstallButton", () => { [ { description: "Fake Issue", + kind: "generic", source: 0, severity: 0, details: "Fake Issue details", diff --git a/web/src/components/core/IssuesDrawer.test.tsx b/web/src/components/core/IssuesDrawer.test.tsx index 4dfb14245a..3e030a3b17 100644 --- a/web/src/components/core/IssuesDrawer.test.tsx +++ b/web/src/components/core/IssuesDrawer.test.tsx @@ -1,5 +1,5 @@ /* - * Copyright (c) [2024] SUSE LLC + * Copyright (c) [2024-2025] SUSE LLC * * All Rights Reserved. * @@ -63,6 +63,7 @@ describe("IssuesDrawer", () => { [ { description: "Registration Fake Issue", + kind: "generic", source: 0, severity: 0, details: "Registration Fake Issue details", @@ -71,6 +72,7 @@ describe("IssuesDrawer", () => { [ { description: "Software Fake Issue", + kind: "generic", source: 0, severity: 0, details: "Software Fake Issue details", @@ -79,12 +81,14 @@ describe("IssuesDrawer", () => { [ { description: "Storage Fake Issue 1", + kind: "generic", source: 0, severity: 0, details: "Storage Fake Issue 1 details", }, { description: "Storage Fake Issue 2", + kind: "generic", source: 0, severity: 0, details: "Storage Fake Issue 2 details", @@ -93,6 +97,7 @@ describe("IssuesDrawer", () => { [ { description: "Users Fake Issue", + kind: "generic", source: 0, severity: 0, details: "Users Fake Issue details", diff --git a/web/src/components/layout/Header.test.tsx b/web/src/components/layout/Header.test.tsx index bd34ec37b8..cf6067a1b3 100644 --- a/web/src/components/layout/Header.test.tsx +++ b/web/src/components/layout/Header.test.tsx @@ -1,5 +1,5 @@ /* - * Copyright (c) [2024] SUSE LLC + * Copyright (c) [2024-2025] SUSE LLC * * All Rights Reserved. * @@ -31,14 +31,14 @@ const tumbleweed: Product = { id: "Tumbleweed", name: "openSUSE Tumbleweed", description: "Tumbleweed description...", - registration: "no", + registration: false, }; const microos: Product = { id: "MicroOS", name: "openSUSE MicroOS", description: "MicroOS description", - registration: "no", + registration: false, }; let phase: InstallationPhase; diff --git a/web/src/components/layout/Sidebar.test.tsx b/web/src/components/layout/Sidebar.test.tsx index fa094548cc..619f55c1e2 100644 --- a/web/src/components/layout/Sidebar.test.tsx +++ b/web/src/components/layout/Sidebar.test.tsx @@ -1,5 +1,5 @@ /* - * Copyright (c) [2024] SUSE LLC + * Copyright (c) [2024-2025] SUSE LLC * * All Rights Reserved. * @@ -32,13 +32,13 @@ jest.mock("~/components/core/ChangeProductLink", () => () =>
ChangeProductL const tw: Product = { id: "Tumbleweed", name: "openSUSE Tumbleweed", - registration: "no", + registration: false, }; const sle: Product = { id: "sle", name: "SLE", - registration: "mandatory", + registration: true, }; let selectedProduct: Product; diff --git a/web/src/components/layout/Sidebar.tsx b/web/src/components/layout/Sidebar.tsx index 5d446130d9..a36d4c32d9 100644 --- a/web/src/components/layout/Sidebar.tsx +++ b/web/src/components/layout/Sidebar.tsx @@ -1,5 +1,5 @@ /* - * Copyright (c) [2024] SUSE LLC + * Copyright (c) [2024-2025] SUSE LLC * * All Rights Reserved. * @@ -34,7 +34,7 @@ const MainNavigation = (): React.ReactNode => { const links = rootRoutes().map((r) => { if (!r.handle) return null; - if (r.handle.needsRegistrableProduct && product.registration === "no") return null; + if (r.handle.needsRegistrableProduct && !product.registration) return null; // eslint-disable-next-line agama-i18n/string-literals const name = _(r.handle.name); diff --git a/web/src/components/product/LicenseDialog.test.tsx b/web/src/components/product/LicenseDialog.test.tsx index 4cd3ead200..6ea976502a 100644 --- a/web/src/components/product/LicenseDialog.test.tsx +++ b/web/src/components/product/LicenseDialog.test.tsx @@ -32,7 +32,7 @@ const sle: Product = { name: "SUSE Linux Enterprise", icon: "sle.svg", description: "SLE description", - registration: "mandatory", + registration: true, license: "license.sle", }; diff --git a/web/src/components/product/ProductRegistrationAlert.test.tsx b/web/src/components/product/ProductRegistrationAlert.test.tsx index 856e47737a..5fd2d828e5 100644 --- a/web/src/components/product/ProductRegistrationAlert.test.tsx +++ b/web/src/components/product/ProductRegistrationAlert.test.tsx @@ -1,5 +1,5 @@ /* - * Copyright (c) [2024] SUSE LLC + * Copyright (c) [2024-2025] SUSE LLC * * All Rights Reserved. * @@ -24,30 +24,30 @@ import React from "react"; import { screen } from "@testing-library/react"; import { installerRender, mockRoutes } from "~/test-utils"; import ProductRegistrationAlert from "./ProductRegistrationAlert"; -import { Product, RegistrationInfo } from "~/types/software"; -import { useProduct, useRegistration } from "~/queries/software"; +import { Product } from "~/types/software"; +import { useProduct } from "~/queries/software"; +import { useIssues } from "~/queries/issues"; import { PRODUCT, REGISTRATION, ROOT, USER } from "~/routes/paths"; +import { Issue } from "~/types/issues"; jest.mock("~/components/core/ChangeProductLink", () => () =>
ChangeProductLink Mock
); const tw: Product = { id: "Tumbleweed", name: "openSUSE Tumbleweed", - registration: "no", + registration: false, }; const sle: Product = { id: "sle", name: "SLE", - registration: "mandatory", + registration: true, }; let selectedProduct: Product; -let registrationInfoMock: RegistrationInfo; jest.mock("~/queries/software", () => ({ ...jest.requireActual("~/queries/software"), - useRegistration: (): ReturnType => registrationInfoMock, useProduct: (): ReturnType => { return { products: [tw, sle], @@ -56,6 +56,20 @@ jest.mock("~/queries/software", () => ({ }, })); +let issues: Issue[] = []; +const registrationIssue: Issue = { + description: "Product must be registered", + details: "", + kind: "missing_registration", + source: 0, + severity: 0, +}; + +jest.mock("~/queries/issues", () => ({ + ...jest.requireActual("~/queries/issues"), + useIssues: (): ReturnType => issues, +})); + const rendersNothingInSomePaths = () => { describe.each([ ["login", ROOT.login], @@ -77,10 +91,10 @@ const rendersNothingInSomePaths = () => { }; describe("ProductRegistrationAlert", () => { - describe("when product is registrable and registration code is not set", () => { + describe("when the registration is missing", () => { beforeEach(() => { + issues = [registrationIssue]; selectedProduct = sle; - registrationInfoMock = { key: "", email: "" }; }); rendersNothingInSomePaths(); @@ -109,21 +123,10 @@ describe("ProductRegistrationAlert", () => { }); }); - describe("when product is registrable and registration code is already set", () => { + describe("when the registration is not needed", () => { beforeEach(() => { + issues = []; selectedProduct = sle; - registrationInfoMock = { key: "INTERNAL-USE-ONLY-1234-5678", email: "" }; - }); - - it("renders nothing", () => { - const { container } = installerRender(); - expect(container).toBeEmptyDOMElement(); - }); - }); - - describe("when product is not registrable", () => { - beforeEach(() => { - selectedProduct = tw; }); it("renders nothing", () => { diff --git a/web/src/components/product/ProductRegistrationAlert.tsx b/web/src/components/product/ProductRegistrationAlert.tsx index 4693a969db..403735be99 100644 --- a/web/src/components/product/ProductRegistrationAlert.tsx +++ b/web/src/components/product/ProductRegistrationAlert.tsx @@ -1,5 +1,5 @@ /* - * Copyright (c) [2023-2024] SUSE LLC + * Copyright (c) [2023-2025] SUSE LLC * * All Rights Reserved. * @@ -24,11 +24,11 @@ import React from "react"; import { Alert } from "@patternfly/react-core"; import { useLocation } from "react-router-dom"; import { Link } from "~/components/core"; -import { useProduct, useRegistration } from "~/queries/software"; +import { useProduct } from "~/queries/software"; import { REGISTRATION, SUPPORTIVE_PATHS } from "~/routes/paths"; -import { isEmpty } from "~/utils"; import { _ } from "~/i18n"; import { sprintf } from "sprintf-js"; +import { useIssues } from "~/queries/issues"; const LinkToRegistration = () => { const location = useLocation(); @@ -45,12 +45,13 @@ const LinkToRegistration = () => { export default function ProductRegistrationAlert() { const location = useLocation(); const { selectedProduct: product } = useProduct(); - const registration = useRegistration(); + const issues = useIssues("product"); + const registrationRequired = issues.find((i) => i.kind === "missing_registration"); // NOTE: it shouldn't be mounted in these paths, but let's prevent rendering // if so just in case. if (SUPPORTIVE_PATHS.includes(location.pathname)) return; - if (["no", undefined].includes(product.registration) || !isEmpty(registration.key)) return; + if (!registrationRequired) return; return ( diff --git a/web/src/components/product/ProductRegistrationPage.test.tsx b/web/src/components/product/ProductRegistrationPage.test.tsx index c83d411d35..b493ecf374 100644 --- a/web/src/components/product/ProductRegistrationPage.test.tsx +++ b/web/src/components/product/ProductRegistrationPage.test.tsx @@ -1,5 +1,5 @@ /* - * Copyright (c) [2024] SUSE LLC + * Copyright (c) [2024-2025] SUSE LLC * * All Rights Reserved. * @@ -30,19 +30,23 @@ import { useProduct, useRegistration } from "~/queries/software"; const tw: Product = { id: "Tumbleweed", name: "openSUSE Tumbleweed", - registration: "no", + registration: false, }; const sle: Product = { id: "sle", name: "SLE", - registration: "mandatory", + registration: true, }; let selectedProduct: Product; let registrationInfoMock: RegistrationInfo; const registerMutationMock = jest.fn(); +jest.mock("~/components/product/ProductRegistrationAlert", () => () => ( +
ProductRegistrationAlert Mock
+)); + jest.mock("~/queries/software", () => ({ ...jest.requireActual("~/queries/software"), useRegisterMutation: () => ({ mutate: registerMutationMock }), @@ -74,11 +78,6 @@ describe("ProductRegistrationPage", () => { registrationInfoMock = { key: "", email: "" }; }); - it("renders ProductRegistrationAlert component", () => { - installerRender(); - screen.getByText("Warning alert:"); - }); - it("renders a form to allow user registering the product", async () => { const { user } = installerRender(); const registrationCodeInput = screen.getByLabelText("Registration code"); @@ -107,11 +106,6 @@ describe("ProductRegistrationPage", () => { registrationInfoMock = { key: "INTERNAL-USE-ONLY-1234-5678", email: "example@company.test" }; }); - it("does not render ProductRegistrationAlert component", () => { - installerRender(); - expect(screen.queryByText("Warning alert:")).toBeNull(); - }); - it("renders registration information with code partially hidden", async () => { const { user } = installerRender(); const visibilityCodeToggler = screen.getByRole("button", { name: "Show" }); @@ -125,42 +119,5 @@ describe("ProductRegistrationPage", () => { expect(screen.queryByText("INTERNAL-USE-ONLY-1234-5678")).toBeNull(); screen.getByText(/\*?5678/); }); - - // describe("but at registration path already", () => { - // beforeEach(() => { - // mockRoutes(REGISTRATION.root); - // }); - // - // it("does not render the link to registration", () => { - // installerRender(); - // screen.getByRole("heading", { - // name: /Warning alert:.*must be registered/, - // }); - // expect(screen.queryAllByRole("link")).toEqual([]); - // }); - // }); - // }); - // - // describe("when product is registrable and registration code is already set", () => { - // beforeEach(() => { - // selectedProduct = sle; - // registrationInfoMock = { key: "INTERNAL-USE-ONLY-1234-5678", email: "" }; - // }); - // - // it("renders nothing", () => { - // const { container } = installerRender(); - // expect(container).toBeEmptyDOMElement(); - // }); - // }); - // - // describe("when product is not registrable", () => { - // beforeEach(() => { - // selectedProduct = tw; - // }); - // - // it("renders nothing", () => { - // const { container } = installerRender(); - // expect(container).toBeEmptyDOMElement(); - // }); }); }); diff --git a/web/src/components/product/ProductRegistrationPage.tsx b/web/src/components/product/ProductRegistrationPage.tsx index 2aa23f4f8e..dd6ba5d778 100644 --- a/web/src/components/product/ProductRegistrationPage.tsx +++ b/web/src/components/product/ProductRegistrationPage.tsx @@ -1,5 +1,5 @@ /* - * Copyright (c) [2023-2024] SUSE LLC + * Copyright (c) [2023-2025] SUSE LLC * * All Rights Reserved. * @@ -146,7 +146,7 @@ export default function ProductRegistrationPage() { const registration = useRegistration(); // TODO: render something meaningful instead? "Product not registrable"? - if (product.registration === "no") return; + if (!product.registration) return; return ( diff --git a/web/src/components/product/ProductSelectionPage.test.tsx b/web/src/components/product/ProductSelectionPage.test.tsx index a27b5b06a8..72b7dbf205 100644 --- a/web/src/components/product/ProductSelectionPage.test.tsx +++ b/web/src/components/product/ProductSelectionPage.test.tsx @@ -38,7 +38,7 @@ const tumbleweed: Product = { name: "openSUSE Tumbleweed", icon: "tumbleweed.svg", description: "Tumbleweed description...", - registration: "no", + registration: false, }; const microOs: Product = { @@ -46,7 +46,7 @@ const microOs: Product = { name: "openSUSE MicroOS", icon: "microos.svg", description: "MicroOS description", - registration: "no", + registration: false, license: "fake.license", }; diff --git a/web/src/components/product/ProductSelectionProgress.test.tsx b/web/src/components/product/ProductSelectionProgress.test.tsx index 0171fe9bc0..2101bbf43f 100644 --- a/web/src/components/product/ProductSelectionProgress.test.tsx +++ b/web/src/components/product/ProductSelectionProgress.test.tsx @@ -30,7 +30,7 @@ import { Product } from "~/types/software"; jest.mock("~/components/core/ProgressReport", () => () =>
ProgressReport Mock
); let isBusy = false; -const tumbleweed: Product = { id: "openSUSE", name: "openSUSE Tumbleweed", registration: "no" }; +const tumbleweed: Product = { id: "openSUSE", name: "openSUSE Tumbleweed", registration: false }; jest.mock("~/queries/status", () => ({ ...jest.requireActual("~/queries/status"), diff --git a/web/src/types/issues.ts b/web/src/types/issues.ts index 7cfee8dd82..e34031c8e3 100644 --- a/web/src/types/issues.ts +++ b/web/src/types/issues.ts @@ -1,5 +1,5 @@ /* - * Copyright (c) [2024] SUSE LLC + * Copyright (c) [2024-2025] SUSE LLC * * All Rights Reserved. * @@ -57,6 +57,8 @@ enum IssueSeverity { type Issue = { /** Issue description */ description: string; + /** Issue kind **/ + kind: string; /** Issue details. It is not mandatory. */ details: string | undefined; /** Where the issue comes from */ diff --git a/web/src/types/software.ts b/web/src/types/software.ts index ea9337a537..3791e9cfc2 100644 --- a/web/src/types/software.ts +++ b/web/src/types/software.ts @@ -1,5 +1,5 @@ /* - * Copyright (c) [2024] SUSE LLC + * Copyright (c) [2024-2025] SUSE LLC * * All Rights Reserved. * @@ -42,7 +42,7 @@ type Product = { /** Product icon (e.g., "default.svg") */ icon?: string; /** If product is registrable or not */ - registration: "no" | "optional" | "mandatory"; + registration: boolean; /** The product license id, if any */ license?: string; };