Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Léo-Paul Géneau
gitlab-ce
Commits
fbf74719
Commit
fbf74719
authored
Jun 27, 2018
by
Fatih Acet
Committed by
Tim Zallmann
Jun 27, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Componentize diff lines and diff comments
parent
5c13af58
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
598 additions
and
646 deletions
+598
-646
app/assets/javascripts/diffs/components/diff_line_gutter_content.vue
...javascripts/diffs/components/diff_line_gutter_content.vue
+18
-19
app/assets/javascripts/diffs/components/diff_table_cell.vue
app/assets/javascripts/diffs/components/diff_table_cell.vue
+131
-0
app/assets/javascripts/diffs/components/diff_table_row.vue
app/assets/javascripts/diffs/components/diff_table_row.vue
+191
-0
app/assets/javascripts/diffs/components/inline_diff_comment_row.vue
.../javascripts/diffs/components/inline_diff_comment_row.vue
+82
-0
app/assets/javascripts/diffs/components/inline_diff_view.vue
app/assets/javascripts/diffs/components/inline_diff_view.vue
+15
-94
app/assets/javascripts/diffs/components/parallel_diff_comment_row.vue
...avascripts/diffs/components/parallel_diff_comment_row.vue
+129
-0
app/assets/javascripts/diffs/components/parallel_diff_view.vue
...ssets/javascripts/diffs/components/parallel_diff_view.vue
+18
-187
app/assets/javascripts/diffs/constants.js
app/assets/javascripts/diffs/constants.js
+2
-0
app/assets/javascripts/diffs/mixins/diff_content.js
app/assets/javascripts/diffs/mixins/diff_content.js
+7
-39
app/assets/stylesheets/highlight/white_base.scss
app/assets/stylesheets/highlight/white_base.scss
+3
-1
spec/javascripts/diffs/components/diff_line_gutter_content_spec.js
...scripts/diffs/components/diff_line_gutter_content_spec.js
+1
-46
spec/javascripts/diffs/components/inline_diff_view_spec.js
spec/javascripts/diffs/components/inline_diff_view_spec.js
+1
-65
spec/javascripts/diffs/components/parallel_diff_view_spec.js
spec/javascripts/diffs/components/parallel_diff_view_spec.js
+0
-195
No files found.
app/assets/javascripts/diffs/components/diff_line_gutter_content.vue
View file @
fbf74719
...
...
@@ -4,14 +4,7 @@ import { s__ } from '~/locale';
import
{
mapState
,
mapGetters
,
mapActions
}
from
'
vuex
'
;
import
Icon
from
'
~/vue_shared/components/icon.vue
'
;
import
DiffGutterAvatars
from
'
./diff_gutter_avatars.vue
'
;
import
{
MATCH_LINE_TYPE
,
CONTEXT_LINE_TYPE
,
OLD_NO_NEW_LINE_TYPE
,
NEW_NO_NEW_LINE_TYPE
,
LINE_POSITION_RIGHT
,
UNFOLD_COUNT
,
}
from
'
../constants
'
;
import
{
LINE_POSITION_RIGHT
,
UNFOLD_COUNT
}
from
'
../constants
'
;
import
*
as
utils
from
'
../store/utils
'
;
export
default
{
...
...
@@ -63,6 +56,21 @@ export default {
required
:
false
,
default
:
false
,
},
isMatchLine
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
isMetaLine
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
isContextLine
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
},
computed
:
{
...
mapState
({
...
...
@@ -70,15 +78,6 @@ export default {
diffFiles
:
state
=>
state
.
diffs
.
diffFiles
,
}),
...
mapGetters
([
'
isLoggedIn
'
,
'
discussionsByLineCode
'
]),
isMatchLine
()
{
return
this
.
lineType
===
MATCH_LINE_TYPE
;
},
isContextLine
()
{
return
this
.
lineType
===
CONTEXT_LINE_TYPE
;
},
isMetaLine
()
{
return
this
.
lineType
===
OLD_NO_NEW_LINE_TYPE
||
this
.
lineType
===
NEW_NO_NEW_LINE_TYPE
;
},
lineHref
()
{
return
this
.
lineCode
?
`#
${
this
.
lineCode
}
`
:
'
#
'
;
},
...
...
@@ -109,9 +108,9 @@ export default {
},
},
methods
:
{
...
mapActions
([
'
loadMoreLines
'
]),
...
mapActions
([
'
loadMoreLines
'
,
'
showCommentForm
'
]),
handleCommentButton
()
{
this
.
$emit
(
'
showCommentForm
'
,
{
lineCode
:
this
.
lineCode
});
this
.
showCommentForm
(
{
lineCode
:
this
.
lineCode
});
},
handleLoadMoreLines
()
{
if
(
this
.
isRequesting
)
{
...
...
app/assets/javascripts/diffs/components/diff_table_cell.vue
0 → 100644
View file @
fbf74719
<
script
>
import
{
mapGetters
}
from
'
vuex
'
;
import
DiffLineGutterContent
from
'
./diff_line_gutter_content.vue
'
;
import
{
MATCH_LINE_TYPE
,
CONTEXT_LINE_TYPE
,
EMPTY_CELL_TYPE
,
OLD_LINE_TYPE
,
OLD_NO_NEW_LINE_TYPE
,
NEW_NO_NEW_LINE_TYPE
,
LINE_HOVER_CLASS_NAME
,
LINE_UNFOLD_CLASS_NAME
,
}
from
'
../constants
'
;
export
default
{
components
:
{
DiffLineGutterContent
,
},
props
:
{
line
:
{
type
:
Object
,
required
:
true
,
},
diffFile
:
{
type
:
Object
,
required
:
true
,
},
showCommentButton
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
linePosition
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
lineType
:
{
type
:
String
,
required
:
false
,
default
:
''
,
},
isContentLine
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
isBottom
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
isHover
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
},
computed
:
{
...
mapGetters
([
'
isLoggedIn
'
,
'
isInlineView
'
]),
normalizedLine
()
{
if
(
this
.
isInlineView
)
{
return
this
.
line
;
}
return
this
.
lineType
===
OLD_LINE_TYPE
?
this
.
line
.
left
:
this
.
line
.
right
;
},
isMatchLine
()
{
return
this
.
normalizedLine
.
type
===
MATCH_LINE_TYPE
;
},
isContextLine
()
{
return
this
.
normalizedLine
.
type
===
CONTEXT_LINE_TYPE
;
},
isMetaLine
()
{
return
(
this
.
normalizedLine
.
type
===
OLD_NO_NEW_LINE_TYPE
||
this
.
normalizedLine
.
type
===
NEW_NO_NEW_LINE_TYPE
||
this
.
normalizedLine
.
type
===
EMPTY_CELL_TYPE
);
},
classNameMap
()
{
const
{
type
}
=
this
.
normalizedLine
;
return
{
[
type
]:
type
,
[
LINE_UNFOLD_CLASS_NAME
]:
this
.
isMatchLine
,
[
LINE_HOVER_CLASS_NAME
]:
this
.
isLoggedIn
&&
this
.
isHover
&&
!
this
.
isMatchLine
&&
!
this
.
isContextLine
&&
!
this
.
isMetaLine
,
};
},
lineNumber
()
{
const
{
lineType
,
normalizedLine
}
=
this
;
return
lineType
===
OLD_LINE_TYPE
?
normalizedLine
.
oldLine
:
normalizedLine
.
newLine
;
},
},
};
</
script
>
<
template
>
<td
v-if=
"isContentLine"
:class=
"lineType"
class=
"line_content"
v-html=
"normalizedLine.richText"
>
</td>
<td
v-else
:class=
"classNameMap"
>
<diff-line-gutter-content
:file-hash=
"diffFile.fileHash"
:line-type=
"normalizedLine.type"
:line-code=
"normalizedLine.lineCode"
:line-position=
"linePosition"
:line-number=
"lineNumber"
:meta-data=
"normalizedLine.metaData"
:show-comment-button=
"showCommentButton"
:context-lines-path=
"diffFile.contextLinesPath"
:is-bottom=
"isBottom"
:is-match-line=
"isMatchLine"
:is-context-line=
"isContentLine"
:is-meta-line=
"isMetaLine"
/>
</td>
</
template
>
app/assets/javascripts/diffs/components/diff_table_row.vue
0 → 100644
View file @
fbf74719
<
script
>
import
$
from
'
jquery
'
;
import
{
mapGetters
}
from
'
vuex
'
;
import
DiffTableCell
from
'
./diff_table_cell.vue
'
;
import
{
NEW_LINE_TYPE
,
OLD_LINE_TYPE
,
CONTEXT_LINE_TYPE
,
CONTEXT_LINE_CLASS_NAME
,
OLD_NO_NEW_LINE_TYPE
,
PARALLEL_DIFF_VIEW_TYPE
,
NEW_NO_NEW_LINE_TYPE
,
LINE_POSITION_LEFT
,
LINE_POSITION_RIGHT
,
}
from
'
../constants
'
;
export
default
{
components
:
{
DiffTableCell
,
},
props
:
{
diffFile
:
{
type
:
Object
,
required
:
true
,
},
line
:
{
type
:
Object
,
required
:
true
,
},
isBottom
:
{
type
:
Boolean
,
required
:
false
,
default
:
false
,
},
},
data
()
{
return
{
isHover
:
false
,
isLeftHover
:
false
,
isRightHover
:
false
,
};
},
computed
:
{
...
mapGetters
([
'
isInlineView
'
,
'
isParallelView
'
]),
isContextLine
()
{
return
this
.
line
.
left
?
this
.
line
.
left
.
type
===
CONTEXT_LINE_TYPE
:
this
.
line
.
type
===
CONTEXT_LINE_TYPE
;
},
classNameMap
()
{
return
{
[
this
.
line
.
type
]:
this
.
line
.
type
,
[
CONTEXT_LINE_CLASS_NAME
]:
this
.
isContextLine
,
[
PARALLEL_DIFF_VIEW_TYPE
]:
this
.
isParallelView
,
};
},
inlineRowId
()
{
const
{
lineCode
,
oldLine
,
newLine
}
=
this
.
line
;
return
lineCode
||
`
${
this
.
diffFile
.
fileHash
}
_
${
oldLine
}
_
${
newLine
}
`
;
},
parallelViewLeftLineType
()
{
if
(
this
.
line
.
right
.
type
===
NEW_NO_NEW_LINE_TYPE
)
{
return
OLD_NO_NEW_LINE_TYPE
;
}
return
this
.
line
.
left
.
type
;
},
},
created
()
{
this
.
newLineType
=
NEW_LINE_TYPE
;
this
.
oldLineType
=
OLD_LINE_TYPE
;
this
.
linePositionLeft
=
LINE_POSITION_LEFT
;
this
.
linePositionRight
=
LINE_POSITION_RIGHT
;
},
methods
:
{
handleMouseMove
(
e
)
{
const
isHover
=
e
.
type
===
'
mouseover
'
;
if
(
this
.
isInlineView
)
{
this
.
isHover
=
isHover
;
}
else
{
const
hoveringCell
=
e
.
target
.
closest
(
'
td
'
);
const
allCellsInHoveringRow
=
Array
.
from
(
e
.
currentTarget
.
children
);
const
hoverIndex
=
allCellsInHoveringRow
.
indexOf
(
hoveringCell
);
if
(
hoverIndex
>=
2
)
{
this
.
isRightHover
=
isHover
;
}
else
{
this
.
isLeftHover
=
isHover
;
}
}
},
// Prevent text selecting on both sides of parallel diff view
// Backport of the same code from legacy diff notes.
handleParallelLineMouseDown
(
e
)
{
const
line
=
$
(
e
.
currentTarget
);
const
table
=
line
.
closest
(
'
table
'
);
table
.
removeClass
(
'
left-side-selected right-side-selected
'
);
const
[
lineClass
]
=
[
'
left-side
'
,
'
right-side
'
].
filter
(
name
=>
line
.
hasClass
(
name
));
if
(
lineClass
)
{
table
.
addClass
(
`
${
lineClass
}
-selected`
);
}
},
},
};
</
script
>
<
template
>
<tr
v-if=
"isInlineView"
:id=
"inlineRowId"
:class=
"classNameMap"
class=
"line_holder"
@
mouseover=
"handleMouseMove"
@
mouseout=
"handleMouseMove"
>
<diff-table-cell
:diff-file=
"diffFile"
:line=
"line"
:line-type=
"oldLineType"
:is-bottom=
"isBottom"
:is-hover=
"isHover"
:show-comment-button=
"true"
class=
"diff-line-num old_line"
/>
<diff-table-cell
:diff-file=
"diffFile"
:line=
"line"
:line-type=
"newLineType"
:is-bottom=
"isBottom"
:is-hover=
"isHover"
class=
"diff-line-num new_line"
/>
<diff-table-cell
:class=
"line.type"
:diff-file=
"diffFile"
:line=
"line"
:is-content-line=
"true"
/>
</tr>
<tr
v-else
:class=
"classNameMap"
class=
"line_holder"
@
mouseover=
"handleMouseMove"
@
mouseout=
"handleMouseMove"
>
<diff-table-cell
:diff-file=
"diffFile"
:line=
"line"
:line-type=
"oldLineType"
:line-position=
"linePositionLeft"
:is-bottom=
"isBottom"
:is-hover=
"isLeftHover"
:show-comment-button=
"true"
class=
"diff-line-num old_line"
/>
<diff-table-cell
:id=
"line.left.lineCode"
:diff-file=
"diffFile"
:line=
"line"
:is-content-line=
"true"
:line-type=
"parallelViewLeftLineType"
class=
"line_content parallel left-side"
@
mousedown.native=
"handleParallelLineMouseDown"
/>
<diff-table-cell
:diff-file=
"diffFile"
:line=
"line"
:line-type=
"newLineType"
:line-position=
"linePositionRight"
:is-bottom=
"isBottom"
:is-hover=
"isRightHover"
:show-comment-button=
"true"
class=
"diff-line-num new_line"
/>
<diff-table-cell
:id=
"line.right.lineCode"
:diff-file=
"diffFile"
:line=
"line"
:is-content-line=
"true"
:line-type=
"line.right.type"
class=
"line_content parallel right-side"
@
mousedown.native=
"handleParallelLineMouseDown"
/>
</tr>
</
template
>
app/assets/javascripts/diffs/components/inline_diff_comment_row.vue
0 → 100644
View file @
fbf74719
<
script
>
import
{
mapState
,
mapGetters
}
from
'
vuex
'
;
import
diffDiscussions
from
'
./diff_discussions.vue
'
;
import
diffLineNoteForm
from
'
./diff_line_note_form.vue
'
;
export
default
{
components
:
{
diffDiscussions
,
diffLineNoteForm
,
},
props
:
{
line
:
{
type
:
Object
,
required
:
true
,
},
diffFile
:
{
type
:
Object
,
required
:
true
,
},
diffLines
:
{
type
:
Array
,
required
:
true
,
},
lineIndex
:
{
type
:
Number
,
required
:
true
,
},
},
computed
:
{
...
mapState
({
diffLineCommentForms
:
state
=>
state
.
diffs
.
diffLineCommentForms
,
}),
...
mapGetters
([
'
discussionsByLineCode
'
]),
isDiscussionExpanded
()
{
if
(
!
this
.
discussions
.
length
)
{
return
false
;
}
return
this
.
discussions
.
every
(
discussion
=>
discussion
.
expanded
);
},
hasCommentForm
()
{
return
this
.
diffLineCommentForms
[
this
.
line
.
lineCode
];
},
discussions
()
{
return
this
.
discussionsByLineCode
[
this
.
line
.
lineCode
]
||
[];
},
shouldRender
()
{
return
this
.
isDiscussionExpanded
||
this
.
hasCommentForm
;
},
className
()
{
return
this
.
discussions
.
length
?
''
:
'
js-temp-notes-holder
'
;
},
},
};
</
script
>
<
template
>
<tr
v-if=
"shouldRender"
:class=
"className"
class=
"notes_holder"
>
<td
class=
"notes_line"
colspan=
"2"
></td>
<td
class=
"notes_content"
>
<div
class=
"content"
>
<diff-discussions
:discussions=
"discussions"
/>
<diff-line-note-form
v-if=
"diffLineCommentForms[line.lineCode]"
:diff-file=
"diffFile"
:diff-lines=
"diffLines"
:line=
"line"
:note-target-line=
"diffLines[lineIndex]"
/>
</div>
</td>
</tr>
</
template
>
app/assets/javascripts/diffs/components/inline_diff_view.vue
View file @
fbf74719
<
script
>
import
diffContentMixin
from
'
../mixins/diff_content
'
;
import
{
MATCH_LINE_TYPE
,
CONTEXT_LINE_TYPE
,
OLD_NO_NEW_LINE_TYPE
,
NEW_NO_NEW_LINE_TYPE
,
LINE_HOVER_CLASS_NAME
,
LINE_UNFOLD_CLASS_NAME
,
}
from
'
../constants
'
;
import
inlineDiffCommentRow
from
'
./inline_diff_comment_row.vue
'
;
export
default
{
mixins
:
[
diffContentMixin
],
methods
:
{
handleMouse
(
lineCode
,
isOver
)
{
this
.
hoveredLineCode
=
isOver
?
lineCode
:
null
;
},
getLineClass
(
line
)
{
const
isSameLine
=
this
.
hoveredLineCode
&&
this
.
hoveredLineCode
===
line
.
lineCode
;
const
isMatchLine
=
line
.
type
===
MATCH_LINE_TYPE
;
const
isContextLine
=
line
.
type
===
CONTEXT_LINE_TYPE
;
const
isMetaLine
=
line
.
type
===
OLD_NO_NEW_LINE_TYPE
||
line
.
type
===
NEW_NO_NEW_LINE_TYPE
;
return
{
[
line
.
type
]:
line
.
type
,
[
LINE_UNFOLD_CLASS_NAME
]:
isMatchLine
,
[
LINE_HOVER_CLASS_NAME
]:
this
.
isLoggedIn
&&
isSameLine
&&
!
isMatchLine
&&
!
isContextLine
&&
!
isMetaLine
,
};
},
components
:
{
inlineDiffCommentRow
,
},
mixins
:
[
diffContentMixin
],
};
</
script
>
...
...
@@ -41,76 +19,19 @@ export default {
<template
v-for=
"(line, index) in normalizedDiffLines"
>
<tr
:id=
"line.lineCode || `$
{fileHash}_${line.oldLine}_${line.newLine}`"
<diff-table-row
:diff-file=
"diffFile"
:line=
"line"
:is-bottom=
"index + 1 === diffLinesLength"
:key=
"line.lineCode"
:class="getRowClass(line)"
class="line_holder"
@mouseover="handleMouse(line.lineCode, true)"
@mouseout="handleMouse(line.lineCode, false)"
>
<td
:class=
"getLineClass(line)"
class=
"diff-line-num old_line"
>
<diff-line-gutter-content
:file-hash=
"fileHash"
:line-type=
"line.type"
:line-code=
"line.lineCode"
:line-number=
"line.oldLine"
:meta-data=
"line.metaData"
:show-comment-button=
"true"
:context-lines-path=
"diffFile.contextLinesPath"
:is-bottom=
"index + 1 === diffLinesLength"
@
showCommentForm=
"handleShowCommentForm"
/>
</td>
<td
:class=
"getLineClass(line)"
class=
"diff-line-num new_line"
>
<diff-line-gutter-content
:file-hash=
"fileHash"
:line-type=
"line.type"
:line-code=
"line.lineCode"
:line-number=
"line.newLine"
:meta-data=
"line.metaData"
:is-bottom=
"index + 1 === diffLinesLength"
:context-lines-path=
"diffFile.contextLinesPath"
/>
</td>
<td
:class=
"line.type"
class=
"line_content"
v-html=
"line.richText"
>
</td>
</tr>
<tr
v-if=
"isDiscussionExpanded(line.lineCode) || diffLineCommentForms[line.lineCode]"
/>
<inline-diff-comment-row
:diff-file=
"diffFile"
:diff-lines=
"normalizedDiffLines"
:line=
"line"
:line-index=
"index"
:key=
"index"
:class=
"discussionsByLineCode[line.lineCode] ? '' : 'js-temp-notes-holder'"
class=
"notes_holder"
>
<td
class=
"notes_line"
colspan=
"2"
></td>
<td
class=
"notes_content"
>
<div
class=
"content"
>
<diff-discussions
:discussions=
"discussionsByLineCode[line.lineCode] || []"
/>
<diff-line-note-form
v-if=
"diffLineCommentForms[line.lineCode]"
:diff-file=
"diffFile"
:diff-lines=
"diffLines"
:line=
"line"
:note-target-line=
"diffLines[index]"
/>
</div>
</td>
</tr>
/>
</
template
>
</tbody>
</table>
...
...
app/assets/javascripts/diffs/components/parallel_diff_comment_row.vue
0 → 100644
View file @
fbf74719
<
script
>
import
{
mapState
,
mapGetters
}
from
'
vuex
'
;
import
diffDiscussions
from
'
./diff_discussions.vue
'
;
import
diffLineNoteForm
from
'
./diff_line_note_form.vue
'
;
export
default
{
components
:
{
diffDiscussions
,
diffLineNoteForm
,
},
props
:
{
line
:
{
type
:
Object
,
required
:
true
,
},
diffFile
:
{
type
:
Object
,
required
:
true
,
},
diffLines
:
{
type
:
Array
,
required
:
true
,
},
lineIndex
:
{
type
:
Number
,
required
:
true
,
},
},
computed
:
{
...
mapState
({
diffLineCommentForms
:
state
=>
state
.
diffs
.
diffLineCommentForms
,
}),
...
mapGetters
([
'
discussionsByLineCode
'
]),
leftLineCode
()
{
return
this
.
line
.
left
.
lineCode
;
},
rightLineCode
()
{
return
this
.
line
.
right
.
lineCode
;
},
hasDiscussion
()
{
const
discussions
=
this
.
discussionsByLineCode
;
return
discussions
[
this
.
leftLineCode
]
||
discussions
[
this
.
rightLineCode
];
},
hasExpandedDiscussionOnLeft
()
{
const
discussions
=
this
.
discussionsByLineCode
[
this
.
leftLineCode
];
return
discussions
?
discussions
.
every
(
discussion
=>
discussion
.
expanded
)
:
false
;
},
hasExpandedDiscussionOnRight
()
{
const
discussions
=
this
.
discussionsByLineCode
[
this
.
rightLineCode
];
return
discussions
?
discussions
.
every
(
discussion
=>
discussion
.
expanded
)
:
false
;
},
hasAnyExpandedDiscussion
()
{
return
this
.
hasExpandedDiscussionOnLeft
||
this
.
hasExpandedDiscussionOnRight
;
},
shouldRenderDiscussionsRow
()
{
const
hasDiscussion
=
this
.
hasDiscussion
&&
this
.
hasAnyExpandedDiscussion
;
const
hasCommentFormOnLeft
=
this
.
diffLineCommentForms
[
this
.
leftLineCode
];
const
hasCommentFormOnRight
=
this
.
diffLineCommentForms
[
this
.
rightLineCode
];
return
hasDiscussion
||
hasCommentFormOnLeft
||
hasCommentFormOnRight
;
},
shouldRenderDiscussionsOnLeft
()
{
return
this
.
discussionsByLineCode
[
this
.
leftLineCode
]
&&
this
.
hasExpandedDiscussionOnLeft
;
},
shouldRenderDiscussionsOnRight
()
{
return
(
this
.
discussionsByLineCode
[
this
.
rightLineCode
]
&&
this
.
hasExpandedDiscussionOnRight
&&
this
.
line
.
right
.
type
);
},
className
()
{
return
this
.
hasDiscussion
?
''
:
'
js-temp-notes-holder
'
;
},
},
};
</
script
>
<
template
>
<tr
v-if=
"shouldRenderDiscussionsRow"
:class=
"className"
class=
"notes_holder"
>
<td
class=
"notes_line old"
></td>
<td
class=
"notes_content parallel old"
>
<div
v-if=
"shouldRenderDiscussionsOnLeft"
class=
"content"
>
<diff-discussions
:discussions=
"discussionsByLineCode[leftLineCode]"
/>
</div>
<diff-line-note-form
v-if=
"diffLineCommentForms[leftLineCode] &&
diffLineCommentForms[leftLineCode]"
:diff-file=
"diffFile"
:diff-lines=
"diffLines"
:line=
"line.left"
:note-target-line=
"diffLines[lineIndex].left"
position=
"left"
/>
</td>
<td
class=
"notes_line new"
></td>
<td
class=
"notes_content parallel new"
>
<div
v-if=
"shouldRenderDiscussionsOnRight"
class=
"content"
>
<diff-discussions
:discussions=
"discussionsByLineCode[rightLineCode]"
/>
</div>
<diff-line-note-form
v-if=
"diffLineCommentForms[rightLineCode] &&
diffLineCommentForms[rightLineCode] && line.right.type"
:diff-file=
"diffFile"
:diff-lines=
"diffLines"
:line=
"line.right"
:note-target-line=
"diffLines[lineIndex].right"
position=
"right"
/>
</td>
</tr>
</
template
>
app/assets/javascripts/diffs/components/parallel_diff_view.vue
View file @
fbf74719
<
script
>
import
diffContentMixin
from
'
../mixins/diff_content
'
;
import
{
EMPTY_CELL_TYPE
,
MATCH_LINE_TYPE
,
CONTEXT_LINE_TYPE
,
OLD_NO_NEW_LINE_TYPE
,
NEW_NO_NEW_LINE_TYPE
,
LINE_HOVER_CLASS_NAME
,
LINE_UNFOLD_CLASS_NAME
,
LINE_POSITION_RIGHT
,
}
from
'
../constants
'
;
import
parallelDiffCommentRow
from
'
./parallel_diff_comment_row.vue
'
;
import
{
EMPTY_CELL_TYPE
}
from
'
../constants
'
;
export
default
{
components
:
{
parallelDiffCommentRow
,
},
mixins
:
[
diffContentMixin
],
computed
:
{
parallelDiffLines
()
{
...
...
@@ -26,77 +21,6 @@ export default {
});
},
},
methods
:
{
hasDiscussion
(
line
)
{
const
discussions
=
this
.
discussionsByLineCode
;
const
hasDiscussion
=
discussions
[
line
.
left
.
lineCode
]
||
discussions
[
line
.
right
.
lineCode
];
return
hasDiscussion
;
},
getClassName
(
line
,
position
)
{
const
{
type
,
lineCode
}
=
line
[
position
];
const
isMatchLine
=
type
===
MATCH_LINE_TYPE
;
const
isContextLine
=
!
isMatchLine
&&
type
!==
EMPTY_CELL_TYPE
&&
type
!==
CONTEXT_LINE_TYPE
;
const
isMetaLine
=
type
===
OLD_NO_NEW_LINE_TYPE
||
type
===
NEW_NO_NEW_LINE_TYPE
;
const
isSameLine
=
this
.
hoveredLineCode
&&
this
.
hoveredLineCode
===
lineCode
;
const
isSameSection
=
position
===
this
.
hoveredSection
;
return
{
[
type
]:
type
,
[
LINE_UNFOLD_CLASS_NAME
]:
isMatchLine
,
[
LINE_HOVER_CLASS_NAME
]:
this
.
isLoggedIn
&&
isContextLine
&&
isSameLine
&&
isSameSection
&&
!
isMetaLine
,
};
},
handleMouse
(
e
,
line
,
isHover
)
{
if
(
isHover
)
{
const
cell
=
e
.
target
.
closest
(
'
td
'
);
if
(
this
.
$refs
.
leftLines
.
indexOf
(
cell
)
>
-
1
)
{
this
.
hoveredLineCode
=
line
.
left
.
lineCode
;
this
.
hoveredSection
=
'
left
'
;
}
else
if
(
this
.
$refs
.
rightLines
.
indexOf
(
cell
)
>
-
1
)
{
this
.
hoveredLineCode
=
line
.
right
.
lineCode
;
this
.
hoveredSection
=
'
right
'
;
}
}
else
{
this
.
hoveredLineCode
=
null
;
this
.
hoveredSection
=
null
;
}
},
shouldRenderDiscussionsRow
(
line
)
{
const
hasDiscussion
=
this
.
hasDiscussion
(
line
)
&&
this
.
hasAnyExpandedDiscussion
(
line
);
const
hasCommentFormOnLeft
=
this
.
diffLineCommentForms
[
line
.
left
.
lineCode
];
const
hasCommentFormOnRight
=
this
.
diffLineCommentForms
[
line
.
right
.
lineCode
];
return
hasDiscussion
||
hasCommentFormOnLeft
||
hasCommentFormOnRight
;
},
shouldRenderDiscussions
(
line
,
position
)
{
const
{
lineCode
}
=
line
[
position
];
let
render
=
this
.
discussionsByLineCode
[
lineCode
]
&&
this
.
isDiscussionExpanded
(
lineCode
);
// Avoid rendering context line discussions on the right side in parallel view
if
(
position
===
LINE_POSITION_RIGHT
)
{
render
=
render
&&
line
.
right
.
type
;
}
return
render
;
},
hasAnyExpandedDiscussion
(
line
)
{
const
isLeftExpanded
=
this
.
isDiscussionExpanded
(
line
.
left
.
lineCode
);
const
isRightExpanded
=
this
.
isDiscussionExpanded
(
line
.
right
.
lineCode
);
return
isLeftExpanded
||
isRightExpanded
;
},
getLineCode
(
line
,
side
)
{
const
{
lineCode
}
=
side
;
if
(
lineCode
)
{
return
lineCode
;
}
return
`
${
this
.
fileHash
}
_
${
line
.
left
.
oldLine
}
_
${
line
.
right
.
newLine
}
`
;
},
},
};
</
script
>
...
...
@@ -104,119 +28,26 @@ export default {
<div
:class=
"userColorScheme"
:data-commit-id=
"commitId"
class=
"code diff-wrap-lines js-syntax-highlight text-file"
>
class=
"code diff-wrap-lines js-syntax-highlight text-file"
>
<table>
<tbody>
<template
v-for=
"(line, index) in parallelDiffLines"
>
<tr
<diff-table-row
:diff-file=
"diffFile"
:line=
"line"
:is-bottom=
"index + 1 === diffLinesLength"
:key=
"index"
:class=
"getRowClass(line)"
class=
"line_holder parallel"
@
mouseover=
"handleMouse($event, line, true)"
@
mouseout=
"handleMouse($event, line, false)"
>
<td
ref=
"leftLines"
:class=
"getClassName(line, 'left')"
class=
"diff-line-num old_line"
>
<diff-line-gutter-content
:file-hash=
"fileHash"
:line-type=
"line.left.type"
:line-code=
"line.left.lineCode"
:line-number=
"line.left.oldLine"
:meta-data=
"line.left.metaData"
:show-comment-button=
"true"
:context-lines-path=
"diffFile.contextLinesPath"
:is-bottom=
"index + 1 === diffLinesLength"
line-position=
"left"
@
showCommentForm=
"handleShowCommentForm"
/>
</td>
<td
ref=
"leftLines"
:class=
"getClassName(line, 'left')"
:id=
"getLineCode(line, line.left)"
class=
"line_content parallel left-side"
v-html=
"line.left.richText"
>
</td>
<td
ref=
"rightLines"
:class=
"getClassName(line, 'right')"
class=
"diff-line-num new_line"
>
<diff-line-gutter-content
:file-hash=
"fileHash"
:line-type=
"line.right.type"
:line-code=
"line.right.lineCode"
:line-number=
"line.right.newLine"
:meta-data=
"line.right.metaData"
:show-comment-button=
"true"
:context-lines-path=
"diffFile.contextLinesPath"
:is-bottom=
"index + 1 === diffLinesLength"
line-position=
"right"
@
showCommentForm=
"handleShowCommentForm"
/>
</td>
<td
ref=
"rightLines"
:class=
"getClassName(line, 'right')"
:id=
"getLineCode(line, line.right)"
class=
"line_content parallel right-side"
v-html=
"line.right.richText"
>
</td>
</tr>
<tr
v-if=
"shouldRenderDiscussionsRow(line)"
/>
<parallel-diff-comment-row
:key=
"line.left.lineCode || line.right.lineCode"
:class=
"hasDiscussion(line) ? '' : 'js-temp-notes-holder'"
class=
"notes_holder"
>
<td
class=
"notes_line old"
></td>
<td
class=
"notes_content parallel old"
>
<div
v-if=
"shouldRenderDiscussions(line, 'left')"
class=
"content"
>
<diff-discussions
:discussions=
"discussionsByLineCode[line.left.lineCode]"
/>
</div>
<diff-line-note-form
v-if=
"diffLineCommentForms[line.left.lineCode] &&
diffLineCommentForms[line.left.lineCode]"
:diff-file=
"diffFile"
:diff-lines=
"diffLines"
:line=
"line.left"
:note-target-line=
"diffLines[index].left"
position=
"left"
/>
</td>
<td
class=
"notes_line new"
></td>
<td
class=
"notes_content parallel new"
>
<div
v-if=
"shouldRenderDiscussions(line, 'right')"
class=
"content"
>
<diff-discussions
:discussions=
"discussionsByLineCode[line.right.lineCode]"
/>
</div>
<diff-line-note-form
v-if=
"diffLineCommentForms[line.right.lineCode] &&
diffLineCommentForms[line.right.lineCode] && line.right.type"
:diff-file=
"diffFile"
:diff-lines=
"diffLines"
:line=
"line.right"
:note-target-line=
"diffLines[index].right"
position=
"right"
/>
</td>
</tr>
:line=
"line"
:diff-file=
"diffFile"
:diff-lines=
"parallelDiffLines"
:line-index=
"index"
/>
</
template
>
</tbody>
</table>
...
...
app/assets/javascripts/diffs/constants.js
View file @
fbf74719
...
...
@@ -14,6 +14,8 @@ export const TEXT_DIFF_POSITION_TYPE = 'text';
export
const
LINE_POSITION_LEFT
=
'
left
'
;
export
const
LINE_POSITION_RIGHT
=
'
right
'
;
export
const
LINE_SIDE_LEFT
=
'
left-side
'
;
export
const
LINE_SIDE_RIGHT
=
'
right-side
'
;
export
const
DIFF_VIEW_COOKIE_NAME
=
'
diff_view
'
;
export
const
LINE_HOVER_CLASS_NAME
=
'
is-over
'
;
...
...
app/assets/javascripts/diffs/mixins/diff_content.js
View file @
fbf74719
import
{
map
State
,
mapGetters
,
mapAction
s
}
from
'
vuex
'
;
import
{
map
Getter
s
}
from
'
vuex
'
;
import
diffDiscussions
from
'
../components/diff_discussions.vue
'
;
import
diffLineGutterContent
from
'
../components/diff_line_gutter_content.vue
'
;
import
diffLineNoteForm
from
'
../components/diff_line_note_form.vue
'
;
import
diffTableRow
from
'
../components/diff_table_row.vue
'
;
import
{
trimFirstCharOfLineContent
}
from
'
../store/utils
'
;
import
{
CONTEXT_LINE_TYPE
,
CONTEXT_LINE_CLASS_NAME
}
from
'
../constants
'
;
export
default
{
props
:
{
...
...
@@ -16,22 +16,14 @@ export default {
required
:
true
,
},
},
data
()
{
return
{
hoveredLineCode
:
null
,
hoveredSection
:
null
,
};
},
components
:
{
diffDiscussions
,
diffTableRow
,
diffLineNoteForm
,
diffLineGutterContent
,
},
computed
:
{
...
mapState
({
diffLineCommentForms
:
state
=>
state
.
diffs
.
diffLineCommentForms
,
}),
...
mapGetters
([
'
discussionsByLineCode
'
,
'
isLoggedIn
'
,
'
commit
'
]),
...
mapGetters
([
'
commit
'
]),
commitId
()
{
return
this
.
commit
&&
this
.
commit
.
id
;
},
...
...
@@ -41,15 +33,15 @@ export default {
normalizedDiffLines
()
{
return
this
.
diffLines
.
map
(
line
=>
{
if
(
line
.
richText
)
{
return
t
his
.
trimFirstChar
(
line
);
return
t
rimFirstCharOfLineContent
(
line
);
}
if
(
line
.
left
)
{
Object
.
assign
(
line
,
{
left
:
t
his
.
trimFirstChar
(
line
.
left
)
});
Object
.
assign
(
line
,
{
left
:
t
rimFirstCharOfLineContent
(
line
.
left
)
});
}
if
(
line
.
right
)
{
Object
.
assign
(
line
,
{
right
:
t
his
.
trimFirstChar
(
line
.
right
)
});
Object
.
assign
(
line
,
{
right
:
t
rimFirstCharOfLineContent
(
line
.
right
)
});
}
return
line
;
...
...
@@ -62,28 +54,4 @@ export default {
return
this
.
diffFile
.
fileHash
;
},
},
methods
:
{
...
mapActions
([
'
showCommentForm
'
,
'
cancelCommentForm
'
]),
getRowClass
(
line
)
{
const
isContextLine
=
line
.
left
?
line
.
left
.
type
===
CONTEXT_LINE_TYPE
:
line
.
type
===
CONTEXT_LINE_TYPE
;
return
{
[
line
.
type
]:
line
.
type
,
[
CONTEXT_LINE_CLASS_NAME
]:
isContextLine
,
};
},
trimFirstChar
(
line
)
{
return
trimFirstCharOfLineContent
(
line
);
},
handleShowCommentForm
(
params
)
{
this
.
showCommentForm
({
lineCode
:
params
.
lineCode
});
},
isDiscussionExpanded
(
lineCode
)
{
const
discussions
=
this
.
discussionsByLineCode
[
lineCode
];
return
discussions
?
discussions
.
every
(
discussion
=>
discussion
.
expanded
)
:
false
;
},
},
};
app/assets/stylesheets/highlight/white_base.scss
View file @
fbf74719
...
...
@@ -102,7 +102,9 @@ pre.code,
// Diff line
.line_holder
{
&
.match
.line_content
{
&
.match
.line_content
,
.new-nonewline.line_content
,
.old-nonewline.line_content
{
@include
matchLine
;
}
...
...
spec/javascripts/diffs/components/diff_line_gutter_content_spec.js
View file @
fbf74719
...
...
@@ -2,12 +2,6 @@ import Vue from 'vue';
import
DiffLineGutterContent
from
'
~/diffs/components/diff_line_gutter_content.vue
'
;
import
store
from
'
~/mr_notes/stores
'
;
import
{
createComponentWithStore
}
from
'
spec/helpers/vue_mount_component_helper
'
;
import
{
MATCH_LINE_TYPE
,
CONTEXT_LINE_TYPE
,
OLD_NO_NEW_LINE_TYPE
,
NEW_NO_NEW_LINE_TYPE
,
}
from
'
~/diffs/constants
'
;
import
discussionsMockData
from
'
../mock_data/diff_discussions
'
;
import
diffFileMockData
from
'
../mock_data/diff_file
'
;
...
...
@@ -31,45 +25,6 @@ describe('DiffLineGutterContent', () => {
};
describe
(
'
computed
'
,
()
=>
{
describe
(
'
isMatchLine
'
,
()
=>
{
it
(
'
should return true for match line type
'
,
()
=>
{
const
component
=
createComponent
({
lineType
:
MATCH_LINE_TYPE
});
expect
(
component
.
isMatchLine
).
toEqual
(
true
);
});
it
(
'
should return false for non-match line type
'
,
()
=>
{
const
component
=
createComponent
({
lineType
:
CONTEXT_LINE_TYPE
});
expect
(
component
.
isMatchLine
).
toEqual
(
false
);
});
});
describe
(
'
isContextLine
'
,
()
=>
{
it
(
'
should return true for context line type
'
,
()
=>
{
const
component
=
createComponent
({
lineType
:
CONTEXT_LINE_TYPE
});
expect
(
component
.
isContextLine
).
toEqual
(
true
);
});
it
(
'
should return false for non-context line type
'
,
()
=>
{
const
component
=
createComponent
({
lineType
:
MATCH_LINE_TYPE
});
expect
(
component
.
isContextLine
).
toEqual
(
false
);
});
});
describe
(
'
isMetaLine
'
,
()
=>
{
it
(
'
should return true for meta line type
'
,
()
=>
{
const
component
=
createComponent
({
lineType
:
NEW_NO_NEW_LINE_TYPE
});
expect
(
component
.
isMetaLine
).
toEqual
(
true
);
const
component2
=
createComponent
({
lineType
:
OLD_NO_NEW_LINE_TYPE
});
expect
(
component2
.
isMetaLine
).
toEqual
(
true
);
});
it
(
'
should return false for non-meta line type
'
,
()
=>
{
const
component
=
createComponent
({
lineType
:
MATCH_LINE_TYPE
});
expect
(
component
.
isMetaLine
).
toEqual
(
false
);
});
});
describe
(
'
lineHref
'
,
()
=>
{
it
(
'
should prepend # to lineCode
'
,
()
=>
{
const
lineCode
=
'
LC_42
'
;
...
...
@@ -109,7 +64,7 @@ describe('DiffLineGutterContent', () => {
describe
(
'
template
'
,
()
=>
{
it
(
'
should render three dots for context lines
'
,
()
=>
{
const
component
=
createComponent
({
lineType
:
MATCH_LINE_TYPE
,
isMatchLine
:
true
,
});
expect
(
component
.
$el
.
querySelector
(
'
span
'
).
classList
.
contains
(
'
context-cell
'
)).
toEqual
(
true
);
...
...
spec/javascripts/diffs/components/inline_diff_view_spec.js
View file @
fbf74719
import
Vue
from
'
vue
'
;
import
InlineDiffView
from
'
~/diffs/components/inline_diff_view.vue
'
;
import
store
from
'
~/mr_notes/stores
'
;
import
*
as
constants
from
'
~/diffs/constants
'
;
import
{
createComponentWithStore
}
from
'
spec/helpers/vue_mount_component_helper
'
;
import
diffFileMockData
from
'
../mock_data/diff_file
'
;
import
discussionsMockData
from
'
../mock_data/diff_discussions
'
;
...
...
@@ -14,58 +13,13 @@ describe('InlineDiffView', () => {
beforeEach
(()
=>
{
const
diffFile
=
getDiffFileMock
();
store
.
dispatch
(
'
setInlineDiffViewType
'
);
component
=
createComponentWithStore
(
Vue
.
extend
(
InlineDiffView
),
store
,
{
diffFile
,
diffLines
:
diffFile
.
highlightedDiffLines
,
}).
$mount
();
});
describe
(
'
methods
'
,
()
=>
{
describe
(
'
handleMouse
'
,
()
=>
{
it
(
'
should set hoveredLineCode
'
,
()
=>
{
expect
(
component
.
hoveredLineCode
).
toEqual
(
null
);
component
.
handleMouse
(
'
lineCode1
'
,
true
);
expect
(
component
.
hoveredLineCode
).
toEqual
(
'
lineCode1
'
);
component
.
handleMouse
(
'
lineCode1
'
,
false
);
expect
(
component
.
hoveredLineCode
).
toEqual
(
null
);
});
});
describe
(
'
getLineClass
'
,
()
=>
{
it
(
'
should return line class object
'
,
()
=>
{
const
{
LINE_HOVER_CLASS_NAME
,
LINE_UNFOLD_CLASS_NAME
}
=
constants
;
const
{
MATCH_LINE_TYPE
,
NEW_LINE_TYPE
}
=
constants
;
expect
(
component
.
getLineClass
(
component
.
diffLines
[
0
])).
toEqual
({
[
NEW_LINE_TYPE
]:
NEW_LINE_TYPE
,
[
LINE_UNFOLD_CLASS_NAME
]:
false
,
[
LINE_HOVER_CLASS_NAME
]:
false
,
});
component
.
handleMouse
(
component
.
diffLines
[
0
].
lineCode
,
true
);
Object
.
defineProperty
(
component
,
'
isLoggedIn
'
,
{
get
()
{
return
true
;
},
});
expect
(
component
.
getLineClass
(
component
.
diffLines
[
0
])).
toEqual
({
[
NEW_LINE_TYPE
]:
NEW_LINE_TYPE
,
[
LINE_UNFOLD_CLASS_NAME
]:
false
,
[
LINE_HOVER_CLASS_NAME
]:
true
,
});
expect
(
component
.
getLineClass
(
component
.
diffLines
[
5
])).
toEqual
({
[
MATCH_LINE_TYPE
]:
MATCH_LINE_TYPE
,
[
LINE_UNFOLD_CLASS_NAME
]:
true
,
[
LINE_HOVER_CLASS_NAME
]:
false
,
});
});
});
});
describe
(
'
template
'
,
()
=>
{
it
(
'
should have rendered diff lines
'
,
()
=>
{
const
el
=
component
.
$el
;
...
...
@@ -89,23 +43,5 @@ describe('InlineDiffView', () => {
done
();
});
});
it
(
'
should render new discussion forms
'
,
done
=>
{
const
el
=
component
.
$el
;
const
lines
=
getDiffFileMock
().
highlightedDiffLines
;
component
.
handleShowCommentForm
({
lineCode
:
lines
[
0
].
lineCode
});
component
.
handleShowCommentForm
({
lineCode
:
lines
[
1
].
lineCode
});
Vue
.
nextTick
(()
=>
{
expect
(
el
.
querySelectorAll
(
'
.js-vue-markdown-field
'
).
length
).
toEqual
(
2
);
expect
(
el
.
querySelectorAll
(
'
tr
'
)[
1
].
classList
.
contains
(
'
notes_holder
'
)).
toEqual
(
true
);
expect
(
el
.
querySelectorAll
(
'
tr
'
)[
3
].
classList
.
contains
(
'
notes_holder
'
)).
toEqual
(
true
);
store
.
state
.
diffs
.
diffLineCommentForms
=
{};
done
();
});
});
});
});
spec/javascripts/diffs/components/parallel_diff_view_spec.js
View file @
fbf74719
...
...
@@ -4,12 +4,10 @@ import store from '~/mr_notes/stores';
import
*
as
constants
from
'
~/diffs/constants
'
;
import
{
createComponentWithStore
}
from
'
spec/helpers/vue_mount_component_helper
'
;
import
diffFileMockData
from
'
../mock_data/diff_file
'
;
import
discussionsMockData
from
'
../mock_data/diff_discussions
'
;
describe
(
'
ParallelDiffView
'
,
()
=>
{
let
component
;
const
getDiffFileMock
=
()
=>
Object
.
assign
({},
diffFileMockData
);
const
getDiscussionsMockData
=
()
=>
[
Object
.
assign
({},
discussionsMockData
)];
beforeEach
(()
=>
{
const
diffFile
=
getDiffFileMock
();
...
...
@@ -28,197 +26,4 @@ describe('ParallelDiffView', () => {
});
});
});
describe
(
'
methods
'
,
()
=>
{
describe
(
'
hasDiscussion
'
,
()
=>
{
it
(
'
it should return true if there is a discussion either for left or right section
'
,
()
=>
{
Object
.
defineProperty
(
component
,
'
discussionsByLineCode
'
,
{
get
()
{
return
{
line_42
:
true
};
},
});
expect
(
component
.
hasDiscussion
({
left
:
{},
right
:
{}
})).
toEqual
(
undefined
);
expect
(
component
.
hasDiscussion
({
left
:
{
lineCode
:
'
line_42
'
},
right
:
{}
})).
toEqual
(
true
);
expect
(
component
.
hasDiscussion
({
left
:
{},
right
:
{
lineCode
:
'
line_42
'
}
})).
toEqual
(
true
);
});
});
describe
(
'
getClassName
'
,
()
=>
{
it
(
'
should return line class object
'
,
()
=>
{
const
{
LINE_HOVER_CLASS_NAME
,
LINE_UNFOLD_CLASS_NAME
}
=
constants
;
const
{
MATCH_LINE_TYPE
,
NEW_LINE_TYPE
,
LINE_POSITION_RIGHT
}
=
constants
;
expect
(
component
.
getClassName
(
component
.
diffLines
[
1
],
LINE_POSITION_RIGHT
)).
toEqual
({
[
NEW_LINE_TYPE
]:
NEW_LINE_TYPE
,
[
LINE_UNFOLD_CLASS_NAME
]:
false
,
[
LINE_HOVER_CLASS_NAME
]:
false
,
});
const
eventMock
=
{
target
:
component
.
$refs
.
rightLines
[
1
],
};
component
.
handleMouse
(
eventMock
,
component
.
diffLines
[
1
],
true
);
Object
.
defineProperty
(
component
,
'
isLoggedIn
'
,
{
get
()
{
return
true
;
},
});
expect
(
component
.
getClassName
(
component
.
diffLines
[
1
],
LINE_POSITION_RIGHT
)).
toEqual
({
[
NEW_LINE_TYPE
]:
NEW_LINE_TYPE
,
[
LINE_UNFOLD_CLASS_NAME
]:
false
,
[
LINE_HOVER_CLASS_NAME
]:
true
,
});
expect
(
component
.
getClassName
(
component
.
diffLines
[
5
],
LINE_POSITION_RIGHT
)).
toEqual
({
[
MATCH_LINE_TYPE
]:
MATCH_LINE_TYPE
,
[
LINE_UNFOLD_CLASS_NAME
]:
true
,
[
LINE_HOVER_CLASS_NAME
]:
false
,
});
});
});
describe
(
'
handleMouse
'
,
()
=>
{
it
(
'
should set hovered line code and line section to null when isHover is false
'
,
()
=>
{
const
rightLineEventMock
=
{
target
:
component
.
$refs
.
rightLines
[
1
]
};
expect
(
component
.
hoveredLineCode
).
toEqual
(
null
);
expect
(
component
.
hoveredSection
).
toEqual
(
null
);
component
.
handleMouse
(
rightLineEventMock
,
null
,
false
);
expect
(
component
.
hoveredLineCode
).
toEqual
(
null
);
expect
(
component
.
hoveredSection
).
toEqual
(
null
);
});
it
(
'
should set hovered line code and line section for right section
'
,
()
=>
{
const
rightLineEventMock
=
{
target
:
component
.
$refs
.
rightLines
[
1
]
};
component
.
handleMouse
(
rightLineEventMock
,
component
.
diffLines
[
1
],
true
);
expect
(
component
.
hoveredLineCode
).
toEqual
(
component
.
diffLines
[
1
].
right
.
lineCode
);
expect
(
component
.
hoveredSection
).
toEqual
(
constants
.
LINE_POSITION_RIGHT
);
});
it
(
'
should set hovered line code and line section for left section
'
,
()
=>
{
const
leftLineEventMock
=
{
target
:
component
.
$refs
.
leftLines
[
2
]
};
component
.
handleMouse
(
leftLineEventMock
,
component
.
diffLines
[
2
],
true
);
expect
(
component
.
hoveredLineCode
).
toEqual
(
component
.
diffLines
[
2
].
left
.
lineCode
);
expect
(
component
.
hoveredSection
).
toEqual
(
constants
.
LINE_POSITION_LEFT
);
});
});
describe
(
'
shouldRenderDiscussions
'
,
()
=>
{
it
(
'
should return true if there is a discussion on left side and it is expanded
'
,
()
=>
{
const
line
=
{
left
:
{
lineCode
:
'
lineCode1
'
}
};
spyOn
(
component
,
'
isDiscussionExpanded
'
).
and
.
returnValue
(
true
);
Object
.
defineProperty
(
component
,
'
discussionsByLineCode
'
,
{
get
()
{
return
{
[
line
.
left
.
lineCode
]:
true
,
};
},
});
expect
(
component
.
shouldRenderDiscussions
(
line
,
constants
.
LINE_POSITION_LEFT
)).
toEqual
(
true
);
expect
(
component
.
isDiscussionExpanded
).
toHaveBeenCalledWith
(
line
.
left
.
lineCode
);
});
it
(
'
should return false if there is a discussion on left side but it is collapsed
'
,
()
=>
{
const
line
=
{
left
:
{
lineCode
:
'
lineCode1
'
}
};
spyOn
(
component
,
'
isDiscussionExpanded
'
).
and
.
returnValue
(
false
);
Object
.
defineProperty
(
component
,
'
discussionsByLineCode
'
,
{
get
()
{
return
{
[
line
.
left
.
lineCode
]:
true
,
};
},
});
expect
(
component
.
shouldRenderDiscussions
(
line
,
constants
.
LINE_POSITION_LEFT
)).
toEqual
(
false
,
);
});
it
(
'
should return false for discussions on the right side if there is no line type
'
,
()
=>
{
const
CUSTOM_RIGHT_LINE_TYPE
=
'
CUSTOM_RIGHT_LINE_TYPE
'
;
const
line
=
{
right
:
{
lineCode
:
'
lineCode1
'
,
type
:
CUSTOM_RIGHT_LINE_TYPE
}
};
spyOn
(
component
,
'
isDiscussionExpanded
'
).
and
.
returnValue
(
true
);
Object
.
defineProperty
(
component
,
'
discussionsByLineCode
'
,
{
get
()
{
return
{
[
line
.
right
.
lineCode
]:
true
,
};
},
});
expect
(
component
.
shouldRenderDiscussions
(
line
,
constants
.
LINE_POSITION_RIGHT
)).
toEqual
(
CUSTOM_RIGHT_LINE_TYPE
,
);
});
});
describe
(
'
hasAnyExpandedDiscussion
'
,
()
=>
{
const
LINE_CODE_LEFT
=
'
LINE_CODE_LEFT
'
;
const
LINE_CODE_RIGHT
=
'
LINE_CODE_RIGHT
'
;
it
(
'
should return true if there is a discussion either on the left or the right side
'
,
()
=>
{
const
mockLineOne
=
{
right
:
{
lineCode
:
LINE_CODE_RIGHT
},
left
:
{},
};
const
mockLineTwo
=
{
left
:
{
lineCode
:
LINE_CODE_LEFT
},
right
:
{},
};
spyOn
(
component
,
'
isDiscussionExpanded
'
).
and
.
callFake
(
lc
=>
lc
===
LINE_CODE_RIGHT
);
expect
(
component
.
hasAnyExpandedDiscussion
(
mockLineOne
)).
toEqual
(
true
);
expect
(
component
.
hasAnyExpandedDiscussion
(
mockLineTwo
)).
toEqual
(
false
);
});
});
});
describe
(
'
template
'
,
()
=>
{
it
(
'
should have rendered diff lines
'
,
()
=>
{
const
el
=
component
.
$el
;
expect
(
el
.
querySelectorAll
(
'
tr.line_holder.parallel
'
).
length
).
toEqual
(
6
);
expect
(
el
.
querySelectorAll
(
'
td.empty-cell
'
).
length
).
toEqual
(
4
);
expect
(
el
.
querySelectorAll
(
'
td.line_content.parallel.right-side
'
).
length
).
toEqual
(
6
);
expect
(
el
.
querySelectorAll
(
'
td.line_content.parallel.left-side
'
).
length
).
toEqual
(
6
);
expect
(
el
.
querySelectorAll
(
'
td.match
'
).
length
).
toEqual
(
4
);
expect
(
el
.
textContent
.
indexOf
(
'
Bad dates
'
)
>
-
1
).
toEqual
(
true
);
});
it
(
'
should render discussions
'
,
done
=>
{
const
el
=
component
.
$el
;
component
.
$store
.
dispatch
(
'
setInitialNotes
'
,
getDiscussionsMockData
());
Vue
.
nextTick
(()
=>
{
expect
(
el
.
querySelectorAll
(
'
.notes_holder
'
).
length
).
toEqual
(
1
);
expect
(
el
.
querySelectorAll
(
'
.notes_holder .note-discussion li
'
).
length
).
toEqual
(
5
);
expect
(
el
.
innerText
.
indexOf
(
'
comment 5
'
)
>
-
1
).
toEqual
(
true
);
component
.
$store
.
dispatch
(
'
setInitialNotes
'
,
[]);
done
();
});
});
it
(
'
should render new discussion forms
'
,
done
=>
{
const
el
=
component
.
$el
;
const
lines
=
getDiffFileMock
().
parallelDiffLines
;
component
.
handleShowCommentForm
({
lineCode
:
lines
[
0
].
lineCode
});
component
.
handleShowCommentForm
({
lineCode
:
lines
[
1
].
lineCode
});
Vue
.
nextTick
(()
=>
{
expect
(
el
.
querySelectorAll
(
'
.js-vue-markdown-field
'
).
length
).
toEqual
(
2
);
expect
(
el
.
querySelectorAll
(
'
tr
'
)[
1
].
classList
.
contains
(
'
notes_holder
'
)).
toEqual
(
true
);
expect
(
el
.
querySelectorAll
(
'
tr
'
)[
3
].
classList
.
contains
(
'
notes_holder
'
)).
toEqual
(
true
);
store
.
state
.
diffs
.
diffLineCommentForms
=
{};
done
();
});
});
});
});
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment