fix: several merge messes
This commit is contained in:
parent
b823d8d21b
commit
e63094e8e8
|
|
@ -52,6 +52,10 @@
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
||||||
|
import {
|
||||||
|
choiceDisplayLabel,
|
||||||
|
syncStateFromModelValue
|
||||||
|
} from './choiceComboboxHelpers.js'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
id: {
|
id: {
|
||||||
|
|
@ -117,23 +121,23 @@ const filteredChoices = computed(() => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
watch(() => props.modelValue, () => {
|
watch([() => props.modelValue, () => props.choices], () => {
|
||||||
if (!isOpen.value) {
|
if (!isOpen.value) {
|
||||||
query.value = selectedLabel()
|
syncFromModelValue()
|
||||||
}
|
}
|
||||||
}, { immediate: true })
|
}, { immediate: true })
|
||||||
|
|
||||||
function choiceLabel(choice) {
|
function choiceLabel(choice) {
|
||||||
return choice.title || choice.value
|
return choiceDisplayLabel(choice)
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectedLabel() {
|
function syncFromModelValue() {
|
||||||
const match = props.choices.find(choice => choice.value === props.modelValue)
|
const next = syncStateFromModelValue(props.choices, props.modelValue)
|
||||||
if (!match) {
|
query.value = next.query
|
||||||
return props.modelValue || ''
|
|
||||||
}
|
|
||||||
|
|
||||||
return choiceLabel(match)
|
if (next.modelValue !== props.modelValue) {
|
||||||
|
emitValue(next.modelValue)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function openList() {
|
function openList() {
|
||||||
|
|
@ -144,7 +148,7 @@ function openList() {
|
||||||
|
|
||||||
function closeList() {
|
function closeList() {
|
||||||
isOpen.value = false
|
isOpen.value = false
|
||||||
query.value = selectedLabel()
|
syncFromModelValue()
|
||||||
}
|
}
|
||||||
|
|
||||||
function emitValue(value) {
|
function emitValue(value) {
|
||||||
|
|
@ -153,11 +157,15 @@ function emitValue(value) {
|
||||||
|
|
||||||
function selectChoice(choice) {
|
function selectChoice(choice) {
|
||||||
emitValue(choice.value)
|
emitValue(choice.value)
|
||||||
closeList()
|
query.value = choiceLabel(choice)
|
||||||
|
isOpen.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleFocus() {
|
function handleFocus() {
|
||||||
query.value = isOpen.value ? query.value : selectedLabel()
|
if (!isOpen.value) {
|
||||||
|
syncFromModelValue()
|
||||||
|
}
|
||||||
|
|
||||||
openList()
|
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,
|
getRootAndWait,
|
||||||
getActionButtons,
|
getActionButtons,
|
||||||
takeScreenshotOnFailure,
|
takeScreenshotOnFailure,
|
||||||
|
waitForArgumentFormPage,
|
||||||
|
waitForArgumentFormReady,
|
||||||
} from '../../lib/elements.js'
|
} from '../../lib/elements.js'
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -46,11 +48,13 @@ describe('config: multipleDropdowns', function () {
|
||||||
|
|
||||||
await button.click()
|
await button.click()
|
||||||
|
|
||||||
// Wait for navigation to argument form page
|
await waitForArgumentFormPage(8000)
|
||||||
await webdriver.wait(new Condition('wait for argument form page', async () => {
|
await waitForArgumentFormReady(10000)
|
||||||
const url = await webdriver.getCurrentUrl()
|
|
||||||
return url.includes('/actionBinding/') && url.includes('/argumentForm')
|
await webdriver.wait(new Condition('wait for choice comboboxes', async () => {
|
||||||
}), 8000)
|
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'))
|
const comboboxes = await webdriver.findElements(By.css('main .choice-combobox'))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,9 +20,7 @@ compile-x64-lin:
|
||||||
go env -u GOOS
|
go env -u GOOS
|
||||||
|
|
||||||
compile-x64-win: windows-resources
|
compile-x64-win: windows-resources
|
||||||
go env -w GOOS=windows GOARCH=amd64
|
GOOS=windows GOARCH=amd64 go build -o OliveTin.exe
|
||||||
go build -o OliveTin.exe
|
|
||||||
go env -u GOOS GOARCH
|
|
||||||
|
|
||||||
windows-resources:
|
windows-resources:
|
||||||
$(MAKE) -wC .. 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) {
|
func TestEnvInConfig(t *testing.T) {
|
||||||
for _, tt := range envConfigTests {
|
for _, tt := range envConfigTests {
|
||||||
cfg := DefaultConfig()
|
cfg := DefaultConfig()
|
||||||
setIfNotEmpty("INPUT", tt.input)
|
setTestEnvInput(t, tt.input)
|
||||||
k := koanf.New(".")
|
if !loadConfigFromYAML(t, tt.yaml, cfg) {
|
||||||
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) {
|
|
||||||
t.Errorf("Error unmarshalling config for env=%q", tt.input)
|
t.Errorf("Error unmarshalling config for env=%q", tt.input)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
field := tt.selector(cfg)
|
field := tt.selector(cfg)
|
||||||
assert.Equal(t, tt.output, field,
|
assert.Equal(t, tt.output, field,
|
||||||
"Unmarshaled config field doesn't match expected value: env=%q", tt.input)
|
"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}"
|
local raw="${1#v}"
|
||||||
raw="${raw%%-*}"
|
raw="${raw%%-*}"
|
||||||
if [[ ! "${raw}" =~ ^[0-9]+(\.[0-9]+){0,3}$ ]]; then
|
if [[ ! "${raw}" =~ ^[0-9]+(\.[0-9]+){0,3}$ ]]; then
|
||||||
echo "0.0.0"
|
echo "Invalid MSI version (expected major[.minor[.patch[.build]]]): ${1}" >&2
|
||||||
return
|
return 1
|
||||||
fi
|
fi
|
||||||
local -a parts=()
|
local -a parts=()
|
||||||
IFS='.' read -r -a parts <<<"${raw}"
|
IFS='.' read -r -a parts <<<"${raw}"
|
||||||
|
|
@ -43,7 +43,7 @@ if [[ -z "${VERSION}" ]]; then
|
||||||
echo "Could not determine release version; set VERSION explicitly" >&2
|
echo "Could not determine release version; set VERSION explicitly" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
MSI_VERSION="$(normalize_msi_version "${VERSION}")"
|
MSI_VERSION="$(normalize_msi_version "${VERSION}")" || exit 1
|
||||||
|
|
||||||
STAGING="$(mktemp -d)"
|
STAGING="$(mktemp -d)"
|
||||||
APP_STAGING="$(mktemp -d)"
|
APP_STAGING="$(mktemp -d)"
|
||||||
|
|
|
||||||
|
|
@ -37,14 +37,14 @@ normalize_windows_version() {
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve_version() {
|
resolve_version() {
|
||||||
if [[ -n "${VERSION:-}" ]]; then
|
|
||||||
echo "${VERSION}"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
if [[ $# -gt 0 && -n "${1:-}" ]]; then
|
if [[ $# -gt 0 && -n "${1:-}" ]]; then
|
||||||
echo "${1}"
|
echo "${1}"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
if [[ -n "${VERSION:-}" ]]; then
|
||||||
|
echo "${VERSION}"
|
||||||
|
return
|
||||||
|
fi
|
||||||
if git -C "${REPO_ROOT}" describe --tags --abbrev=0 >/dev/null 2>&1; then
|
if git -C "${REPO_ROOT}" describe --tags --abbrev=0 >/dev/null 2>&1; then
|
||||||
git -C "${REPO_ROOT}" describe --tags --abbrev=0
|
git -C "${REPO_ROOT}" describe --tags --abbrev=0
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ checksums_path="${DIST_DIR}/checksums.txt"
|
||||||
new_checksum="$(cd "${DIST_DIR}" && sha256sum "${MSI_NAME}")"
|
new_checksum="$(cd "${DIST_DIR}" && sha256sum "${MSI_NAME}")"
|
||||||
if [[ -f "${checksums_path}" ]] && grep -qF " ${MSI_NAME}" "${checksums_path}"; then
|
if [[ -f "${checksums_path}" ]] && grep -qF " ${MSI_NAME}" "${checksums_path}"; then
|
||||||
tmp="$(mktemp)"
|
tmp="$(mktemp)"
|
||||||
grep -vF " ${MSI_NAME}" "${checksums_path}" > "${tmp}"
|
grep -vF " ${MSI_NAME}" "${checksums_path}" > "${tmp}" || true
|
||||||
printf '%s\n' "${new_checksum}" >> "${tmp}"
|
printf '%s\n' "${new_checksum}" >> "${tmp}"
|
||||||
mv "${tmp}" "${checksums_path}"
|
mv "${tmp}" "${checksums_path}"
|
||||||
elif [[ -f "${checksums_path}" ]]; then
|
elif [[ -f "${checksums_path}" ]]; then
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue