• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

skmtc / skmtc / 19195291987

08 Nov 2025 03:59PM UTC coverage: 64.61% (-0.02%) from 64.626%
19195291987

push

github

dmitrigrabov
Remove unused ids

678 of 901 branches covered (75.25%)

Branch coverage included in aggregate %.

19 of 21 new or added lines in 11 files covered. (90.48%)

1 existing line in 1 file now uncovered.

7897 of 12371 relevant lines covered (63.83%)

68.95 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

57.86
/deno/cli/tasks/SelectProjectTask.tsx
1
import { useTask } from '@/components/TaskContext.tsx'
13✔
2
import { TaskBox } from '@/components/TaskBox.tsx'
13✔
3
import { Text } from 'ink'
13✔
4
import { useSkmtc } from '@/components/SkmtcContext.tsx'
13✔
5
import { useState } from 'react'
13✔
6
import { TextInput } from '@inkjs/ui'
13✔
7
import { TaskContainer } from '@/components/TaskContainer.tsx'
13✔
8
import SelectInput from 'ink-select-input'
13✔
9
import { useGetGenerators } from '@/components/useGetGenerators.ts'
13✔
10
import { Project } from '@/lib/project.ts'
13✔
11
import { Spinner } from '@/components/Spinner.tsx'
13✔
12

13
type ProjectOption = {
14
  label: string
15
  value: string
16
  isCustom?: boolean
17
}
18

19
type ProjectItemProps = {
20
  label: string
21
  isSelected?: boolean
22
  isCustom?: boolean
23
  customValue?: string
24
  hasCustomValue?: boolean
25
  onCustomValueChange?: (value: string) => void
26
}
27

28
const PLACEHOLDER = 'Create new project'
13✔
29

30
const ProjectItem = ({
13✔
31
  label,
13✔
32
  isSelected = false,
13✔
33
  isCustom,
13✔
34
  customValue = PLACEHOLDER,
13✔
35
  hasCustomValue = false,
13✔
36
  onCustomValueChange
13✔
37
}: ProjectItemProps) => {
13✔
38
  if (isCustom) {
15✔
39
    // When selected and it's still the placeholder, start with empty input
40
    // When selected and user has typed something, show their value
41
    const inputValue = isSelected && !hasCustomValue ? '' : customValue
×
42

43
    // When not selected, show placeholder if value is empty
44
    const displayValue = customValue || PLACEHOLDER
×
45

46
    return isSelected ? (
×
47
      <TextInput defaultValue={inputValue} onSubmit={() => {}} onChange={onCustomValueChange} />
×
48
    ) : (
49
      <Text color={isSelected ? 'white' : undefined} dimColor={hasCustomValue}>
16!
50
        {displayValue}
16✔
51
      </Text>
52
    )
53
  }
16✔
54

55
  return <Text color={isSelected ? 'white' : undefined}>{label}</Text>
31!
56
}
13✔
57

58
export const SelectProjectTask = () => {
13✔
59
  const { dispatch } = useTask()
136✔
60
  const { state, dispatchMessage } = useSkmtc()
136✔
61
  const [customProjectName, setCustomProjectName] = useState(PLACEHOLDER)
136✔
62
  const [hasCustomValue, setHasCustomValue] = useState(false)
136✔
63
  const [response, setResponse] = useState<string | null>(null)
136✔
64
  const [isCreating, setIsCreating] = useState(false)
136✔
65
  const availableGenerators = useGetGenerators()
136✔
66

UNCOV
67
  const handleCustomValueChange = (value: string) => {
×
68
    setCustomProjectName(value)
×
69
    // Mark as custom if user has typed anything different from empty or placeholder
70
    if (value && value !== PLACEHOLDER) {
×
71
      setHasCustomValue(true)
×
72
    } else {
×
73
      // User cleared the input or it's back to placeholder
74
      setHasCustomValue(false)
×
75
    }
×
76
  }
×
77

78
  if (isCreating) {
×
79
    return (
×
NEW
80
      <TaskBox active>
×
81
        <Spinner label={`Creating project "${customProjectName}"...`} />
×
82
      </TaskBox>
83
    )
84
  }
×
85

86
  if (response !== null) {
136✔
87
    return (
256✔
88
      <TaskBox prompt="Select project" active={false}>
768✔
89
        <Text dimColor>{response}</Text>
768✔
90
      </TaskBox>
91
    )
92
  }
256✔
93

94
  if (state.skmtcRoot.projects.length === 0) {
136✔
95
    return (
138✔
96
      <TaskBox active>
276✔
97
        <Text>No projects found</Text>
276✔
98
      </TaskBox>
99
    )
100
  }
138✔
101

102
  const options: ProjectOption[] = [
137✔
103
    ...state.skmtcRoot.projects.map(project => ({
137✔
104
      label: project.name,
138✔
105
      value: project.name
138✔
106
    })),
137✔
107
    {
137✔
108
      label: 'Create new project',
137✔
109
      value: '__custom__',
137✔
110
      isCustom: true
137✔
111
    }
137✔
112
  ]
137✔
113

114
  const handleCreateProject = async () => {
×
115
    // Validate that user has entered a custom project name
116
    if (!hasCustomValue || !customProjectName || customProjectName === PLACEHOLDER) {
×
117
      dispatchMessage({ error: 'Please enter a valid project name' })
×
118
      return
×
119
    }
×
120

121
    if (!availableGenerators) {
×
122
      dispatchMessage({ error: 'Generators not loaded yet' })
×
123
      return
×
124
    }
×
125

126
    setIsCreating(true)
×
127

128
    try {
×
129
      const project = await Project.create({
×
130
        name: customProjectName,
×
131
        basePath: '',
×
132
        generators: [],
×
133
        skmtcRoot: state.skmtcRoot,
×
134
        availableGenerators
×
135
      })
×
136

137
      setResponse(customProjectName)
×
138
      dispatchMessage({ success: `Project "${customProjectName}" created` })
×
139

140
      dispatch({
×
141
        type: 'set-task-state',
×
142
        payload: { taskKey: 'select-project-task', state: project }
×
143
      })
×
144
      dispatch({ type: 'increment-current-task' })
×
145
    } catch (error) {
×
146
      console.error(error)
×
147
      dispatchMessage({ error: `Failed to create project "${customProjectName}"` })
×
148
      setIsCreating(false)
×
149
    }
×
150
  }
×
151

152
  return (
137✔
153
    <TaskContainer prompt="Select project">
274✔
154
      <SelectInput
137✔
155
        items={options}
137✔
156
        itemComponent={props => (
137✔
157
          <ProjectItem
137✔
158
            {...props}
139✔
159
            customValue={customProjectName}
139✔
160
            hasCustomValue={hasCustomValue}
139✔
161
            onCustomValueChange={handleCustomValueChange}
139✔
162
          />
163
        )}
164
        onSelect={item => {
137✔
165
          if (item.value === '__custom__') {
×
166
            handleCreateProject()
×
167
          } else {
×
168
            const project = state.skmtcRoot.findProject(item.value)
138✔
169
            setResponse(item.value)
138✔
170

171
            dispatch({
138✔
172
              type: 'set-task-state',
138✔
173
              payload: { taskKey: 'select-project-task', state: project }
552✔
174
            })
138✔
175

176
            dispatch({ type: 'increment-current-task' })
414✔
177
          }
138✔
178
        }}
138✔
179
      />
180
    </TaskContainer>
181
  )
182
}
13✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc