Skip to content
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CWM::Dialog; shared_examples for more widgets #592

Merged
merged 18 commits into from
Jun 27, 2017
Merged

CWM::Dialog; shared_examples for more widgets #592

merged 18 commits into from
Jun 27, 2017

Conversation

mvidner
Copy link
Member

@mvidner mvidner commented Jun 19, 2017

These are needed for the Expert Partitioner, and were introduced in yast/yast-partitioner#5 (because we had not branched SP3 back then)

  • CWM::Dialog
  • UI::Sequence
  • RSpec.shared_examples for more CWM widgets
  • UI::Greasemonkey

@coveralls
Copy link

Coverage Status

Coverage decreased (-0.09%) to 27.659% when pulling a2dfe53 on cwm-rspec2 into 15350bb on master.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.2%) to 27.994% when pulling ba55f90 on cwm-rspec2 into 15350bb on master.

which is in turn adapted from GreasemonkeyClass in yast2-storage
@coveralls
Copy link

Coverage Status

Coverage increased (+0.4%) to 28.19% when pulling 09bb403 on cwm-rspec2 into 15350bb on master.

module UI
# UI layout helpers.
#
module Greasemonkey
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you want to add GreaseMonkey to yast2, then significant improvement of code quality is needed ;) as yast2 mean that it will be used on more places and there is highed requirements. Also documentation have to be significantly improved and same for test coverage.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As for test coverage, I can only offer 100% ;-)

As for the API: I need it to stay compatible, because that is the point: reusing pieces of the old dialogs while I concentrate on other things. Actually, in yast/yast-partitioner#5 I used this but then in yast/yast-partitioner#15 nothing is used as I gradually rewrote the dialogs. I expect several recurrences of this.

I will add docs.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well, when we add it to yast2, it is like we are suggesting to reuse it. So I think for this case functional API make sense as it is conversion of one kind of term to other, but I really like to have code that does not look like ycp :)


describe "UI::Greasemonkey" do
RSpec.shared_examples "a Greasemonkey method" do |mname|
it "transforms its argument properly" do
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it should better document what happen like it "transforms GreaseMonkey term to UI term"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also what about adding describe ".#{mname}" do around it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. OK
  2. No, this is done by the describes below.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still missing 1. fixed. It should mention that output of greasemonkey method should be valid UI term.

include Yast::UIShortcuts

# @return [String,nil] Set a title, or keep the existing title
abstract_method :title
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does it make sense to have method that return nil? like def title; nil; end? why not having nil as default?

Yast::Wizard.CloseDialog
end

def run_assuming_open
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really do not like this name. Also why it is public method? and why it missing documentation if it is intention to be a public method?

I suggest something like def show

end
end

def wizard_create_dialog(&block)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing documentation, also why it is public method?

true
end

# @return [Array<Symbol>]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

at least link to cwm documentation for it

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and in fact, it doesn't have to be onlu symbol, it is in fact Array<any non nil object>

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. OK.
  2. I think you are wrong about this:
    Convert.to_symbol(ret)
    enforces a Symbol.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well, in fact I do not test it. But from past I know that any object stop during handle and convert to symbol looks happen only after test for skip for store

saveWidgets(widgets, event_descr) if save && !skip_store_for.include?(ret)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Parse error.
Anyway, a non-symbol means store may run, so the dialog "works", but nil is returned from show and I think such usage is wrong and should be fixed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

on tricky value is string, which is converted, so if handle return "test" skip for have to have "test", but return value is :test. But I agree that we should not support it.


# File: Greasemonkey.ycp
# Package: yast2-storage
# Summary: Expert Partitioner
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these three lines are no longer valid.

# Summary: Expert Partitioner
# Authors: Arvin Schnell <aschnell@suse.de>
#
# Lets see if this turns out to be useful.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

require "yast"

module UI
# UI layout helpers.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this need really more extensive documentation

require "yast"
Yast.import "Sequencer"

# FIXME: once the API is reviewed, move this to yast-yast2
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no longer valid

# {Yast::SequencerClass#Run Yast::Sequencer.Run}
# but smarter:
# - auto :abort (see {#abortable})
# - *aliases* are assumed to be method names if unpecified
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo unpecified

# - *aliases* are assumed to be method names if unpecified
# (see {#from_methods})
def run(aliases: nil, sequence:)
aliases = from_methods(sequence) if aliases.nil?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can be written as aliases ||= from_methods(sequence)

# (an :abort from a dialog should :abort the whole sequence)
def abortable(sequence_hash)
sequence_hash.map do |name, destination|
if name == "ws_start"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this "hack" should be documented why it is needed. Also it smells for me like constant.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not a hack, it is a standard part of the sequence hash that specifies the starting point.

Unfortunately the docs for Sequencer itself is ... bad.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so use constant with proper name like "INITIAL_DIALOG"?

# (also see Yast::SequencerClass#WS_special)
def skip_stack(method_symbol)
@skip_stack ||= {}
@skip_stack[method_symbol] = true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to be honest I do not get why it is class method and not instance one as I expect that skipped methods are single run specific, not? so what happen if two or three Sequence is used in row?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have a point. IIUC you don't want FooSequence to affect BarSequence. I believe this will not happen, because I have used a class-level @attribute, not a @@class-attribute (which is shared across the hierarchy). I will add a test for it.

It is a class method because I need it at the class level. Actual usage:

    class AddPartition < UI::Sequence
      def preconditions
        if slots.empty?
          Yast::Popup.Error("...")
          return :back
        end
        :next
      end
      skip_stack :preconditions

      def type
        Dialogs::PartitionType.run(disk, @ptemplate, @slots)
      end

      def size
        Dialogs::PartitionSize.run(disk, @ptemplate, @slots)
      end
      ...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so it is class attribute in fact. Well, it make sense then, if it is subclass specific attribute, that is persistent accross same instances.

btw you can write it as skip_stack def preconditions

@skip_stack[method_symbol] = true
end

def skip_stack?(name)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

documentation

@coveralls
Copy link

Coverage Status

Coverage increased (+0.6%) to 28.411% when pulling a0bfee4 on cwm-rspec2 into ed43046 on master.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.6%) to 28.411% when pulling 878a7dc on cwm-rspec2 into ed43046 on master.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.6%) to 28.393% when pulling 912b950 on cwm-rspec2 into ed43046 on master.

# @example
# term(:FrameWithMarginBox, "Title", "arg1", "arg2")
# ->
# Frame("Title", MarginBox(1.45, 0.45, "arg1", "arg2"))
Copy link
Member

@jreidinger jreidinger Jun 23, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seen this usage, I think it make sense to mention it as old example and deprecated. I think prefered way to use should be

include GreaseMonkey

def contents
  VBox(
    FrameWithMarginBox("Title", "arg1", "arg2")
  )
end

and this should be a priority example for suggested usage. Or how do you see it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is out of scope for this PR. As I say in the module header,

These started out in the Expert Partitioner in yast2-storage.
The use case is reusing pieces of this legacy code in the new yast2-partitioner.
That is why the API and the implementation look old.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if only use case is reusing code in yast2-partitioner, that why it is in yast2 where it should serve all modules? That is why I am more strict regarding API and other stuff, because one module scope it is ok, if there are some legacy stuff, but if we add it to yast2 itself, it means we have to be more careful in future when we want to improve it.

"first" => [subj.method(:first), true]
}

expect(subj.from_methods(seq)).to eq(wanted)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not get this test. I expect it should test if TestSequence do not skip "first", not? Here it test that class that explicitly skip it really skip it, which is not what "it" description mention

it does fail if @skip_stack is replaced with @@skip_stack
@coveralls
Copy link

Coverage Status

Coverage increased (+0.6%) to 28.393% when pulling cd83bfe on cwm-rspec2 into ed43046 on master.


# @return [Array<Symbol>]
# Events for which `store` won't be called, see {Yast::CWMClass#show}
def skip_store_for
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question is for which actions it should be done. Currently only use case I see is :redraw. So maybe this should be redraw_event and also handle it in run? Just idea as @teclator currently solving something similar.

# A {UI::Sequence} is an object-oriented interface for the good old
# {Yast::SequencerClass Yast::Sequencer}.
# In the simple case it runs a sequence of dialogs
# connected by Back and Next buttons.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as sequencer can be a bit tricky, I really welcome here one or two trivial examples of usage

Copy link
Member

@jreidinger jreidinger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

two documenting NPs and I am still not convinced that it is good idea to add to YaST2 itself greasemonkey beast without API and code improvements, but in the end LGTM

@mvidner mvidner merged commit f13ddf9 into master Jun 27, 2017
@mvidner mvidner deleted the cwm-rspec2 branch June 27, 2017 06:41
@mvidner mvidner mentioned this pull request Jun 29, 2017
mvidner added a commit to yast/yast-partitioner that referenced this pull request Jun 29, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants