fix: several merge messes
This commit is contained in:
parent
b823d8d21b
commit
e63094e8e8
|
|
@ -52,6 +52,10 @@
|
|||
|
||||
<script setup>
|
||||
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
||||
import {
|
||||
choiceDisplayLabel,
|
||||
syncStateFromModelValue
|
||||
} from './choiceComboboxHelpers.js'
|
||||
|
||||
const props = defineProps({
|
||||
id: {
|
||||
|
|
@ -117,23 +121,23 @@ const filteredChoices = computed(() => {
|
|||
})
|
||||
})
|
||||
|
||||
watch(() => props.modelValue, () => {
|
||||
watch([() => props.modelValue, () => props.choices], () => {
|
||||
if (!isOpen.value) {
|
||||
query.value = selectedLabel()
|
||||
syncFromModelValue()
|
||||
}
|
||||
}, { immediate: true })
|
||||
|
||||
function choiceLabel(choice) {
|
||||
return choice.title || choice.value
|
||||
return choiceDisplayLabel(choice)
|
||||
}
|
||||
|
||||
function selectedLabel() {
|
||||
const match = props.choices.find(choice => choice.value === props.modelValue)
|
||||
if (!match) {
|
||||
return props.modelValue || ''
|
||||
}
|
||||
function syncFromModelValue() {
|
||||
const next = syncStateFromModelValue(props.choices, props.modelValue)
|
||||
query.value = next.query
|
||||
|
||||
return choiceLabel(match)
|
||||
if (next.modelValue !== props.modelValue) {
|
||||
emitValue(next.modelValue)
|
||||
}
|
||||
}
|
||||
|
||||
function openList() {
|
||||
|
|
@ -144,7 +148,7 @@ function openList() {
|
|||
|
||||
function closeList() {
|
||||
isOpen.value = false
|
||||
query.value = selectedLabel()
|
||||
syncFromModelValue()
|
||||
}
|
||||
|
||||
function emitValue(value) {
|
||||
|
|
@ -153,11 +157,15 @@ function emitValue(value) {
|
|||
|
||||
function selectChoice(choice) {
|
||||
emitValue(choice.value)
|
||||
closeList()
|
||||
query.value = choiceLabel(choice)
|
||||
isOpen.value = false
|
||||
}
|
||||
|
||||
function handleFocus() {
|
||||
query.value = isOpen.value ? query.value : selectedLabel()
|
||||
if (!isOpen.value) {
|
||||
syncFromModelValue()
|
||||
}
|
||||
|
||||
openList()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
export function findSelectedChoice (choices, modelValue) {
|
||||
if (!modelValue) {
|
||||
return null
|
||||
}
|
||||
|
||||
return choices.find(choice => choice.value === modelValue) ?? null
|
||||
}
|
||||
|
||||
export function choiceDisplayLabel (choice) {
|
||||
return choice.title || choice.value
|
||||
}
|
||||
|
||||
export function displayLabelForModelValue (choices, modelValue) {
|
||||
const match = findSelectedChoice(choices, modelValue)
|
||||
return match ? choiceDisplayLabel(match) : ''
|
||||
}
|
||||
|
||||
export function normalizedModelValue (choices, modelValue) {
|
||||
if (!modelValue) {
|
||||
return ''
|
||||
}
|
||||
|
||||
return findSelectedChoice(choices, modelValue) ? modelValue : ''
|
||||
}
|
||||
|
||||
export function syncStateFromModelValue (choices, modelValue) {
|
||||
const normalizedValue = normalizedModelValue(choices, modelValue)
|
||||
|
||||
return {
|
||||
query: displayLabelForModelValue(choices, normalizedValue),
|
||||
modelValue: normalizedValue
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
import test from 'node:test'
|
||||
import assert from 'node:assert/strict'
|
||||
import {
|
||||
displayLabelForModelValue,
|
||||
normalizedModelValue,
|
||||
syncStateFromModelValue
|
||||
} from './choiceComboboxHelpers.js'
|
||||
|
||||
const choices = [
|
||||
{ title: 'Production', value: 'prod' },
|
||||
{ title: 'Staging', value: 'stage' }
|
||||
]
|
||||
|
||||
test('displayLabelForModelValue returns the choice label for valid values', () => {
|
||||
assert.equal(displayLabelForModelValue(choices, 'prod'), 'Production')
|
||||
})
|
||||
|
||||
test('displayLabelForModelValue clears invalid enum values instead of echoing them', () => {
|
||||
assert.equal(displayLabelForModelValue(choices, 'missing'), '')
|
||||
})
|
||||
|
||||
test('normalizedModelValue keeps valid values and clears invalid ones', () => {
|
||||
assert.equal(normalizedModelValue(choices, 'stage'), 'stage')
|
||||
assert.equal(normalizedModelValue(choices, 'missing'), '')
|
||||
assert.equal(normalizedModelValue(choices, ''), '')
|
||||
})
|
||||
|
||||
test('syncStateFromModelValue clears invalid selections for closed-state sync', () => {
|
||||
assert.deepEqual(syncStateFromModelValue(choices, 'missing'), {
|
||||
query: '',
|
||||
modelValue: ''
|
||||
})
|
||||
})
|
||||
|
||||
test('syncStateFromModelValue preserves valid selections for closed-state sync', () => {
|
||||
assert.deepEqual(syncStateFromModelValue(choices, 'stage'), {
|
||||
query: 'Staging',
|
||||
modelValue: 'stage'
|
||||
})
|
||||
})
|
||||
|
|
@ -5,6 +5,8 @@ import {
|
|||
getRootAndWait,
|
||||
getActionButtons,
|
||||
takeScreenshotOnFailure,
|
||||
waitForArgumentFormPage,
|
||||
waitForArgumentFormReady,
|
||||
} from '../../lib/elements.js'
|
||||
|
||||
|
||||
|
|
@ -46,11 +48,13 @@ describe('config: multipleDropdowns', function () {
|
|||
|
||||
await button.click()
|
||||
|
||||
// Wait for navigation to argument form page
|
||||
await webdriver.wait(new Condition('wait for argument form page', async () => {
|
||||
const url = await webdriver.getCurrentUrl()
|
||||
return url.includes('/actionBinding/') && url.includes('/argumentForm')
|
||||
}), 8000)
|
||||
await waitForArgumentFormPage(8000)
|
||||
await waitForArgumentFormReady(10000)
|
||||
|
||||
await webdriver.wait(new Condition('wait for choice comboboxes', async () => {
|
||||
const boxes = await webdriver.findElements(By.css('main .choice-combobox'))
|
||||
return boxes.length >= 2
|
||||
}), 10000)
|
||||
|
||||
const comboboxes = await webdriver.findElements(By.css('main .choice-combobox'))
|
||||
|
||||
|
|
|
|||
|
|
@ -20,9 +20,7 @@ compile-x64-lin:
|
|||
go env -u GOOS
|
||||
|
||||
compile-x64-win: windows-resources
|
||||
go env -w GOOS=windows GOARCH=amd64
|
||||
go build -o OliveTin.exe
|
||||
go env -u GOOS GOARCH
|
||||
GOOS=windows GOARCH=amd64 go build -o OliveTin.exe
|
||||
|
||||
windows-resources:
|
||||
$(MAKE) -wC .. windows-resources
|
||||
|
|
|
|||
|
|
@ -89,29 +89,39 @@ var envConfigTests = []struct {
|
|||
}},
|
||||
}
|
||||
|
||||
func setTestEnvInput(t *testing.T, input string) {
|
||||
t.Helper()
|
||||
if input != "" {
|
||||
if err := os.Setenv("INPUT", input); err != nil {
|
||||
t.Fatalf("Setenv INPUT: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if err := os.Unsetenv("INPUT"); err != nil {
|
||||
t.Fatalf("Unsetenv INPUT: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func loadConfigFromYAML(t *testing.T, yamlStr string, cfg *Config) bool {
|
||||
t.Helper()
|
||||
k := koanf.New(".")
|
||||
if err := k.Load(rawbytes.Provider([]byte(yamlStr)), yaml.Parser()); err != nil {
|
||||
t.Errorf("Error loading YAML: %v", err)
|
||||
return false
|
||||
}
|
||||
return unmarshalRoot(k, cfg)
|
||||
}
|
||||
|
||||
func TestEnvInConfig(t *testing.T) {
|
||||
for _, tt := range envConfigTests {
|
||||
cfg := DefaultConfig()
|
||||
setIfNotEmpty("INPUT", tt.input)
|
||||
k := koanf.New(".")
|
||||
err := k.Load(rawbytes.Provider([]byte(tt.yaml)), yaml.Parser())
|
||||
if err != nil {
|
||||
t.Errorf("Error loading YAML: %v", err)
|
||||
continue
|
||||
}
|
||||
if !unmarshalRoot(k, cfg) {
|
||||
setTestEnvInput(t, tt.input)
|
||||
if !loadConfigFromYAML(t, tt.yaml, cfg) {
|
||||
t.Errorf("Error unmarshalling config for env=%q", tt.input)
|
||||
continue
|
||||
}
|
||||
field := tt.selector(cfg)
|
||||
assert.Equal(t, tt.output, field,
|
||||
"Unmarshaled config field doesn't match expected value: env=%q", tt.input)
|
||||
os.Unsetenv("INPUT")
|
||||
}
|
||||
}
|
||||
|
||||
func setIfNotEmpty(key, val string) {
|
||||
if val != "" {
|
||||
os.Setenv(key, val)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ normalize_msi_version() {
|
|||
local raw="${1#v}"
|
||||
raw="${raw%%-*}"
|
||||
if [[ ! "${raw}" =~ ^[0-9]+(\.[0-9]+){0,3}$ ]]; then
|
||||
echo "0.0.0"
|
||||
return
|
||||
echo "Invalid MSI version (expected major[.minor[.patch[.build]]]): ${1}" >&2
|
||||
return 1
|
||||
fi
|
||||
local -a parts=()
|
||||
IFS='.' read -r -a parts <<<"${raw}"
|
||||
|
|
@ -43,7 +43,7 @@ if [[ -z "${VERSION}" ]]; then
|
|||
echo "Could not determine release version; set VERSION explicitly" >&2
|
||||
exit 1
|
||||
fi
|
||||
MSI_VERSION="$(normalize_msi_version "${VERSION}")"
|
||||
MSI_VERSION="$(normalize_msi_version "${VERSION}")" || exit 1
|
||||
|
||||
STAGING="$(mktemp -d)"
|
||||
APP_STAGING="$(mktemp -d)"
|
||||
|
|
|
|||
|
|
@ -37,14 +37,14 @@ normalize_windows_version() {
|
|||
}
|
||||
|
||||
resolve_version() {
|
||||
if [[ -n "${VERSION:-}" ]]; then
|
||||
echo "${VERSION}"
|
||||
return
|
||||
fi
|
||||
if [[ $# -gt 0 && -n "${1:-}" ]]; then
|
||||
echo "${1}"
|
||||
return
|
||||
fi
|
||||
if [[ -n "${VERSION:-}" ]]; then
|
||||
echo "${VERSION}"
|
||||
return
|
||||
fi
|
||||
if git -C "${REPO_ROOT}" describe --tags --abbrev=0 >/dev/null 2>&1; then
|
||||
git -C "${REPO_ROOT}" describe --tags --abbrev=0
|
||||
return
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ checksums_path="${DIST_DIR}/checksums.txt"
|
|||
new_checksum="$(cd "${DIST_DIR}" && sha256sum "${MSI_NAME}")"
|
||||
if [[ -f "${checksums_path}" ]] && grep -qF " ${MSI_NAME}" "${checksums_path}"; then
|
||||
tmp="$(mktemp)"
|
||||
grep -vF " ${MSI_NAME}" "${checksums_path}" > "${tmp}"
|
||||
grep -vF " ${MSI_NAME}" "${checksums_path}" > "${tmp}" || true
|
||||
printf '%s\n' "${new_checksum}" >> "${tmp}"
|
||||
mv "${tmp}" "${checksums_path}"
|
||||
elif [[ -f "${checksums_path}" ]]; then
|
||||
|
|
|
|||
Loading…
Reference in New Issue