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

Commitf11a7ab

Browse files
committed
refactor step tests
Signed-off-by: shmck <shawn.j.mckay@gmail.com>
1 parent1e13c24 commitf11a7ab

File tree

3 files changed

+148
-98
lines changed

3 files changed

+148
-98
lines changed

‎src/templates/coderoad.yaml

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,8 @@ config:
3131
# - npm install
3232
## App versions helps to ensure compatability with the Extension
3333
appVersions:
34-
{}
3534
## Ensure compatability with a minimal VSCode CodeRoad version
36-
#vscode:'>=0.7.0'
35+
vscode:">=0.7.0"
3736
## Repo information to load code from
3837
##
3938
repo:
@@ -62,25 +61,16 @@ levels:
6261
## Setup for the first task. Required.
6362
setup:
6463
## Files to open in a text editor when the task loads. Optional.
65-
files:[]
66-
# - package.json
67-
## Commits to load when the task loads. These should include failing tests. Required.
68-
## The list will be filled by the parser
69-
commits:
70-
[]
71-
# - a commit hash
64+
files:
65+
-package.json
7266
## Solution for the first task. Required.
7367
solution:
7468
## Files to open when the solution loads. Optional.
75-
files:[]
76-
# - package.json
77-
## Commits that complete the task. All tests should pass when the commits load. These commits will not be loaded by the tutorial user in normal tutorial activity.
78-
## The list will be filled by the parser
79-
commits:[]
69+
files:
70+
-package.json
8071
## Example Two: Running commands
8172
-id:L1S2
8273
setup:
83-
commits:[]
8474
## CLI commands that are run when the task loads. Optional.
8575
commands:
8676
-npm install
@@ -94,27 +84,18 @@ levels:
9484
setup:
9585
files:
9686
-package.json
97-
commits:
98-
-commit7
9987
## Listeners that run tests when a file or directory changes.
10088
watchers:
10189
-package.json
10290
-node_modules/some-package
10391
solution:
10492
files:
10593
-package.json
106-
commits:
107-
-commit8
10894
## Example Four: Subtasks
10995
-id:L1S4
11096
setup:
111-
commits:
112-
-commit8
11397
commands:
11498
## A filter is a regex that limits the test results
11599
-filter:"^Example 2"
116100
## A feature that shows subtasks: all filtered active test names and the status of the tests (pass/fail).
117101
-subtasks:true
118-
solution:
119-
commits:
120-
-commit9

‎src/utils/parse.ts

Lines changed: 75 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ import * as T from "../../typings/tutorial";
44

55
typeTutorialFrame={
66
summary:T.TutorialSummary;
7+
levels:{
8+
[levelKey:string]:T.Level;
9+
};
10+
steps:{[stepKey:string]:Partial<T.Step>};
711
};
812

913
exportfunctionparseMdContent(md:string):TutorialFrame|never{
@@ -24,73 +28,66 @@ export function parseMdContent(md: string): TutorialFrame | never {
2428
}
2529
});
2630

27-
constsections={};
31+
constmdContent:TutorialFrame={
32+
summary:{
33+
title:"",
34+
description:"",
35+
},
36+
levels:{},
37+
steps:{},
38+
};
2839

29-
//Identify and remove the header
40+
//Capture summary
3041
constsummaryMatch=parts
3142
.shift()
3243
.match(/^#\s(?<tutorialTitle>.*)[\n\r]+(?<tutorialDescription>[^]*)/);
33-
3444
if(!summaryMatch.groups.tutorialTitle){
3545
thrownewError("Missing tutorial title");
3646
}
47+
mdContent.summary.title=summaryMatch.groups.tutorialTitle.trim();
3748

3849
if(!summaryMatch.groups.tutorialDescription){
3950
thrownewError("Missing tutorial summary description");
4051
}
41-
42-
sections["summary"]={
43-
title:summaryMatch.groups.tutorialTitle.trim(),
44-
description:summaryMatch.groups.tutorialDescription.trim(),
45-
};
52+
mdContent.summary.description=summaryMatch.groups.tutorialDescription.trim();
4653

4754
// Identify each part of the content
48-
parts.forEach((section)=>{
55+
parts.forEach((section:string)=>{
56+
// match level
4957
constlevelRegex=/^(##\s(?<levelId>L\d+)\s(?<levelTitle>.*)[\n\r]*(>\s*(?<levelSummary>.*))?[\n\r]+(?<levelContent>[^]*))/;
50-
conststepRegex=/^(###\s(?<stepId>(?<levelId>L\d+)S\d+)\s(?<stepTitle>.*)[\n\r]+(?<stepContent>[^]*))/;
51-
52-
constlevelMatch=section.match(levelRegex);
53-
conststepMatch=section.match(stepRegex);
54-
55-
if(levelMatch){
58+
constlevelMatch:RegExpMatchArray|null=section.match(levelRegex);
59+
if(levelMatch&&levelMatch.groups){
5660
const{
5761
levelId,
5862
levelTitle,
5963
levelSummary,
6064
levelContent,
6165
}=levelMatch.groups;
6266

63-
constlevel={
64-
[levelId]:{
65-
id:levelId,
66-
title:levelTitle,
67-
summary:levelSummary
68-
?levelSummary.trim()
69-
:_.truncate(levelContent,{length:80,omission:"..."}),
70-
content:levelContent.trim(),
71-
},
72-
};
73-
74-
_.merge(sections,level);
75-
}elseif(stepMatch){
76-
conststep={
77-
[stepMatch.groups.levelId]:{
78-
steps:{
79-
[stepMatch.groups.stepId]:{
80-
id:stepMatch.groups.stepId,
81-
// title: stepMatch.groups.stepTitle, //Not using at this momemnt
82-
content:stepMatch.groups.stepContent.trim(),
83-
},
84-
},
85-
},
67+
//@ts-ignore
68+
mdContent.levels[levelId]={
69+
id:levelId,
70+
title:levelTitle,
71+
summary:levelSummary
72+
?levelSummary.trim()
73+
:_.truncate(levelContent,{length:80,omission:"..."}),
74+
content:levelContent.trim(),
8675
};
87-
88-
_.merge(sections,step);
76+
}else{
77+
// match step
78+
conststepRegex=/^(###\s(?<stepId>(?<levelId>L\d+)S\d+)\s(?<stepTitle>.*)[\n\r]+(?<stepContent>[^]*))/;
79+
conststepMatch:RegExpMatchArray|null=section.match(stepRegex);
80+
if(stepMatch&&stepMatch.groups){
81+
const{ stepId, stepContent}=stepMatch.groups;
82+
mdContent.steps[stepId]={
83+
id:stepId,
84+
content:stepContent.trim(),
85+
};
86+
}
8987
}
9088
});
9189

92-
//@ts-ignore
93-
returnsections;
90+
returnmdContent;
9491
}
9592

9693
typeParseParams={
@@ -100,41 +97,41 @@ type ParseParams = {
10097
};
10198

10299
exportfunctionparse(params:ParseParams):any{
103-
constparsed={ ...params.config};
104-
105100
constmdContent:TutorialFrame=parseMdContent(params.text);
106101

107-
// Add the summary to the tutorial file
108-
parsed["summary"]=mdContent.summary;
102+
constparsed:Partial<T.Tutorial>={
103+
summary:mdContent.summary,
104+
config:params.config.config,
105+
levels:[],
106+
};
109107

110108
// merge content and tutorial
111-
if(parsed.levels){
112-
parsed.levels.forEach((level:T.Level,levelIndex:number)=>{
113-
constlevelContent=mdContent[level.id];
109+
if(params.config.levels&&params.config.levels.length){
110+
parsed.levels=params.config.levels.map(
111+
(level:T.Level,levelIndex:number)=>{
112+
constlevelContent=mdContent.levels[level.id];
113+
114+
if(!levelContent){
115+
console.log(`Markdown content not found for${level.id}`);
116+
return;
117+
}
114118

115-
if(!levelContent){
116-
console.log(`Markdown content not found for${level.id}`);
117-
return;
118-
}
119+
level={ ...level, ...levelContent};
119120

120-
// add level setup commits
121-
constlevelSetupKey=`L${levelIndex+1}`;
122-
if(params.commits[levelSetupKey]){
123-
if(!level.setup){
124-
level.setup={
125-
commits:[],
126-
};
121+
// add level setup commits
122+
constlevelSetupKey=level.id;
123+
if(params.commits[levelSetupKey]){
124+
if(!level.setup){
125+
level.setup={
126+
commits:[],
127+
};
128+
}
129+
level.setup.commits=params.commits[levelSetupKey];
127130
}
128-
level.setup.commits=params.commits[levelSetupKey];
129-
}
130-
131-
const{ steps, ...content}=levelContent;
132131

133-
// add level step commits
134-
if(steps){
135-
level.steps=Object.keys(steps).map(
136-
(stepId:string,stepIndex:number)=>{
137-
conststep:T.Step=steps[stepId];
132+
// add level step commits
133+
level.steps=(level.steps||[]).map(
134+
(step:T.Step,stepIndex:number)=>{
138135
conststepKey=`${levelSetupKey}S${stepIndex+1}`;
139136
conststepSetupKey=`${stepKey}Q`;
140137
if(params.commits[stepSetupKey]){
@@ -156,16 +153,20 @@ export function parse(params: ParseParams): any {
156153
step.solution.commits=params.commits[stepSolutionKey];
157154
}
158155

156+
// add markdown
157+
conststepMarkdown:Partial<T.Step>=mdContent.steps[step.id];
158+
if(stepMarkdown){
159+
step={ ...step, ...stepMarkdown};
160+
}
161+
159162
step.id=`${stepKey}`;
160163
returnstep;
161164
}
162165
);
163-
}else{
164-
level.steps=[];
165-
}
166166

167-
_.merge(level,content);
168-
});
167+
returnlevel;
168+
}
169+
);
169170
}
170171

171172
returnparsed;

‎tests/parse.test.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,74 @@ The first step
359359
expect(result.levels[0].setup).toEqual(expected.levels[0].setup);
360360
});
361361

362+
it("should load the full config for a step",()=>{
363+
constmd=`# Title
364+
365+
Description.
366+
367+
## L1 Title
368+
369+
First line
370+
371+
### L1S1 Step
372+
373+
The first step
374+
`;
375+
constconfig={
376+
levels:[
377+
{
378+
id:"L1",
379+
steps:[
380+
{
381+
id:"L1S1",
382+
setup:{
383+
commands:["npm install"],
384+
files:["someFile.js"],
385+
watchers:["someFile.js"],
386+
filter:"someFilter",
387+
subtasks:true,
388+
},
389+
},
390+
],
391+
},
392+
],
393+
};
394+
constresult=parse({
395+
text:md,
396+
config,
397+
commits:{
398+
L1S1Q:["abcdefg1","123456789"],
399+
},
400+
});
401+
constexpected={
402+
summary:{
403+
description:"Description.",
404+
},
405+
levels:[
406+
{
407+
id:"L1",
408+
summary:"First line",
409+
content:"First line",
410+
steps:[
411+
{
412+
id:"L1S1",
413+
content:"The first step",
414+
setup:{
415+
commits:["abcdefg1","123456789"],
416+
commands:["npm install"],
417+
files:["someFile.js"],
418+
watchers:["someFile.js"],
419+
filter:"someFilter",
420+
subtasks:true,
421+
},
422+
},
423+
],
424+
},
425+
],
426+
};
427+
expect(result.levels[0].steps[0]).toEqual(expected.levels[0].steps[0]);
428+
});
429+
362430
// config
363431
it("should parse the tutorial config",()=>{
364432
constmd=`# Title

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp