-
Notifications
You must be signed in to change notification settings - Fork 44
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
Conversation
with RSpec.shared_examples too
which is in turn adapted from GreasemonkeyClass in yast2-storage
module UI | ||
# UI layout helpers. | ||
# | ||
module Greasemonkey |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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"
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- OK
- No, this is done by the
describe
s below.
There was a problem hiding this comment.
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.
library/cwm/src/lib/cwm/dialog.rb
Outdated
include Yast::UIShortcuts | ||
|
||
# @return [String,nil] Set a title, or keep the existing title | ||
abstract_method :title |
There was a problem hiding this comment.
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?
library/cwm/src/lib/cwm/dialog.rb
Outdated
Yast::Wizard.CloseDialog | ||
end | ||
|
||
def run_assuming_open |
There was a problem hiding this comment.
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
library/cwm/src/lib/cwm/dialog.rb
Outdated
end | ||
end | ||
|
||
def wizard_create_dialog(&block) |
There was a problem hiding this comment.
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>] |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- OK.
- I think you are wrong about this:
yast-yast2/library/cwm/src/modules/CWM.rb
Line 877 in 15350bb
Convert.to_symbol(ret)
There was a problem hiding this comment.
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
yast-yast2/library/cwm/src/modules/CWM.rb
Line 874 in 15350bb
saveWidgets(widgets, event_descr) if save && !skip_store_for.include?(ret) |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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? |
There was a problem hiding this comment.
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" |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
...
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
documentation
this should fix Travis
# @example | ||
# term(:FrameWithMarginBox, "Title", "arg1", "arg2") | ||
# -> | ||
# Frame("Title", MarginBox(1.45, 0.45, "arg1", "arg2")) |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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
|
||
# @return [Array<Symbol>] | ||
# Events for which `store` won't be called, see {Yast::CWMClass#show} | ||
def skip_store_for |
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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
There was a problem hiding this 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
These are needed for the Expert Partitioner, and were introduced in yast/yast-partitioner#5 (because we had not branched SP3 back then)