import QtQuick import QtTest import BiLauncher // Маленькие переиспользуемые компоненты: DarkCombo, LabelledField, // ProgressPanel, LoaderRow. TestCase { id: testCase name: "Components" width: 600 height: 400 visible: true when: windowShown Component { id: comboComponent; DarkCombo { width: 200; height: 32 } } Component { id: fieldComponent; LabelledField { width: 220 } } Component { id: panelComponent; ProgressPanel {} } Component { id: loaderRowComponent; LoaderRow { width: 300 } } // Подставной backend для LoaderRow: те же методы и сигнал, что у LauncherBackend. Component { id: fakeBackendComponent QtObject { property var versions: ({}) property bool loading: false property var refreshCalls: [] signal loaderVersionsChanged(string loaderKey, string gameVersion) function loaderVersions(key, game) { return versions[key + "/" + game] || [] } function refreshLoaderVersions(key, game) { refreshCalls.push(key + "/" + game) } function loaderVersionsLoading(key, game) { return loading } } } // --- DarkCombo ------------------------------------------------------------- function test_comboSelectsAndDisplays() { const combo = createTemporaryObject(comboComponent, testCase, { model: ["Alpha", "Beta", "Gamma"] }) verify(combo) compare(combo.count, 3) compare(combo.displayText, "Alpha") const activated = signalSpy.createObject(testCase, { target: combo, signalName: "activated" }) mouseClick(combo) tryVerify(() => combo.popup.opened) combo.currentIndex = 2 compare(combo.displayText, "Gamma") combo.popup.close() tryVerify(() => !combo.popup.visible) // Клавиатура: стрелки меняют выбор и шлют activated. combo.forceActiveFocus() keyClick(Qt.Key_Up) compare(combo.currentIndex, 1) compare(activated.count, 1) verify(combo.indicator.source.toString().length > 0) } // --- LabelledField ------------------------------------------------------- function test_labelledFieldAliasesAndSignal() { const field = createTemporaryObject(fieldComponent, testCase, { label: "Ник", placeholder: "Steve" }) verify(field) compare(field.children[0].text, "Ник") const input = field.children[1] compare(input.placeholderText, "Steve") const finished = signalSpy.createObject(testCase, { target: field, signalName: "editingFinished" }) input.forceActiveFocus() keyClick(Qt.Key_A) keyClick(Qt.Key_B) compare(field.text, "ab") keyClick(Qt.Key_Return) compare(finished.count, 1) field.text = "preset" compare(input.text, "preset") } // --- ProgressPanel ------------------------------------------------------- function test_progressPanelPercentAndCancel() { const panel = createTemporaryObject(panelComponent, testCase, { title: "1.20.1", status: "Libraries", fraction: -1 }) verify(panel) const texts = panel.children.filter(c => c.text !== undefined) const percent = texts.find(t => t.text === "…") verify(percent, "без известного итога показывается многоточие") panel.fraction = 0.426 compare(percent.text, "43%") panel.fraction = 1 compare(percent.text, "100%") // Подпись: detail важнее status. const detailText = texts.find(t => t.text === "Libraries") verify(detailText) panel.detail = "brigadier-1.1.8.jar" compare(detailText.text, "brigadier-1.1.8.jar") const cancel = signalSpy.createObject(testCase, { target: panel, signalName: "cancelRequested" }) mouseClick(panel, panel.width - 14, panel.height - 12) compare(cancel.count, 1) panel.cancellable = false mouseClick(panel, panel.width - 14, panel.height - 12) compare(cancel.count, 1, "крестик скрыт — отмены нет") } // --- LoaderRow ----------------------------------------------------------- function test_loaderRowFollowsBackend() { const backend = createTemporaryObject(fakeBackendComponent, testCase) backend.versions = { "fabric/1.20.1": [ { version: "0.16.10", label: "0.16.10", recommended: false, stable: true }, { version: "0.16.9", label: "0.16.9", recommended: false, stable: true } ] } const row = createTemporaryObject(loaderRowComponent, testCase, { backend: backend, loaderKey: "fabric", title: "Fabric Loader" }) verify(row) const changed = signalSpy.createObject(testCase, { target: row, signalName: "changed" }) // Без версии игры галочка недоступна, список пуст. compare(row.entries.length, 0) row.gameVersion = "1.20.1" compare(row.entries.length, 0, "пока галочка снята — версии не запрашиваются") // Сборка уже с Fabric: выбранная версия сохраняется, запрос обновления уходит. row.applyBuild("fabric", "0.16.9") verify(row.checked) compare(row.selectedVersion, "0.16.9") compare(row.entries.length, 2) verify(backend.refreshCalls.indexOf("fabric/1.20.1") >= 0) compare(changed.count, 0, "применение сохранённой сборки не считается правкой") // Каталог обновился и выбранной версии в нём больше нет — берётся первая. backend.versions = { "fabric/1.20.1": [ { version: "0.17.0", label: "0.17.0", recommended: true, stable: true } ] } backend.loaderVersionsChanged("fabric", "1.20.1") compare(row.selectedVersion, "0.17.0") compare(changed.count, 1) // Чужой лоадер в сборке — галочка снимается. row.applyBuild("forge", "47.4.0") verify(!row.checked) compare(row.selectedVersion, "") compare(row.entries.length, 0) // Смена версии игры сбрасывает выбор. row.applyBuild("fabric", "0.17.0") row.gameVersion = "1.19.4" compare(row.selectedVersion, "") } Component { id: signalSpy; SignalSpy {} } }