Files
qbit-cdn/src/test/java/com/kingsrook/qbits/cdn/CdnHelpBundleTest.java
T
james.maesandClaude Opus 5.5 79ae6264f8 fix: the qbit metadata version comes from the build, not a hardcoded constant
The producer read a literal version, so released artifacts reported a stale
or -SNAPSHOT version. qbit-cdn.properties (version=${project.version}) is
Maven-filtered and the producer loads it; tests assert producer == bundle ==
artifact version.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 01:22:59 -05:00

123 lines
6.6 KiB
Java

/*
* Copyright 2026 Kingsrook, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.kingsrook.qbits.cdn;
import java.net.URLClassLoader;
import java.nio.file.Path;
import java.util.Map;
import java.util.Set;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.kingsrook.qqq.backend.core.instances.QInstanceEnricher;
import com.kingsrook.qqq.backend.core.model.metadata.QBackendMetaData;
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
import com.kingsrook.qqq.backend.core.model.metadata.help.bundles.HelpBundleLayer;
import com.kingsrook.qqq.backend.core.model.metadata.help.bundles.HelpBundles;
import com.kingsrook.qqq.backend.core.modules.backend.implementations.memory.MemoryBackendModule;
import com.kingsrook.qqq.backend.core.testing.HelpBundleAssertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import static org.assertj.core.api.Assertions.assertThat;
/*******************************************************************************
** Coverage for shipped help and names bound from the host configuration.
*******************************************************************************/
class CdnHelpBundleTest
{
@TempDir
Path temporary;
/*******************************************************************************
** The resource covers all fixed metadata, without host objects or exclusions.
*******************************************************************************/
@Test
void shippedBundleIsComplete() throws Exception
{
QInstance instance = new QInstance();
instance.addBackend(new QBackendMetaData().withName("memory").withBackendType(MemoryBackendModule.class));
new CdnQBitProducer().withQBitConfig(new CdnQBitConfig().withBackendName("memory")).produce(instance);
// Core adds bulk CRUD processes during enrichment; those belong to core.
Set<String> ownedProcesses = Set.copyOf(instance.getProcesses().keySet());
Set<String> ownedWidgets = Set.copyOf(instance.getWidgets().keySet());
Set<String> ownedSources = Set.copyOf(instance.getPossibleValueSources().keySet());
new QInstanceEnricher(instance).enrich();
HelpBundleAssertions.forInstance(instance).bundles("help/qbit-cdn.yaml")
.owning(target -> target.name().startsWith("cdn")
&& (!target.kind().equals("process") || ownedProcesses.contains(target.name()))).assertComplete();
assertThat(instance.getTable("helpContent")).isNull();
var bundle = HelpBundles.of(instance).getBundles().get(0);
assertThat(bundle.getId()).isEqualTo("qbit-cdn");
assertThat(bundle.getVersion()).as("the help bundle carries the artifact version").isEqualTo(System.getProperty("qbit.artifactVersion")).isEqualTo(CdnQBitProducer.VERSION);
assertThat(bundle.getLayer()).isEqualTo(HelpBundleLayer.QBIT);
assertThat(bundle.getEntries()).extracting(entry -> entry.getKey()).doesNotHaveDuplicates();
// Core's gate does not require widgets or possible-value sources yet.
ownedWidgets.forEach(name -> assertThat(bundle.getEntries()).as(name)
.anyMatch(entry -> entry.getKey().equals("widget:" + name + ";slot:label")));
ownedSources.forEach(name -> assertThat(bundle.getEntries()).as(name)
.anyMatch(entry -> entry.getKey().equals("possibleValueSource:" + name + ";slot:help")));
}
/*******************************************************************************
** Check the registered bundle, including host-named actions and a renamed app,
** through the core gate using a temporary classpath resource.
*******************************************************************************/
@Test
void configuredBundleIsComplete() throws Exception
{
QInstance instance = CdnTestSupport.setUp();
var config = CdnRuntime.getConfig().withAppName("edgeConsole");
QInstance renamed = new QInstance();
instance.getBackends().values().forEach(renamed::addBackend);
renamed.addTable(instance.getTable("post"));
new CdnQBitProducer().withQBitConfig(config).produce(renamed);
Set<String> ownedProcesses = Set.copyOf(renamed.getProcesses().keySet());
new QInstanceEnricher(renamed).enrich();
var bundle = HelpBundles.of(renamed).getBundles().get(0);
assertThat(bundle.getEntries()).anyMatch(entry -> entry.getKey().equals("process:cdnPurge_post;slot:help")
&& entry.getContent().contains("Review the selected records"));
assertThat(bundle.getEntries()).anyMatch(entry -> entry.getKey().equals("app:edgeConsole;slot:help"));
assertThat(bundle.getEntries()).noneMatch(entry -> entry.getKey().startsWith("app:cdnAdmin;"));
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
mapper.writeValue(temporary.resolve("configured.yaml").toFile(), Map.of("bundle", bundle.getId(),
"version", bundle.getVersion(), "layer", bundle.getLayer(), "entries", bundle.getEntries()));
ClassLoader original = Thread.currentThread().getContextClassLoader();
try(URLClassLoader loader = new URLClassLoader(new java.net.URL[] { temporary.toUri().toURL() }, original))
{
Thread.currentThread().setContextClassLoader(loader);
HelpBundleAssertions.forInstance(renamed).bundles("configured.yaml")
.owning(target -> (target.name().startsWith("cdn") || target.name().equals("edgeConsole"))
&& (!target.kind().equals("process") || ownedProcesses.contains(target.name()))).assertComplete();
mapper.writeValue(temporary.resolve("host.yaml").toFile(), Map.of("bundle", "host", "version", "1",
"layer", "HOST", "entries", java.util.List.of(Map.of("key", "table:cdn_provider;slot:help", "summary", "Your host instructions."))));
HelpBundles.register(renamed, "host.yaml");
assertThat(HelpBundles.of(renamed).resolveWinningEntries()
.get(new HelpBundles.EntryKey("table:cdn_provider;slot:help", "ALL_SCREENS")).entry().getSummary())
.isEqualTo("Your host instructions.");
}
finally
{
Thread.currentThread().setContextClassLoader(original);
}
}
}