Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Feature/subtask markdown#383

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
ShMcK merged 5 commits intomasterfromfeature/subtask-markdown
Jul 5, 2020
Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletionsCHANGELOG.md
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -175,3 +175,29 @@ A description of the task.
- The second hint
- The last hint
```

### [0.9.0]

Change subtask format to include subtasks in markdown.

Subtasks no longer need to be included in yaml, or require a filter.

See an example at <http://github.com/shmck/coderoad-tutorial-subtask-demo>

```md
### 1.1

A description of the task

#### SUBTASKS

- The first subtask
- The second subtask
```

Subtasks are then matched up with tests with names that match

```text
SUBTASK 1.1 :1 test name
SUBTASK 1.2 :2 test name
```
8 changes: 0 additions & 8 deletionsdocs/docs/config-yml.md
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -103,14 +103,6 @@ levels:
-package.json
commits:
-commit8
## Example Four: Subtasks
-id:'1.4'
setup:
commands:
## A filter is a regex that limits the test results
-filter:'^Example 2'
## A feature that shows subtasks: all filtered active test names and the status of the tests (pass/fail).
-subtasks:true
-id:'2'
steps:
-id:'2.1'
Expand Down
2 changes: 0 additions & 2 deletionsdocs/docs/create-a-practice-tutorial.md
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -191,8 +191,6 @@ levels:
-id:'1'
steps:
-id:'1.1'
setup:
subtasks:false
```
Replace the`repo uri` URL with your github repo, note that it's just the username and repo in the URL. This file links everything together. You can see the repo URL and the branch that you created. And the `1.` and `1.1` id's that match the markdown. You can also add commands that will run when a lesson is started, as well as a host of other things.
Expand Down
2 changes: 1 addition & 1 deletionpackage.json
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
{
"name":"coderoad",
"version":"0.8.0",
"version":"0.9.0",
"description":"Play interactive coding tutorials in your editor",
"keywords": [
"tutorial",
Expand Down
2 changes: 1 addition & 1 deletionsrc/channel/index.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -306,7 +306,7 @@ class Channel implements Channel {
awaitvscode.commands.executeCommand(COMMANDS.SET_CURRENT_POSITION,action.payload.position)
awaitsolutionActions({actions:action.payload.actions,send:this.send})
// run test following solution to update position
vscode.commands.executeCommand(COMMANDS.RUN_TEST,{subtasks:true})
vscode.commands.executeCommand(COMMANDS.RUN_TEST)
return
case'EDITOR_SYNC_PROGRESS':
// update progress when a level is deemed complete in the client
Expand Down
2 changes: 1 addition & 1 deletionsrc/editor/commands.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -82,7 +82,7 @@ export const createCommands = ({ extensionPath, workspaceState }: CreateCommandP
webview.send({type:'TEST_RUNNING',payload:{ position}})
},
onLoadSubtasks:({ summary})=>{
webview.send({type:'LOAD_TEST_SUBTASKS',payload:{ summary}})
webview.send({type:'LOAD_SUBTASK_RESULTS',payload:{ summary}})
},
})
},
Expand Down
39 changes: 27 additions & 12 deletionssrc/services/testRunner/index.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,6 +3,7 @@ import * as TT from 'typings/tutorial'
import{exec}from'../node'
importloggerfrom'../logger'
importparser,{ParserOutput}from'./parser'
importparseSubtasksfrom'./subtasks'
import{debounce,throttle}from'./throttle'
importonErrorfrom'../sentry/onError'
import{clearOutput,addOutput}from'./output'
Expand All@@ -13,7 +14,7 @@ interface Callbacks {
onFail(position:T.Position,failSummary:T.TestFail):void
onRun(position:T.Position):void
onError(position:T.Position):void
onLoadSubtasks({ summary}:{summary:{[testName:string]:boolean}}):void
onLoadSubtasks({ summary}:{summary:{[testId:number]:boolean}}):void
}

constfailChannelName='CodeRoad (Tests)'
Expand All@@ -28,7 +29,7 @@ interface TestRunnerParams {
constcreateTestRunner=(data:TT.Tutorial,callbacks:Callbacks)=>{
consttestRunnerConfig=data.config.testRunner
consttestRunnerFilterArg=testRunnerConfig.args?.filter
returnasync({ position, onSuccess, subtasks}:TestRunnerParams):Promise<void>=>{
returnasync({ position, onSuccess}:TestRunnerParams):Promise<void>=>{
conststartTime=throttle()
// throttle time early
if(!startTime){
Expand All@@ -37,11 +38,20 @@ const createTestRunner = (data: TT.Tutorial, callbacks: Callbacks) => {

logger('------------------- RUN TEST -------------------')

// flag as running
if(!subtasks){
callbacks.onRun(position)
// calculate level & step from position
constlevel:TT.Level|null=data.levels.find((l)=>l.id===position.levelId)||null
if(!level){
console.warn(`Level "${position.levelId}" not found`)
return
}
conststep:TT.Step|null=level.steps.find((s)=>s.id===position.stepId)||null
if(!step){
console.warn(`Step "${position.stepId}" not found`)
return
}

callbacks.onRun(position)

letresult:{stdout:string|undefined;stderr:string|undefined}
try{
letcommand=testRunnerConfig.args
Expand DownExpand Up@@ -81,12 +91,6 @@ const createTestRunner = (data: TT.Tutorial, callbacks: Callbacks) => {

consttap:ParserOutput=parser(stdout||'')

if(subtasks){
callbacks.onLoadSubtasks({summary:tap.summary})
// exit early
return
}

addOutput({channel:logChannelName,text:tap.logs.join('\n'),show:false})

if(stderr){
Expand All@@ -107,7 +111,18 @@ const createTestRunner = (data: TT.Tutorial, callbacks: Callbacks) => {
description:firstFail.details||'Unknown error',
summary:tap.summary,
}
callbacks.onFail(position,failSummary)

if(step.setup.subtasks){
constsubtaskSummary=parseSubtasks(tap.summary,position.stepId||'')

callbacks.onFail(position,{
...failSummary,
summary:subtaskSummary,
})
}else{
callbacks.onFail(position,failSummary)
}

constoutput=formatFailOutput(tap)
addOutput({channel:failChannelName,text:output,show:true})
return
Expand Down
25 changes: 25 additions & 0 deletionssrc/services/testRunner/parser.test.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -269,3 +269,28 @@ not ok 2 test_add_one_number (tests.math_test.MathTest)
})
})
})

describe('subtasks',()=>{
it('should parse subtasks',()=>{
constsummary={
'SUBTASKS 1.1 :1 should add one number':true,
'SUBTASKS 1.1 :2 should add two numbers':false,
'SUBTASKS 1.1 :3 should add three numbers':false,
}
constsubtaskRegex=/^SUBTASKS\s(?<stepId>(\d+\.\d+))\s:(?<testId>\d+)\s/
constsubtaskSummary={}
Object.keys(summary).forEach((key)=>{
constmatch=key.match(subtaskRegex)
if(!!match){
const{ stepId, testId}=match.groups||{}
consttestIndex=Number(testId)-1
subtaskSummary[testIndex]=summary[key]
}
})
expect(subtaskSummary).toEqual({
0:true,
1:false,
2:false,
})
})
})
24 changes: 24 additions & 0 deletionssrc/services/testRunner/subtasks.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
interfaceSummary{
[key:string]:boolean
}

// if a subtask matches the current stepId name
// in the format "SUBTASKS 1.1 :1" where 1.1 is the stepId & :1 is the testId
// values will be parsed and sent to the client
constparseSubtasks=(summary:Summary,expectedStepId:string|null):Summary=>{
constsubtaskRegex=/^SUBTASKS\s(?<stepId>(\d+\.\d+))\s:(?<testId>\d+)\s/
constsubtaskSummary={}
Object.keys(summary).forEach((key)=>{
constmatch=key.match(subtaskRegex)
if(!!match){
const{ stepId, testId}=match.groups||{}
if(stepId===expectedStepId){
consttestIndex=Number(testId)-1
subtaskSummary[testIndex]=summary[key]
}
}
})
returnsubtaskSummary
}

exportdefaultparseSubtasks
4 changes: 2 additions & 2 deletionstypings/tutorial.d.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,7 +27,7 @@ export type Step = {
content:string
setup:StepActions
solution:Maybe<StepActions>
subtasks?:{[testName:string]:boolean}
subtasks?:{[index:number]:boolean}
hints?:string[]
}

Expand All@@ -52,7 +52,7 @@ export type StepActions = {
files?:string[]
watchers?:string[]
filter?:string
subtasks?:boolean
subtasks?:string[]
}

exportinterfaceTestRunnerArgs{
Expand Down
2 changes: 1 addition & 1 deletionweb-app/package.json
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
{
"name":"coderoad-app",
"version":"0.8.0",
"version":"0.9.0",
"private":true,
"scripts": {
"build":"react-app-rewired build",
Expand Down
10 changes: 4 additions & 6 deletionsweb-app/src/containers/Tutorial/components/Level.tsx
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -199,14 +199,12 @@ const Level = ({
returnnull
}
letsubtasks=null
if(step?.setup?.subtasks&&testStatus?.summary){
subtasks=Object.keys(testStatus.summary).map((testName:string)=>({
name:testName,
//@ts-ignore typescript is wrong here
pass:testStatus.summary[testName],
if(step?.setup?.subtasks){
subtasks=step.setup.subtasks.map((subtask:string,subtaskIndex:number)=>({
name:subtask,
pass:!!(testStatus?.summary ?testStatus.summary[subtaskIndex] :false),
}))
}
consthints=step.hints
return(
<Step
key={step.id}
Expand Down
2 changes: 1 addition & 1 deletionweb-app/src/containers/Tutorial/components/Step.tsx
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -67,7 +67,7 @@ const Step = (props: Props) => {
<ulcss={styles.subtasks}>
{props.subtasks.map((subtask)=>(
<likey={subtask.name}css={styles.subtask}>
<TestStatusIconsize="xs"checked={subtask.pass}/>
<TestStatusIconsize="xs"checked={props.status==='COMPLETE'||subtask.pass}/>

<spanstyle={{marginLeft:'0.5rem'}}>{subtask.name}</span>
</li>
Expand Down
3 changes: 1 addition & 2 deletionsweb-app/src/services/state/actions/editor.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -58,12 +58,11 @@ export default (editorSend: any) => ({
})

if(step.setup.subtasks){
// load subtaskdata by running tests and parsing result
// load subtasksummary by running tests and parsing result
editorSend({
type:'EDITOR_RUN_TEST',
payload:{
position:context.position,
subtasks:true,
},
})
}
Expand Down
2 changes: 1 addition & 1 deletionweb-app/src/services/state/machine.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -155,7 +155,7 @@ export const createMachine = (options: any) => {
Normal:{
id:'tutorial-level',
on:{
LOAD_TEST_SUBTASKS:{
LOAD_SUBTASK_RESULTS:{
actions:['testSubtasks'],
},
TEST_RUNNING:'TestRunning',
Expand Down
24 changes: 1 addition & 23 deletionsweb-app/src/services/state/useStateMachine.tsx
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,7 @@ import * as React from 'react'
import*asTfrom'typings'
import{createMachine}from'./machine'
import{useMachine}from'../xstate-react'
importcreateRouteStringfrom'./utils/routeString'
importloggerfrom'../logger'

interfaceOutput{
Expand All@@ -12,29 +13,6 @@ interface Output {

declareletacquireVsCodeApi:any

exportconstcreateRouteString=(route:object|string):string=>{
if(typeofroute==='string'){
returnroute
}
constpaths:string[]=[]
letcurrent:object|string|undefined=route
while(current){
// current is final string value
if(typeofcurrent==='string'){
paths.push(current)
break
}

// current is object
constnext:string=Object.keys(current)[0]
paths.push(next)
//@ts-ignore
current=current[next]
}

returnpaths.join('.')
}

consteditor=acquireVsCodeApi()
consteditorSend=(action:T.Action)=>{
logger(`TO EXT: "${action.type}"`)
Expand Down
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
import{createRouteString}from'./useStateMachine'
importcreateRouteStringfrom'./routeString'

describe('route string',()=>{
it('should take a single key route',()=>{
Expand Down
24 changes: 24 additions & 0 deletionsweb-app/src/services/state/utils/routeString.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
constcreateRouteString=(route:object|string):string=>{
if(typeofroute==='string'){
returnroute
}
constpaths:string[]=[]
letcurrent:object|string|undefined=route
while(current){
// current is final string value
if(typeofcurrent==='string'){
paths.push(current)
break
}

// current is object
constnext:string=Object.keys(current)[0]
paths.push(next)
//@ts-ignore
current=current[next]
}

returnpaths.join('.')
}

exportdefaultcreateRouteString
1 change: 0 additions & 1 deletionweb-app/stories/Level.stories.tsx
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -133,7 +133,6 @@ storiesOf('Level', module)
setup:{
id:'L1:S2:SETUP',
commits:['abcdefg'],
subtasks:true,
filter:'^SomeTest',
},
solution:{
Expand Down

[8]ページ先頭

©2009-2025 Movatter.jp