mirror of
https://github.com/atom/atom.git
synced 2026-02-06 12:44:59 -05:00
Merge pull request #271 from github/super-command-panel
Super command panel
This commit is contained in:
@@ -12,3 +12,13 @@
|
||||
'meta-e': 'command-panel:set-selection-as-regex-address'
|
||||
'meta-f': 'command-panel:find-in-file'
|
||||
'meta-F': 'command-panel:find-in-project'
|
||||
|
||||
'.command-panel':
|
||||
'ctrl-{': 'command-panel:collapse-all'
|
||||
'ctrl-}': 'command-panel:expand-all'
|
||||
|
||||
'.command-panel .preview-list':
|
||||
'left': 'command-panel:collapse-result'
|
||||
'ctrl-[': 'command-panel:collapse-result'
|
||||
'right': 'command-panel:expand-result'
|
||||
'ctrl-]': 'command-panel:expand-result'
|
||||
|
||||
@@ -11,7 +11,13 @@ module.exports =
|
||||
class CommandPanelView extends View
|
||||
@content: ->
|
||||
@div class: 'command-panel tool-panel', =>
|
||||
@div outlet: 'previewCount', class: 'preview-count'
|
||||
@div class: 'loading', outlet: 'loadingMessage'
|
||||
@div class: 'header', outlet: 'previewHeader', =>
|
||||
@ul outlet: 'expandCollapse', class: 'expand-collapse', =>
|
||||
@li class: 'expand', 'Expand All'
|
||||
@li class: 'collapse', 'Collapse All'
|
||||
@span outlet: 'previewCount', class: 'preview-count'
|
||||
|
||||
@subview 'previewList', new PreviewList(rootView)
|
||||
@ul class: 'error-messages', outlet: 'errorMessages'
|
||||
@div class: 'prompt-and-editor', =>
|
||||
@@ -40,8 +46,11 @@ class CommandPanelView extends View
|
||||
rootView.command 'command-panel:repeat-relative-address-in-reverse', => @repeatRelativeAddressInReverse()
|
||||
rootView.command 'command-panel:set-selection-as-regex-address', => @setSelectionAsLastRelativeAddress()
|
||||
|
||||
@on 'click', '.expand', @onExpandAll
|
||||
@on 'click', '.collapse', @onCollapseAll
|
||||
|
||||
@previewList.hide()
|
||||
@previewCount.hide()
|
||||
@previewHeader.hide()
|
||||
@errorMessages.hide()
|
||||
@prompt.iconSize(@miniEditor.getFontSize())
|
||||
|
||||
@@ -66,17 +75,35 @@ class CommandPanelView extends View
|
||||
togglePreview: ->
|
||||
if @previewList.is(':focus')
|
||||
@previewList.hide()
|
||||
@previewCount.hide()
|
||||
@previewHeader.hide()
|
||||
@detach()
|
||||
rootView.focus()
|
||||
else
|
||||
@attach() unless @hasParent()
|
||||
if @previewList.hasOperations()
|
||||
@previewList.show().focus()
|
||||
@previewCount.show()
|
||||
@previewHeader.show()
|
||||
else
|
||||
@miniEditor.focus()
|
||||
|
||||
toggleLoading: ->
|
||||
if @loadingMessage.hasClass 'is-loading'
|
||||
@loadingMessage.removeClass 'is-loading'
|
||||
@loadingMessage.html ''
|
||||
@loadingMessage.hide()
|
||||
else
|
||||
@loadingMessage.addClass 'is-loading'
|
||||
@loadingMessage.html 'Searching...'
|
||||
@loadingMessage.show()
|
||||
|
||||
onExpandAll: (event) =>
|
||||
@previewList.expandAllPaths()
|
||||
@previewList.focus()
|
||||
|
||||
onCollapseAll: (event) =>
|
||||
@previewList.collapseAllPaths()
|
||||
@previewList.focus()
|
||||
|
||||
attach: (text='', options={}) ->
|
||||
@errorMessages.hide()
|
||||
|
||||
@@ -89,17 +116,19 @@ class CommandPanelView extends View
|
||||
detach: ->
|
||||
rootView.focus()
|
||||
@previewList.hide()
|
||||
@previewCount.hide()
|
||||
@previewHeader.hide()
|
||||
super
|
||||
|
||||
escapedCommand: ->
|
||||
@miniEditor.getText()
|
||||
|
||||
execute: (command=@escapedCommand())->
|
||||
@toggleLoading()
|
||||
@errorMessages.empty()
|
||||
|
||||
try
|
||||
@commandInterpreter.eval(command, rootView.getActiveEditSession()).done ({operationsToPreview, errorMessages}) =>
|
||||
@toggleLoading()
|
||||
@history.push(command)
|
||||
@historyIndex = @history.length
|
||||
|
||||
@@ -109,6 +138,7 @@ class CommandPanelView extends View
|
||||
@errorMessages.append $$ ->
|
||||
@li errorMessage for errorMessage in errorMessages
|
||||
else if operationsToPreview?.length
|
||||
@previewHeader.show()
|
||||
@previewList.populate(operationsToPreview)
|
||||
@previewList.focus()
|
||||
@previewCount.text("#{_.pluralize(operationsToPreview.length, 'match', 'matches')} in #{_.pluralize(@previewList.getPathCount(), 'file')}").show()
|
||||
|
||||
28
src/packages/command-panel/lib/operation-view.coffee
Normal file
28
src/packages/command-panel/lib/operation-view.coffee
Normal file
@@ -0,0 +1,28 @@
|
||||
{View} = require 'space-pen'
|
||||
|
||||
module.exports =
|
||||
class OperationView extends View
|
||||
@content: ({operation} = {}) ->
|
||||
{prefix, suffix, match, range} = operation.preview()
|
||||
@li 'data-index': operation.index, class: 'operation', =>
|
||||
@span range.start.row + 1, class: 'line-number'
|
||||
@span class: 'preview', =>
|
||||
@span prefix
|
||||
@span match, class: 'match'
|
||||
@span suffix
|
||||
|
||||
initialize: ({@previewList, @operation}) ->
|
||||
@subscribe @previewList, 'core:confirm', =>
|
||||
if @hasClass('selected')
|
||||
@executeOperation()
|
||||
false
|
||||
@on 'mousedown', (e) =>
|
||||
@executeOperation()
|
||||
@previewList.find('.selected').removeClass('selected')
|
||||
@addClass('selected')
|
||||
|
||||
executeOperation: ->
|
||||
editSession = rootView.open(@operation.getPath())
|
||||
bufferRange = @operation.execute(editSession)
|
||||
editSession.setSelectedBufferRange(bufferRange, autoscroll: true) if bufferRange
|
||||
@previewList.focus()
|
||||
58
src/packages/command-panel/lib/path-view.coffee
Normal file
58
src/packages/command-panel/lib/path-view.coffee
Normal file
@@ -0,0 +1,58 @@
|
||||
{View} = require 'space-pen'
|
||||
fs = require 'fs'
|
||||
OperationView = require './operation-view'
|
||||
$ = require 'jquery'
|
||||
|
||||
module.exports =
|
||||
class PathView extends View
|
||||
@content: ({path, operations, previewList} = {}) ->
|
||||
classes = ['path']
|
||||
classes.push('readme') if fs.isReadmePath(path)
|
||||
@li class: classes.join(' '), =>
|
||||
@div outlet: 'pathDetails', class: 'path-details', =>
|
||||
@span class: 'path-name', path
|
||||
@span "(#{operations.length})", class: 'path-match-number'
|
||||
@ul outlet: 'matches', class: 'matches', =>
|
||||
for operation in operations
|
||||
@subview "operation#{operation.index}", new OperationView({operation, previewList})
|
||||
|
||||
initialize: ({@previewList}) ->
|
||||
@pathDetails.on 'mousedown', => @toggle(true)
|
||||
@subscribe @previewList, 'command-panel:collapse-result', =>
|
||||
@collapse(true) if @isSelected()
|
||||
@subscribe @previewList, 'command-panel:expand-result', =>
|
||||
@expand(true) if @isSelected()
|
||||
@subscribe @previewList, 'core:confirm', =>
|
||||
if @hasClass('selected')
|
||||
@toggle(true)
|
||||
false
|
||||
|
||||
isSelected: ->
|
||||
@hasClass('selected') or @find('.selected').length
|
||||
|
||||
setSelected: ->
|
||||
@previewList.find('.selected').removeClass('selected')
|
||||
@addClass('selected')
|
||||
|
||||
toggle: (animate) ->
|
||||
if @hasClass('is-collapsed')
|
||||
@expand(animate)
|
||||
else
|
||||
@collapse(animate)
|
||||
|
||||
expand: (animate=false) ->
|
||||
if animate
|
||||
@matches.show 100, => @removeClass 'is-collapsed'
|
||||
else
|
||||
@matches.show()
|
||||
@removeClass 'is-collapsed'
|
||||
|
||||
collapse: (animate=false) ->
|
||||
if animate
|
||||
@matches.hide 100, =>
|
||||
@addClass 'is-collapsed'
|
||||
@setSelected() if @isSelected()
|
||||
else
|
||||
@matches.hide()
|
||||
@addClass 'is-collapsed'
|
||||
@setSelected() if @isSelected()
|
||||
@@ -3,24 +3,30 @@ $ = require 'jquery'
|
||||
ScrollView = require 'scroll-view'
|
||||
_ = require 'underscore'
|
||||
fs = require 'fs'
|
||||
PathView = require './path-view'
|
||||
OperationView = require './operation-view'
|
||||
|
||||
module.exports =
|
||||
class PreviewList extends ScrollView
|
||||
@content: ->
|
||||
@ol class: 'preview-list', tabindex: -1, ->
|
||||
@ol class: 'preview-list', tabindex: -1
|
||||
|
||||
selectedOperationIndex: 0
|
||||
operations: null
|
||||
|
||||
initialize: (@rootView) ->
|
||||
initialize: ->
|
||||
super
|
||||
|
||||
@on 'core:move-down', => @selectNextOperation(); false
|
||||
@on 'core:move-up', => @selectPreviousOperation(); false
|
||||
@on 'core:confirm', => @executeSelectedOperation()
|
||||
|
||||
@on 'mousedown', 'li.operation', (e) =>
|
||||
@setSelectedOperationIndex(parseInt($(e.target).closest('li').data('index')))
|
||||
@executeSelectedOperation()
|
||||
@command 'command-panel:collapse-all', => @collapseAllPaths()
|
||||
@command 'command-panel:expand-all', => @expandAllPaths()
|
||||
|
||||
expandAllPaths: ->
|
||||
@children().each (index, element) -> $(element).view().expand()
|
||||
|
||||
collapseAllPaths: ->
|
||||
@children().each (index, element) -> $(element).view().collapse()
|
||||
|
||||
destroy: ->
|
||||
@destroyOperations() if @operations
|
||||
@@ -31,26 +37,14 @@ class PreviewList extends ScrollView
|
||||
@destroyOperations() if @operations
|
||||
@operations = operations
|
||||
@empty()
|
||||
@html $$$ ->
|
||||
operation.index = index for operation, index in operations
|
||||
operationsByPath = _.groupBy(operations, (operation) -> operation.getPath())
|
||||
for path, ops of operationsByPath
|
||||
classes = ['path']
|
||||
classes.push('readme') if fs.isReadmePath(path)
|
||||
@li class: classes.join(' '), =>
|
||||
@span path
|
||||
@span "(#{ops.length})", class: 'path-match-number'
|
||||
for operation in ops
|
||||
{prefix, suffix, match, range} = operation.preview()
|
||||
@li 'data-index': operation.index, class: 'operation', =>
|
||||
@span range.start.row + 1, class: 'line-number'
|
||||
@span class: 'preview', =>
|
||||
@span prefix
|
||||
@span match, class: 'match'
|
||||
@span suffix
|
||||
|
||||
@setSelectedOperationIndex(0)
|
||||
operation.index = index for operation, index in operations
|
||||
operationsByPath = _.groupBy(operations, (operation) -> operation.getPath())
|
||||
for path, operations of operationsByPath
|
||||
@append new PathView({path, operations, previewList: this})
|
||||
|
||||
@show()
|
||||
@find('.operation:first').addClass('selected')
|
||||
@setLineNumberWidth()
|
||||
|
||||
setLineNumberWidth: ->
|
||||
@@ -61,33 +55,33 @@ class PreviewList extends ScrollView
|
||||
lineNumbers.width(maxWidth)
|
||||
|
||||
selectNextOperation: ->
|
||||
@setSelectedOperationIndex(@selectedOperationIndex + 1)
|
||||
selectedView = @find('.selected').view()
|
||||
|
||||
if selectedView instanceof PathView
|
||||
if selectedView.hasClass('is-collapsed')
|
||||
nextView = selectedView.next().view()
|
||||
else
|
||||
nextView = selectedView.find('.operation:first')
|
||||
else
|
||||
nextView = selectedView.next().view() ? selectedView.closest('.path').next().view()
|
||||
if nextView?
|
||||
selectedView.removeClass('selected')
|
||||
nextView.addClass('selected')
|
||||
@scrollToElement(nextView)
|
||||
|
||||
selectPreviousOperation: ->
|
||||
@setSelectedOperationIndex(@selectedOperationIndex - 1)
|
||||
selectedView = @find('.selected').view()
|
||||
|
||||
setSelectedOperationIndex: (index, scrollToOperation=true) ->
|
||||
index = Math.max(0, index)
|
||||
index = Math.min(@operations.length - 1, index)
|
||||
@children(".selected").removeClass('selected')
|
||||
element = @children("li.operation:eq(#{index})")
|
||||
element.addClass('selected')
|
||||
if selectedView instanceof PathView
|
||||
previousView = selectedView.prev()
|
||||
previousView = previousView.find('.operation:last').view() unless previousView.hasClass('is-collapsed')
|
||||
else
|
||||
previousView = selectedView.prev().view() ? selectedView.closest('.path').view()
|
||||
|
||||
if scrollToOperation
|
||||
if index is 0
|
||||
@scrollToTop()
|
||||
else
|
||||
@scrollToElement(element)
|
||||
|
||||
@selectedOperationIndex = index
|
||||
|
||||
executeSelectedOperation: ->
|
||||
operation = @getSelectedOperation()
|
||||
editSession = @rootView.open(operation.getPath())
|
||||
bufferRange = operation.execute(editSession)
|
||||
editSession.setSelectedBufferRange(bufferRange, autoscroll: true) if bufferRange
|
||||
@focus()
|
||||
false
|
||||
if previousView?
|
||||
selectedView.removeClass('selected')
|
||||
previousView.addClass('selected')
|
||||
@scrollToElement(previousView)
|
||||
|
||||
getPathCount: ->
|
||||
_.keys(_.groupBy(@operations, (operation) -> operation.getPath())).length
|
||||
@@ -100,23 +94,27 @@ class PreviewList extends ScrollView
|
||||
@operations = null
|
||||
|
||||
getSelectedOperation: ->
|
||||
@operations[@selectedOperationIndex]
|
||||
@find('.operation.selected').view()?.operation
|
||||
|
||||
scrollToElement: (element) ->
|
||||
top = @scrollTop() + element.position().top
|
||||
top = @scrollTop() + element.offset().top - @offset().top
|
||||
bottom = top + element.outerHeight()
|
||||
|
||||
if bottom > @scrollBottom()
|
||||
@scrollBottom(bottom)
|
||||
if top < @scrollTop()
|
||||
@scrollTop(top)
|
||||
@scrollBottom(bottom) if bottom > @scrollBottom()
|
||||
@scrollTop(top) if top < @scrollTop()
|
||||
|
||||
scrollToBottom: ->
|
||||
super()
|
||||
|
||||
@setSelectedOperationIndex(Infinity, false)
|
||||
@find('.selected').removeClass('selected')
|
||||
lastPath = @find('.path:last')
|
||||
if lastPath.hasClass('is-collapsed')
|
||||
lastPath.addClass('selected')
|
||||
else
|
||||
lastPath.find('.operation:last').addClass('selected')
|
||||
|
||||
scrollToTop: ->
|
||||
super()
|
||||
|
||||
@setSelectedOperationIndex(0, false)
|
||||
@find('.selected').removeClass('selected')
|
||||
@find('.path:first').addClass('selected')
|
||||
|
||||
@@ -128,6 +128,9 @@ describe "CommandPanel", ->
|
||||
beforeEach ->
|
||||
expect(commandPanel.previewList).toBeVisible()
|
||||
|
||||
it "shows the expand and collapse all buttons", ->
|
||||
expect(commandPanel.find('.expand-collapse')).toBeVisible()
|
||||
|
||||
describe "when the preview list is focused", ->
|
||||
it "hides the command panel", ->
|
||||
expect(commandPanel.previewList).toMatchSelector(':focus')
|
||||
@@ -171,19 +174,19 @@ describe "CommandPanel", ->
|
||||
expect(commandPanel.hasParent()).toBeTruthy()
|
||||
|
||||
describe "when the mini editor is focused", ->
|
||||
it "retains focus on the mini editor and does not show the preview list or preview count", ->
|
||||
it "retains focus on the mini editor and does not show the preview list or preview header", ->
|
||||
expect(commandPanel.miniEditor.isFocused).toBeTruthy()
|
||||
rootView.trigger 'command-panel:toggle-preview'
|
||||
expect(commandPanel.previewList).toBeHidden()
|
||||
expect(commandPanel.previewCount).toBeHidden()
|
||||
expect(commandPanel.previewHeader).toBeHidden()
|
||||
expect(commandPanel.miniEditor.isFocused).toBeTruthy()
|
||||
|
||||
describe "when the mini editor is not focused", ->
|
||||
it "focuses the mini editor and does not show the preview list or preview count", ->
|
||||
it "focuses the mini editor and does not show the preview list or preview header", ->
|
||||
rootView.focus()
|
||||
rootView.trigger 'command-panel:toggle-preview'
|
||||
expect(commandPanel.previewList).toBeHidden()
|
||||
expect(commandPanel.previewCount).toBeHidden()
|
||||
expect(commandPanel.previewHeader).toBeHidden()
|
||||
expect(commandPanel.miniEditor.isFocused).toBeTruthy()
|
||||
|
||||
describe "when the command panel is not visible", ->
|
||||
@@ -290,7 +293,7 @@ describe "CommandPanel", ->
|
||||
expect(commandPanel.previewList).toBeVisible()
|
||||
expect(commandPanel.previewList).toMatchSelector ':focus'
|
||||
previewItem = commandPanel.previewList.find("li:contains(sample.js):first")
|
||||
expect(previewItem.text()).toBe "sample.js(1)"
|
||||
expect(previewItem.find('.path-details').text()).toBe "sample.js(1)"
|
||||
expect(previewItem.next().find('.preview').text()).toBe "var quicksort = function () {"
|
||||
expect(previewItem.next().find('.preview > .match').text()).toBe "quicksort"
|
||||
|
||||
@@ -392,29 +395,38 @@ describe "CommandPanel", ->
|
||||
expect(previewList.find('li.operation:eq(1)')).toHaveClass 'selected'
|
||||
expect(previewList.getSelectedOperation()).toBe previewList.getOperations()[1]
|
||||
|
||||
_.times previewList.getOperations().length - 2, -> previewList.trigger 'core:move-down'
|
||||
_.times previewList.getOperations().length + previewList.getPathCount(), -> previewList.trigger 'core:move-down'
|
||||
|
||||
expect(previewList.find("li.operation:last")).toHaveClass 'selected'
|
||||
expect(previewList.getSelectedOperation()).toBe _.last(previewList.getOperations())
|
||||
|
||||
expect(previewList.scrollBottom()).toBeCloseTo previewList.prop('scrollHeight'), -1
|
||||
|
||||
_.times previewList.getOperations().length, -> previewList.trigger 'core:move-up'
|
||||
_.times previewList.getOperations().length + previewList.getPathCount(), -> previewList.trigger 'core:move-up'
|
||||
expect(previewList.scrollTop()).toBe 0
|
||||
|
||||
it "doesn't bubble up the event and the command panel text doesn't change", ->
|
||||
rootView.attachToDom()
|
||||
commandPanel.miniEditor.setText "command"
|
||||
previewList.focus()
|
||||
previewList.trigger 'core:move-up'
|
||||
expect(previewList.find('li.operation:eq(0)')).toHaveClass 'selected'
|
||||
expect(commandPanel.miniEditor.getText()).toBe 'command'
|
||||
previewList.trigger 'core:move-down'
|
||||
expect(previewList.find('li.operation:eq(1)')).toHaveClass 'selected'
|
||||
expect(commandPanel.miniEditor.getText()).toBe 'command'
|
||||
previewList.trigger 'core:move-up'
|
||||
expect(previewList.find('li.operation:eq(0)')).toHaveClass 'selected'
|
||||
expect(commandPanel.miniEditor.getText()).toBe 'command'
|
||||
|
||||
it "doesn't select collapsed operations", ->
|
||||
rootView.attachToDom()
|
||||
previewList.trigger 'command-panel:collapse-result'
|
||||
expect(previewList.find('li.path:eq(0)')).toHaveClass 'selected'
|
||||
previewList.trigger 'core:move-down'
|
||||
expect(previewList.find('li.path:eq(1)')).toHaveClass 'selected'
|
||||
previewList.trigger 'core:move-up'
|
||||
expect(previewList.find('li.path:eq(0)')).toHaveClass 'selected'
|
||||
|
||||
describe "when move-to-top and move-to-bottom are triggered on the preview list", ->
|
||||
it "selects the first/last operation", ->
|
||||
it "selects the first path or last operation", ->
|
||||
rootView.attachToDom()
|
||||
expect(previewList.getOperations().length).toBeGreaterThan 0
|
||||
expect(previewList.find('li.operation:eq(0)')).toHaveClass 'selected'
|
||||
@@ -425,8 +437,8 @@ describe "CommandPanel", ->
|
||||
expect(previewList.getSelectedOperation()).toBe _.last(previewList.getOperations())
|
||||
|
||||
previewList.trigger 'core:move-to-top'
|
||||
expect(previewList.find('li.operation:eq(0)')).toHaveClass 'selected'
|
||||
expect(previewList.getSelectedOperation()).toBe previewList.getOperations()[0]
|
||||
expect(previewList.find('li.path:eq(0)')).toHaveClass 'selected'
|
||||
expect(previewList.getSelectedOperation()).toBeUndefined()
|
||||
|
||||
describe "when core:confirm is triggered on the preview list", ->
|
||||
it "opens the operation's buffer, selects and scrolls to the search result, and refocuses the preview list", ->
|
||||
@@ -453,6 +465,15 @@ describe "CommandPanel", ->
|
||||
|
||||
expect(executeHandler).not.toHaveBeenCalled()
|
||||
|
||||
it "toggles the expansion state when a path is selected", ->
|
||||
rootView.attachToDom()
|
||||
previewList.trigger 'core:move-to-top'
|
||||
expect(previewList.find('li.path:first')).toHaveClass 'selected'
|
||||
expect(previewList.find('li.path:first')).not.toHaveClass 'is-collapsed'
|
||||
previewList.trigger 'core:confirm'
|
||||
expect(previewList.find('li.path:first')).toHaveClass 'selected'
|
||||
expect(previewList.find('li.path:first')).toHaveClass 'is-collapsed'
|
||||
|
||||
describe "when an operation in the preview list is clicked", ->
|
||||
it "opens the operation's buffer, selects the search result, and refocuses the preview list", ->
|
||||
spyOn(previewList, 'focus')
|
||||
@@ -465,3 +486,24 @@ describe "CommandPanel", ->
|
||||
expect(editSession.buffer.getPath()).toBe project.resolve(operation.getPath())
|
||||
expect(editSession.getSelectedBufferRange()).toEqual operation.getBufferRange()
|
||||
expect(previewList.focus).toHaveBeenCalled()
|
||||
|
||||
describe "when a path in the preview list is clicked", ->
|
||||
it "shows and hides the matches for that path", ->
|
||||
rootView.attachToDom()
|
||||
expect(previewList.find('li.path:first-child ul.matches')).toBeVisible()
|
||||
previewList.find('li.path:first-child .path-details').mousedown()
|
||||
expect(previewList.find('li.path:first-child ul.matches')).toBeHidden()
|
||||
|
||||
previewList.find('li.path:first-child .path-details').mousedown()
|
||||
expect(previewList.find('li.path:first-child ul.matches')).toBeVisible()
|
||||
|
||||
describe "when command-panel:collapse-result and command-panel:expand-result are triggered", ->
|
||||
it "collapses and selects the path, and then expands the selected path", ->
|
||||
rootView.attachToDom()
|
||||
expect(previewList.find('li.path:first-child ul.matches')).toBeVisible()
|
||||
previewList.trigger 'command-panel:collapse-result'
|
||||
expect(previewList.find('li.path:first-child ul.matches')).toBeHidden()
|
||||
expect(previewList.find('li.path:first-child')).toHaveClass 'selected'
|
||||
previewList.trigger 'command-panel:expand-result'
|
||||
expect(previewList.find('li.path:first-child ul.matches')).toBeVisible()
|
||||
expect(previewList.find('li.path:first-child')).toHaveClass 'selected'
|
||||
|
||||
Reference in New Issue
Block a user