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

Commite8d10b8

Browse files
authored
Merge pull requestcoderoad#311 from coderoad/feature/test-failure
Feature/test failure
2 parents7fdc351 +623c737 commite8d10b8

File tree

20 files changed

+93
-36
lines changed

20 files changed

+93
-36
lines changed

‎CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,3 +101,9 @@ Resulting in a folder structure like the following:
101101
- Continue an incomplete tutorial started in the same workspace. Choose the "continue" path from the start screen. Progress is stored in local storage in the workspace.
102102

103103
![continue tutorial](./docs/images/continue-tutorial.png)
104+
105+
## [0.5.0]
106+
107+
- Show error messages in the webview UI
108+
109+
![fail message in webview](./docs/images/fail-message-in-webview.png)
96.9 KB
Loading

‎src/channel/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { openWorkspace, checkWorkspaceEmpty } from '../services/workspace'
1414
import{readFile}from'fs'
1515
import{join}from'path'
1616
import{promisify}from'util'
17+
import{showOutput}from'../services/testRunner/output'
1718
import{WORKSPACE_ROOT}from'../environment'
1819

1920
constreadFileAsync=promisify(readFile)
@@ -300,7 +301,9 @@ class Channel implements Channel {
300301
// update progress when a level is deemed complete in the client
301302
awaitthis.context.progress.syncProgress(action.payload.progress)
302303
return
303-
304+
case'EDITOR_OPEN_LOGS':
305+
constchannel=action.payload.channel
306+
awaitshowOutput(channel)
304307
default:
305308
logger(`No match for action type:${actionType}`)
306309
return

‎src/editor/commands.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import * as TT from 'typings/tutorial'
33
import*asvscodefrom'vscode'
44
importcreateTestRunnerfrom'../services/testRunner'
55
import{setupActions}from'../actions/setupActions'
6-
importcreateWebViewfrom'../webview'
6+
importcreateWebViewfrom'../services/webview'
77
importloggerfrom'../services/logger'
88

99
exportconstCOMMANDS={
@@ -62,9 +62,9 @@ export const createCommands = ({ extensionPath, workspaceState }: CreateCommandP
6262
// send test pass message back to client
6363
webview.send({type:'TEST_PASS',payload:{ position}})
6464
},
65-
onFail:(position:T.Position,message:string)=>{
65+
onFail:(position:T.Position,failSummary:T.TestFail):void=>{
6666
// send test fail message back to client with failure message
67-
webview.send({type:'TEST_FAIL',payload:{ position,message}})
67+
webview.send({type:'TEST_FAIL',payload:{ position,fail:failSummary}})
6868
},
6969
onError:(position:T.Position)=>{
7070
// TODO: send test error message back to client

‎src/environment.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export type Env = 'test' | 'local' | 'development' | 'production'
1010
exportconstNODE_ENV:Env=process.env.NODE_ENV||'production'
1111

1212
// toggle logging in development
13-
exportconstLOG=false
13+
exportconstLOG=true
1414

1515
// error logging tool
1616
exportconstSENTRY_DSN:string|null=null

‎src/services/testRunner/formatOutput.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { ParserOutput, Fail } from './parser'
44
// export const formatSuccessOutput = (tap: ParserOutput): string => {}
55

66
exportconstformatFailOutput=(tap:ParserOutput):string=>{
7-
letoutput=`FAILEDTESTS\n`
7+
letoutput=`FAILEDTEST LOG\n`
88
tap.failed.forEach((fail:Fail)=>{
99
constdetails=fail.details ?`\n${fail.details}\n` :''
1010
constlogs=fail.logs ?`\n${fail.logs.join('\n')}\n` :''

‎src/services/testRunner/index.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ import logger from '../logger'
55
importparserfrom'./parser'
66
import{debounce,throttle}from'./throttle'
77
importonErrorfrom'../sentry/onError'
8-
import{clearOutput,displayOutput}from'./output'
8+
import{clearOutput,addOutput}from'./output'
99
import{formatFailOutput}from'./formatOutput'
1010

1111
interfaceCallbacks{
1212
onSuccess(position:T.Position):void
13-
onFail(position:T.Position,message:string):void
13+
onFail(position:T.Position,failSummary:T.TestFail):void
1414
onRun(position:T.Position):void
1515
onError(position:T.Position):void
1616
}
@@ -51,20 +51,24 @@ const createTestRunner = (config: TT.TutorialTestRunnerConfig, callbacks: Callba
5151

5252
consttap=parser(stdout||'')
5353

54-
displayOutput({channel:logChannelName,text:tap.logs.join('\n'),show:false})
54+
addOutput({channel:logChannelName,text:tap.logs.join('\n'),show:false})
5555

5656
if(stderr){
5757
// FAIL also trigger stderr
5858
if(stdout&&stdout.length&&!tap.ok){
59-
constfirstFailMessage=tap.failed[0].message
60-
callbacks.onFail(position,firstFailMessage)
59+
constfirstFail=tap.failed[0]
60+
constfailSummary={
61+
title:firstFail.message||'Test Failed',
62+
description:firstFail.details||'Unknown error',
63+
}
64+
callbacks.onFail(position,failSummary)
6165
constoutput=formatFailOutput(tap)
62-
displayOutput({channel:failChannelName,text:output,show:true})
66+
addOutput({channel:failChannelName,text:output,show:true})
6367
return
6468
}else{
6569
callbacks.onError(position)
6670
// open terminal with error string
67-
displayOutput({channel:failChannelName,text:stderr,show:true})
71+
addOutput({channel:failChannelName,text:stderr,show:true})
6872
return
6973
}
7074
}

‎src/services/testRunner/output.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,25 @@ const getOutputChannel = (name: string): vscode.OutputChannel => {
99
returnchannels[name]
1010
}
1111

12-
interfaceDisplayOutput{
12+
interfaceChannelOutput{
1313
channel:string
1414
text:string
1515
show?:boolean
1616
}
1717

18-
exportconstdisplayOutput=(params:DisplayOutput)=>{
18+
exportconstaddOutput=(params:ChannelOutput)=>{
1919
constchannel=getOutputChannel(params.channel)
2020
channel.clear()
21-
channel.show(params.show||false)
2221
channel.append(params.text)
2322
}
2423

24+
exportconstshowOutput=(channelName:string)=>{
25+
constchannel=getOutputChannel(channelName)
26+
channel.show()
27+
}
28+
2529
exportconstclearOutput=(channelName:string)=>{
2630
constchannel=getOutputChannel(channelName)
27-
channel.show(false)
2831
channel.clear()
2932
channel.hide()
3033
}

‎src/webview/index.tsrenamed to‎src/services/webview/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import*aspathfrom'path'
22
import{Action}from'typings'
33
import*asvscodefrom'vscode'
4-
importChannelfrom'../channel'
4+
importChannelfrom'../../channel'
55
importrenderfrom'./render'
66

77
interfaceReactWebViewProps{

‎src/webview/render.tsrenamed to‎src/services/webview/render.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import{JSDOM}from'jsdom'
22
import*aspathfrom'path'
33
import*asvscodefrom'vscode'
4-
importonErrorfrom'../services/sentry/onError'
4+
importonErrorfrom'../sentry/onError'
55

66
constgetNonce=():string=>{
77
lettext=''

‎typings/index.d.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ export interface TestStatus {
4242
type:'success'|'warning'|'error'|'loading'
4343
title:string
4444
content?:string
45+
timeout?:number
4546
}
4647

4748
exportinterfaceMachineContext{
@@ -116,3 +117,8 @@ export interface ProcessEvent {
116117
description:string
117118
status:'RUNNING'|'SUCCESS'|'FAIL'|'ERROR'
118119
}
120+
121+
exporttypeTestFail={
122+
title:string
123+
description:string
124+
}

‎web-app/src/components/Message/index.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ interface Props {
1111
closeable?:boolean
1212
onClose?:()=>void
1313
handleClose?:()=>void
14+
children?:React.ReactElement|null
1415
}
1516

1617
constMessage=(props:Props)=>{
@@ -30,7 +31,10 @@ const Message = (props: Props) => {
3031
onClose={onClose}
3132
shape={props.shape}
3233
>
33-
{props.content}
34+
<div>
35+
<div>{props.content}</div>
36+
<div>{props.children}</div>
37+
</div>
3438
</AlifdMessage>
3539
)
3640
}

‎web-app/src/components/ProcessMessages/TestMessage.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { css, jsx } from '@emotion/core'
55

66
constdurations={
77
success:1000,
8-
warning:4500,
8+
warning:20000,
99
error:4500,
1010
loading:300000,
1111
}
@@ -24,7 +24,7 @@ const useTimeout = ({ duration, key }: { duration: number; key: string }) => {
2424
returntimeoutClose
2525
}
2626

27-
constTestMessage=(props:T.TestStatus)=>{
27+
constTestMessage=(props:T.TestStatus&{children?:React.ReactElement|null})=>{
2828
constduration=durations[props.type]
2929
consttimeoutClose=useTimeout({ duration,key:props.title})
3030
return(
@@ -36,7 +36,9 @@ const TestMessage = (props: T.TestStatus) => {
3636
size="medium"
3737
closeable={props.type!=='loading'}
3838
content={props.content}
39-
/>
39+
>
40+
{props.children}
41+
</Message>
4042
)
4143
}
4244

‎web-app/src/components/ProcessMessages/index.tsx

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
importMessagefrom'../Message'
22
import*asReactfrom'react'
33
import*asTfrom'typings'
4+
importButtonfrom'../Button'
45
import{css,jsx}from'@emotion/core'
56
importTestMessagefrom'./TestMessage'
67

78
interfaceProps{
89
testStatus?:T.TestStatus|null
910
processes:T.ProcessEvent[]
11+
onOpenLogs?:(channel:string)=>void
1012
}
1113

1214
conststyles={
@@ -17,9 +19,21 @@ const styles = {
1719
}
1820

1921
// display a list of active processes
20-
constProcessMessages=({ processes, testStatus}:Props)=>{
22+
constProcessMessages=({ processes, testStatus, onOpenLogs}:Props)=>{
2123
if(testStatus){
22-
return<TestMessage{...testStatus}/>
24+
return(
25+
<TestMessage{...testStatus}>
26+
{testStatus.type==='warning' ?(
27+
<Button
28+
onClick={()=>onOpenLogs&&onOpenLogs('CodeRoad (Tests)')}
29+
type="normal"
30+
style={{marginTop:'0.8rem'}}
31+
>
32+
Open Logs
33+
</Button>
34+
) :null}
35+
</TestMessage>
36+
)
2337
}
2438
if(!processes.length){
2539
returnnull

‎web-app/src/containers/Tutorial/components/Level.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ interface Props {
9696
testStatus:T.TestStatus|null
9797
onContinue():void
9898
onLoadSolution():void
99+
onOpenLogs(channel:string):void
99100
}
100101

101102
constLevel=({
@@ -107,6 +108,7 @@ const Level = ({
107108
status,
108109
onContinue,
109110
onLoadSolution,
111+
onOpenLogs,
110112
processes,
111113
testStatus,
112114
}:Props)=>{
@@ -170,7 +172,7 @@ const Level = ({
170172

171173
{(testStatus||processes.length>0)&&(
172174
<divcss={styles.processes}>
173-
<ProcessMessagesprocesses={processes}testStatus={testStatus}/>
175+
<ProcessMessagesprocesses={processes}testStatus={testStatus}onOpenLogs={onOpenLogs}/>
174176
</div>
175177
)}
176178

‎web-app/src/containers/Tutorial/index.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ const TutorialPage = (props: PageProps) => {
3232
props.send({type:'STEP_SOLUTION_LOAD'})
3333
}
3434

35+
constonOpenLogs=(channel:string):void=>{
36+
props.send({type:'OPEN_LOGS',payload:{ channel}})
37+
}
38+
3539
conststeps=levelData.steps.map((step:TT.Step)=>{
3640
// label step status for step component
3741
letstatus:T.ProgressStatus='INCOMPLETE'
@@ -61,6 +65,7 @@ const TutorialPage = (props: PageProps) => {
6165
status={progress.levels[position.levelId] ?'COMPLETE' :'ACTIVE'}
6266
onContinue={onContinue}
6367
onLoadSolution={onLoadSolution}
68+
onOpenLogs={onOpenLogs}
6469
processes={processes}
6570
testStatus={testStatus}
6671
/>

‎web-app/src/services/state/actions/editor.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import*asCRfrom'typings'
1+
import*asTfrom'typings'
22
import*asTTfrom'typings/tutorial'
33
import*asselectorsfrom'../../selectors'
44

@@ -8,7 +8,7 @@ export default (editorSend: any) => ({
88
type:'EDITOR_STARTUP',
99
})
1010
},
11-
configureNewTutorial(context:CR.MachineContext){
11+
configureNewTutorial(context:T.MachineContext){
1212
editorSend({
1313
type:'EDITOR_TUTORIAL_CONFIG',
1414
payload:{
@@ -17,7 +17,7 @@ export default (editorSend: any) => ({
1717
},
1818
})
1919
},
20-
continueConfig(context:CR.MachineContext){
20+
continueConfig(context:T.MachineContext){
2121
editorSend({
2222
type:'EDITOR_TUTORIAL_CONTINUE_CONFIG',
2323
payload:{
@@ -26,7 +26,7 @@ export default (editorSend: any) => ({
2626
},
2727
})
2828
},
29-
loadLevel(context:CR.MachineContext):void{
29+
loadLevel(context:T.MachineContext):void{
3030
constlevel:TT.Level=selectors.currentLevel(context)
3131
conststep:TT.Step|null=selectors.currentStep(context)
3232
// load step actions
@@ -41,7 +41,7 @@ export default (editorSend: any) => ({
4141
},
4242
})
4343
},
44-
loadStep(context:CR.MachineContext):void{
44+
loadStep(context:T.MachineContext):void{
4545
conststep:TT.Step|null=selectors.currentStep(context)
4646
if(step&&step.setup){
4747
// load step actions
@@ -58,7 +58,7 @@ export default (editorSend: any) => ({
5858
})
5959
}
6060
},
61-
editorLoadSolution(context:CR.MachineContext):void{
61+
editorLoadSolution(context:T.MachineContext):void{
6262
conststep:TT.Step|null=selectors.currentStep(context)
6363
// tell editor to load solution commit
6464
if(step&&step.solution){
@@ -74,7 +74,7 @@ export default (editorSend: any) => ({
7474
})
7575
}
7676
},
77-
syncLevelProgress(context:CR.MachineContext):void{
77+
syncLevelProgress(context:T.MachineContext):void{
7878
editorSend({
7979
type:'EDITOR_SYNC_PROGRESS',
8080
payload:{
@@ -95,4 +95,10 @@ export default (editorSend: any) => ({
9595
type:'EDITOR_REQUEST_WORKSPACE',
9696
})
9797
},
98+
editorOpenLogs(context:T.MachineContext,event:T.MachineEvent):void{
99+
editorSend({
100+
type:'EDITOR_OPEN_LOGS',
101+
payload:{channel:event.payload.channel},
102+
})
103+
},
98104
})

‎web-app/src/services/state/actions/testNotify.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ const testActions: ActionFunctionMap<CR.MachineContext, CR.MachineEvent> = {
2020
testFail:assign({
2121
testStatus:(context,event)=>({
2222
type:'warning',
23-
title:'Fail!',
24-
content:event.payload.message,
23+
title:event.payload.fail.title,
24+
content:event.payload.fail.description,
2525
}),
2626
}),
2727
//@ts-ignore

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp