sapphire 0.3.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/bin/sapphire CHANGED
@@ -3,24 +3,24 @@ $:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
3
3
  require 'sapphire'
4
4
  include Sapphire::Sapphire
5
5
 
6
- reporter = ConsoleReporter.new()
6
+ reporter = TeamCityReporter.new()
7
7
 
8
8
  ARGV.each do |arg|
9
9
  if !arg.end_with? ".rb"
10
10
  next
11
11
  end
12
12
  require arg
13
- Runner.instance.last_scenario.file_name = arg
13
+ Runner.instance.last_scenario.file_name = arg if Runner.instance.last_scenario and Runner.instance.last_scenario.file_name == ""
14
14
  end
15
15
 
16
+ reporter.BeginTesting
17
+
16
18
  if Runner.instance.test_plans.count > 0
17
- Runner.instance.last_test_plan.execute reporter
19
+ Runner.instance.last_test_plan.execute
18
20
  else
19
21
  Runner.instance.scenarios.each do |scenario|
20
22
  scenario.execute reporter
21
23
  end
22
24
  end
23
25
 
24
-
25
-
26
26
  reporter.OutputResults
data/lib/sapphire.rb CHANGED
@@ -11,6 +11,7 @@ require 'colorize'
11
11
  require File.expand_path(File.dirname(__FILE__) +'/sapphire/Strategies/Strategy.rb', __FILE__)
12
12
  require File.expand_path(File.dirname(__FILE__) +'/sapphire/Testing/Reporter.rb', __FILE__)
13
13
  Dir[File.dirname(__FILE__) + '/sapphire/Testing/*.rb'].each {|file| require file }
14
+ Dir[File.dirname(__FILE__) + '/sapphire/TeamCity/*.rb'].each {|file| require file }
14
15
  Dir[File.dirname(__FILE__) + '/sapphire/Configuration/*.rb'].each {|file| require file }
15
16
  Dir[File.dirname(__FILE__) + '/sapphire/WebAbstractions/Controls/Base/*.rb'].each {|file| require file }
16
17
  Dir[File.dirname(__FILE__) + '/sapphire/WebAbstractions/Controls/*.rb'].each {|file| require file }
@@ -22,6 +23,7 @@ Dir[File.dirname(__FILE__) + '/sapphire/DSL/Configuration/*.rb'].each {|file| re
22
23
  Dir[File.dirname(__FILE__) + '/sapphire/DSL/Data/*.rb'].each {|file| require file }
23
24
  Dir[File.dirname(__FILE__) + '/sapphire/DSL/Scenarios/*.rb'].each {|file| require file }
24
25
  Dir[File.dirname(__FILE__) + '/sapphire/DSL/TestPlans/*.rb'].each {|file| require file }
26
+ Dir[File.dirname(__FILE__) + '/sapphire/UI/*.rb'].each {|file| require file }
25
27
 
26
28
  module Sapphire
27
29
  module Sapphire
@@ -37,5 +39,7 @@ module Sapphire
37
39
  include JobAbstractions
38
40
  include WebAbstractions
39
41
  include Testing
42
+ include Testing::TeamCity
43
+ include UI
40
44
  end
41
45
  end
@@ -0,0 +1,15 @@
1
+ module Sapphire
2
+ module DSL
3
+ module Browser
4
+ def Virtually(&block)
5
+ ui = VirtualUI.new
6
+ begin
7
+ ui.Create()
8
+ block.call
9
+ ensure
10
+ ui.Close()
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -6,6 +6,7 @@ class Background
6
6
  attr_reader :block
7
7
  attr_reader :parent
8
8
  attr_reader :results
9
+ attr_reader :and
9
10
 
10
11
  def initialize(parent, pre, text, &block)
11
12
  @block = block
@@ -13,6 +14,7 @@ class Background
13
14
  @text = pre + text.to_s
14
15
  @parent = parent
15
16
  @results = []
17
+ @and = []
16
18
  end
17
19
 
18
20
  def AddResult(result)
@@ -21,4 +23,12 @@ class Background
21
23
  self.parent.result.AddChild(result)
22
24
  end
23
25
 
26
+ def add_and(pre, text, &block)
27
+ if(self.value.is_a? Pending)
28
+ self.and << And.new(self, Pending.new(pre + text), &block)
29
+ else
30
+ self.and << And.new(self, pre + text, &block)
31
+ end
32
+ end
33
+
24
34
  end
@@ -20,7 +20,7 @@ module Sapphire
20
20
  def And(text, &block)
21
21
 
22
22
  if(Runner.instance.last_scenario.last_given == nil && Runner.instance.last_scenario.last_background != nil)
23
- Runner.instance.last_scenario.add_background(Background.new(Runner.instance.last_scenario, "And ", text, &block))
23
+ Runner.instance.last_scenario.last_background.add_and("And ", text, &block)
24
24
  return
25
25
  end
26
26
 
@@ -51,7 +51,6 @@ module Sapphire
51
51
  def Scenario(text, &block)
52
52
  Runner.instance.add_scenario(Scenario.new(text, &block))
53
53
  Runner.instance.last_scenario.block.call
54
- #Runner.instance.last_scenario.execute 1
55
54
  end
56
55
  end
57
56
  end
@@ -19,6 +19,7 @@ module Sapphire
19
19
  @givens = []
20
20
  @backgrounds = []
21
21
  @result = Testing::ScenarioResult.new(text)
22
+ @file_name = ""
22
23
  end
23
24
 
24
25
  def add_given(given)
@@ -19,10 +19,10 @@ class Then
19
19
 
20
20
  def add_and(pre, text, &block)
21
21
  if(!self.value.instance_of? Pending)
22
- x = Then.new(self, pre, text, &block)
22
+ x = And.new(self, pre + text, &block)
23
23
  self.and << x
24
24
  else
25
- self.and << Then.new(self, pre, Pending.new(pre + text), &block)
25
+ self.and << And.new(self, Pending.new(pre + text), &block)
26
26
  end
27
27
  end
28
28
 
@@ -3,9 +3,8 @@ module Sapphire
3
3
  module TestPlans
4
4
 
5
5
  def TestPlan(text, &block)
6
- reporter = ConsoleReporter.new()
7
- Runner.instance.add_test_plan(TestPlan.new(text, &block))
8
- Runner.instance.last_test_plan.execute reporter
6
+ reporter = TeamCityReporter.new()
7
+ Runner.instance.add_test_plan(TestPlan.new(text, reporter, &block))
9
8
  end
10
9
 
11
10
  class TestPlan
@@ -14,10 +13,11 @@ module Sapphire
14
13
  attr_reader :value
15
14
  attr_reader :text
16
15
 
17
- def initialize(text, &block)
16
+ def initialize(text, reporter, &block)
18
17
  @value = text
19
18
  @text = text.to_s
20
19
  @block = block
20
+ @reporter = reporter
21
21
 
22
22
  @items = []
23
23
  @handlers = []
@@ -36,7 +36,7 @@ module Sapphire
36
36
  @handlers.each do |handler|
37
37
  handler.keys.each do |handler_key|
38
38
  if(handler_key == key)
39
- handler[handler_key].Handle item[key]
39
+ handler[handler_key].Handle item[key], @reporter
40
40
  end
41
41
  end
42
42
  end
@@ -47,10 +47,11 @@ module Sapphire
47
47
  @handlers << handler
48
48
  end
49
49
 
50
- def execute(reporter)
50
+ def execute
51
+ @reporter.BeginTesting
51
52
  $stdout.puts ""
52
53
  @block.call
53
- reporter.OutputResults
54
+ @reporter.OutputResults
54
55
  end
55
56
  end
56
57
  end
@@ -2,7 +2,7 @@ require 'teamcity/utils/logger_util'
2
2
  require 'teamcity/rake_exceptions'
3
3
  require 'teamcity/rakerunner_consts'
4
4
 
5
- SPEC_FORMATTER_LOG = ::Rake::TeamCity::Utils::RSpecFileLogger.new
5
+ SPEC_FORMATTER_LOG = ::Rake::TeamCity::Utils::RakeFileLogger.new
6
6
  SPEC_FORMATTER_LOG.log_msg("spec formatter.rb loaded.")
7
7
 
8
8
  require 'teamcity/runner_common'
@@ -50,13 +50,13 @@ module Sapphire
50
50
  # Initializes
51
51
  @groups_stack = []
52
52
 
53
- @example_count = 100
54
53
  if ::Rake::TeamCity.is_in_idea_mode
55
- log(@message_factory.create_tests_count(@example_count))
54
+ #log(@message_factory.create_tests_count(@example_count))
56
55
  elsif ::Rake::TeamCity.is_in_buildserver_mode
57
- log(@message_factory.create_progress_message("Starting.. (#{@example_count} examples)"))
56
+ log(@message_factory.create_progress_message("Starting..."))
58
57
  end
59
58
 
59
+ @current = 0
60
60
  end
61
61
 
62
62
  def PrintItem(result, depth)
@@ -64,11 +64,13 @@ module Sapphire
64
64
  end
65
65
 
66
66
  def ScenarioStart(scenario)
67
- @message_factory.create_suite_started(scenario.text, scenario.file_name)
67
+ log(@message_factory.create_suite_started("Scenario: " + scenario.text))
68
68
  end
69
69
 
70
70
  def ScenarioComplete(scenario)
71
- @message_factory.create_suite_finished(scenario.text)
71
+ log(@message_factory.create_suite_finished("Finally"))
72
+ log(@message_factory.create_suite_finished("Assuming"))
73
+ log(@message_factory.create_suite_finished("Scenario: " + scenario.text))
72
74
  end
73
75
 
74
76
  def PrintHeader()
@@ -92,25 +94,65 @@ module Sapphire
92
94
  end
93
95
 
94
96
  def TestStarted(test)
95
- @@RUNNING_EXAMPLES_STORAGE[test.object_id] = test
97
+
98
+ if test.is_a? Given and @current > 0
99
+ log(@message_factory.create_suite_finished("Then"))
100
+ log(@message_factory.create_suite_finished("When"))
101
+ log(@message_factory.create_suite_finished("Given"))
102
+ elsif test.is_a? Finally
103
+ log(@message_factory.create_suite_finished("Then"))
104
+ log(@message_factory.create_suite_finished("When"))
105
+ log(@message_factory.create_suite_finished("Given"))
106
+ end
107
+
108
+ @current = 1
109
+
110
+ if test.is_a? Given
111
+ log(@message_factory.create_suite_started("Given"))
112
+ elsif test.is_a? When
113
+ log(@message_factory.create_suite_started("When"))
114
+ elsif test.is_a? Then
115
+ log(@message_factory.create_suite_started("Then"))
116
+ elsif test.is_a? Background
117
+ log(@message_factory.create_suite_started("Assuming"))
118
+ elsif test.is_a? Finally
119
+ log(@message_factory.create_suite_started("Finally"))
120
+ end
121
+
122
+ @current = @current + 1
123
+
124
+ log(@message_factory.create_test_started(test.text))
96
125
  end
97
126
 
98
127
  def TestCompleted(test)
99
128
  if test.type == "pending"
100
- @message_factory.create_test_output_message(test.text, true, "Pending: Not Yet Implemented")
101
- @message_factory.create_test_ignored(test.text, "Pending: Not Yet Implemented")
102
- return
129
+ log(@message_factory.create_test_ignored(test.text, "Pending: Not Yet Implemented"))
130
+ elsif test.type == "pass"
131
+ log(@message_factory.create_test_finished(test.text, test.time))
132
+ elsif test.type == "fail"
133
+
134
+ if test.messages.is_a? Array
135
+ messages = test.messages.join("\n")
136
+ else
137
+ messages = test.messages
138
+ end
139
+ stack = ""
140
+ test.stack.each do |line|
141
+ if (!line.include? "sapphire")
142
+ stack += line + "\n"
143
+ end
103
144
  end
104
- if test.type == "pass"
105
- @message_factory.create_test_finished(test.text, test.time)
106
- return
145
+ log(@message_factory.create_test_failed(test.text, messages, stack))
107
146
  end
108
- if test.type == "fail"
109
- @message_factory.create_test_output_message(test.text, true, "enter error here")
110
- @message_factory.create_test_failed(test.text, test.message, "enter backtrace here")
147
+
148
+ if test.item.is_a? Finally
149
+ log(@message_factory.create_suite_finished("Finally"))
111
150
  end
112
151
 
113
- @@RUNNING_EXAMPLES_STORAGE.delete(test.object_id)
152
+ end
153
+
154
+ def BeginTesting
155
+ log(@message_factory.create_test_reported_attached)
114
156
  end
115
157
  end
116
158
  end
@@ -83,6 +83,10 @@ module Sapphire
83
83
  $stdout.print "F".red if test.type == "fail"
84
84
  end
85
85
 
86
+ def BeginTesting
87
+
88
+ end
89
+
86
90
  end
87
91
  end
88
92
  end
@@ -3,7 +3,7 @@ module Sapphire
3
3
  module Executable
4
4
  def execute(reporter)
5
5
  start = Time.now
6
- reporter.TestStarted(self.text)
6
+ reporter.TestStarted(self)
7
7
  begin
8
8
  if(self.value.is_a? Pending)
9
9
  result = ResultTree.new(self.text, TestResult.new("pending", self, "Pending", "", Time.now - start))
@@ -42,6 +42,9 @@ module Sapphire
42
42
 
43
43
  end
44
44
 
45
+ def BeginTesting
46
+
47
+ end
45
48
  end
46
49
  end
47
50
  end
@@ -4,18 +4,20 @@ module Sapphire
4
4
 
5
5
  def execute(reporter)
6
6
  reporter.ScenarioStart self
7
- @failures = []
8
- @pendings = []
9
- @success = []
10
7
 
11
8
  self.backgrounds.each do |b|
12
9
 
13
10
  b.execute reporter
14
11
 
12
+ b.and.each do |g_a|
13
+
14
+ g_a.execute reporter
15
+
16
+ end
17
+
15
18
  end
16
19
 
17
20
  self.givens.each do |g|
18
-
19
21
  g.when.each do |w|
20
22
 
21
23
  g.execute reporter
@@ -0,0 +1,286 @@
1
+ module ChildProcess
2
+ module Windows
3
+ module Lib
4
+
5
+ def self.create_proc(cmd, opts = {})
6
+ cmd_ptr = FFI::MemoryPointer.from_string cmd
7
+
8
+ flags = 0
9
+ inherit = !!opts[:inherit]
10
+
11
+ flags |= DETACHED_PROCESS if opts[:detach]
12
+
13
+ si = StartupInfo.new
14
+ pi = ProcessInfo.new
15
+
16
+ if opts[:stdout] || opts[:stderr]
17
+ si[:dwFlags] ||= 0
18
+ si[:dwFlags] |= STARTF_USESTDHANDLES
19
+ inherit = true
20
+
21
+ si[:hStdOutput] = handle_for(opts[:stdout].fileno) if opts[:stdout]
22
+ si[:hStdError] = handle_for(opts[:stderr].fileno) if opts[:stderr]
23
+ end
24
+
25
+ if opts[:duplex]
26
+ read_pipe_ptr = FFI::MemoryPointer.new(:pointer)
27
+ write_pipe_ptr = FFI::MemoryPointer.new(:pointer)
28
+ sa = SecurityAttributes.new(:inherit => true)
29
+
30
+ ok = create_pipe(read_pipe_ptr, write_pipe_ptr, sa, 0)
31
+ ok or raise Error, last_error_message
32
+
33
+ read_pipe = read_pipe_ptr.read_pointer
34
+ write_pipe = write_pipe_ptr.read_pointer
35
+
36
+ si[:hStdInput] = read_pipe
37
+ end
38
+
39
+ si[:lpDesktop] = FFI::MemoryPointer.from_string("test") if $isVirtual
40
+
41
+ ok = create_process(nil, cmd_ptr, nil, nil, inherit, flags, nil, nil, si, pi)
42
+ ok or raise Error, last_error_message
43
+
44
+ close_handle pi[:hProcess]
45
+ close_handle pi[:hThread]
46
+
47
+ if opts[:duplex]
48
+ opts[:stdin] = io_for(duplicate_handle(write_pipe), File::WRONLY)
49
+ close_handle read_pipe
50
+ close_handle write_pipe
51
+ end
52
+
53
+ pi[:dwProcessId]
54
+ end
55
+
56
+ def self.last_error_message
57
+ errnum = get_last_error
58
+ buf = FFI::MemoryPointer.new :char, 512
59
+
60
+ size = format_message(
61
+ FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY,
62
+ nil, errnum, 0, buf, buf.size, nil
63
+ )
64
+
65
+ buf.read_string(size).strip
66
+ end
67
+
68
+ def self.handle_for(fd_or_io)
69
+ case fd_or_io
70
+ when IO
71
+ handle = get_osfhandle(fd.fileno)
72
+ when Fixnum
73
+ handle = get_osfhandle(fd_or_io)
74
+ else
75
+ if fd_or_io.respond_to?(:to_io)
76
+ io = fd_or_io.to_io
77
+
78
+ unless io.kind_of?(IO)
79
+ raise TypeError, "expected #to_io to return an instance of IO"
80
+ end
81
+
82
+ handle = get_osfhandle(io.fileno)
83
+ else
84
+ raise TypeError, "invalid type: #{fd_or_io.inspect}"
85
+ end
86
+ end
87
+
88
+ if handle == INVALID_HANDLE_VALUE
89
+ raise Error, last_error_message
90
+ end
91
+
92
+ handle
93
+ end
94
+
95
+ def self.io_for(handle, flags = File::RDONLY)
96
+ fd = open_osfhandle(handle, flags)
97
+ if fd == -1
98
+ raise Error, last_error_message
99
+ end
100
+
101
+ ::IO.for_fd fd, flags
102
+ end
103
+
104
+ def self.duplicate_handle(handle)
105
+ dup = FFI::MemoryPointer.new(:pointer)
106
+ proc = current_process
107
+
108
+ ok = _duplicate_handle(
109
+ proc, handle, proc, dup, 0, false, DUPLICATE_SAME_ACCESS)
110
+
111
+ ok or raise Error, last_error_message
112
+
113
+ dup.read_pointer
114
+ ensure
115
+ close_handle proc
116
+ end
117
+
118
+ #
119
+ # BOOL WINAPI CreateProcess(
120
+ # __in_opt LPCTSTR lpApplicationName,
121
+ # __inout_opt LPTSTR lpCommandLine,
122
+ # __in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes,
123
+ # __in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes,
124
+ # __in BOOL bInheritHandles,
125
+ # __in DWORD dwCreationFlags,
126
+ # __in_opt LPVOID lpEnvironment,
127
+ # __in_opt LPCTSTR lpCurrentDirectory,
128
+ # __in LPSTARTUPINFO lpStartupInfo,
129
+ # __out LPPROCESS_INFORMATION lpProcessInformation
130
+ # );
131
+ #
132
+
133
+ attach_function :create_process, :CreateProcessA, [
134
+ :pointer,
135
+ :pointer,
136
+ :pointer,
137
+ :pointer,
138
+ :bool,
139
+ :ulong,
140
+ :pointer,
141
+ :pointer,
142
+ :pointer,
143
+ :pointer],
144
+ :bool
145
+
146
+ #
147
+ # DWORD WINAPI GetLastError(void);
148
+ #
149
+
150
+ attach_function :get_last_error, :GetLastError, [], :ulong
151
+
152
+ #
153
+ # DWORD WINAPI FormatMessage(
154
+ # __in DWORD dwFlags,
155
+ # __in_opt LPCVOID lpSource,
156
+ # __in DWORD dwMessageId,
157
+ # __in DWORD dwLanguageId,
158
+ # __out LPTSTR lpBuffer,
159
+ # __in DWORD nSize,
160
+ # __in_opt va_list *Arguments
161
+ # );
162
+ #
163
+
164
+ attach_function :format_message, :FormatMessageA, [
165
+ :ulong,
166
+ :pointer,
167
+ :ulong,
168
+ :ulong,
169
+ :pointer,
170
+ :ulong,
171
+ :pointer],
172
+ :ulong
173
+
174
+
175
+ attach_function :close_handle, :CloseHandle, [:pointer], :bool
176
+
177
+ #
178
+ # HANDLE WINAPI OpenProcess(
179
+ # __in DWORD dwDesiredAccess,
180
+ # __in BOOL bInheritHandle,
181
+ # __in DWORD dwProcessId
182
+ # );
183
+ #
184
+
185
+ attach_function :open_process, :OpenProcess, [:ulong, :bool, :ulong], :pointer
186
+
187
+ #
188
+ # DWORD WINAPI WaitForSingleObject(
189
+ # __in HANDLE hHandle,
190
+ # __in DWORD dwMilliseconds
191
+ # );
192
+ #
193
+
194
+ attach_function :wait_for_single_object, :WaitForSingleObject, [:pointer, :ulong], :wait_status
195
+
196
+ #
197
+ # BOOL WINAPI GetExitCodeProcess(
198
+ # __in HANDLE hProcess,
199
+ # __out LPDWORD lpExitCode
200
+ # );
201
+ #
202
+
203
+ attach_function :get_exit_code, :GetExitCodeProcess, [:pointer, :pointer], :bool
204
+
205
+ #
206
+ # BOOL WINAPI GenerateConsoleCtrlEvent(
207
+ # __in DWORD dwCtrlEvent,
208
+ # __in DWORD dwProcessGroupId
209
+ # );
210
+ #
211
+
212
+ attach_function :generate_console_ctrl_event, :GenerateConsoleCtrlEvent, [:ulong, :ulong], :bool
213
+
214
+ #
215
+ # BOOL WINAPI TerminateProcess(
216
+ # __in HANDLE hProcess,
217
+ # __in UINT uExitCode
218
+ # );
219
+ #
220
+
221
+ attach_function :terminate_process, :TerminateProcess, [:pointer, :uint], :bool
222
+
223
+ #
224
+ # long _get_osfhandle(
225
+ # int fd
226
+ # );
227
+ #
228
+
229
+ attach_function :get_osfhandle, :_get_osfhandle, [:int], :long
230
+
231
+ #
232
+ # int _open_osfhandle (
233
+ # intptr_t osfhandle,
234
+ # int flags
235
+ # );
236
+ #
237
+
238
+ attach_function :open_osfhandle, :_open_osfhandle, [:pointer, :int], :int
239
+
240
+ # BOOL WINAPI SetHandleInformation(
241
+ # __in HANDLE hObject,
242
+ # __in DWORD dwMask,
243
+ # __in DWORD dwFlags
244
+ # );
245
+
246
+ attach_function :set_handle_information, :SetHandleInformation, [:long, :ulong, :ulong], :bool
247
+
248
+ # BOOL WINAPI CreatePipe(
249
+ # __out PHANDLE hReadPipe,
250
+ # __out PHANDLE hWritePipe,
251
+ # __in_opt LPSECURITY_ATTRIBUTES lpPipeAttributes,
252
+ # __in DWORD nSize
253
+ # );
254
+
255
+ attach_function :create_pipe, :CreatePipe, [:pointer, :pointer, :pointer, :ulong], :bool
256
+
257
+ #
258
+ # HANDLE WINAPI GetCurrentProcess(void);
259
+ #
260
+
261
+ attach_function :current_process, :GetCurrentProcess, [], :pointer
262
+
263
+ #
264
+ # BOOL WINAPI DuplicateHandle(
265
+ # __in HANDLE hSourceProcessHandle,
266
+ # __in HANDLE hSourceHandle,
267
+ # __in HANDLE hTargetProcessHandle,
268
+ # __out LPHANDLE lpTargetHandle,
269
+ # __in DWORD dwDesiredAccess,
270
+ # __in BOOL bInheritHandle,
271
+ # __in DWORD dwOptions
272
+ # );
273
+ #
274
+
275
+ attach_function :_duplicate_handle, :DuplicateHandle, [
276
+ :pointer,
277
+ :pointer,
278
+ :pointer,
279
+ :pointer,
280
+ :ulong,
281
+ :bool,
282
+ :ulong
283
+ ], :bool
284
+ end # Lib
285
+ end # Windows
286
+ end # ChildProcess
@@ -0,0 +1,68 @@
1
+ require 'ffi'
2
+
3
+ module Sapphire
4
+ module UI
5
+ extend FFI::Library
6
+
7
+ ffi_lib 'user32'
8
+ ffi_convention :stdcall
9
+ attach_function :CreateDesktop, :CreateDesktopA, [ :string, :pointer, :pointer, :int, :long, :pointer ], :int
10
+ attach_function :CloseDesktop, [ :int ], :bool
11
+
12
+ ffi_lib 'kernel32'
13
+ attach_function :CreateProcess, :CreateProcessA, [ :pointer, :pointer, :pointer, :pointer, :int, :ushort, :pointer, :pointer, :pointer, :pointer], :int
14
+ attach_function :GetLastError, [ ], :ushort
15
+
16
+ class StartUpInfo < FFI::Struct
17
+ layout :cb, :ushort,
18
+ :lpReserved, :pointer,
19
+ :lpDesktop, :pointer,
20
+ :lpTitle, :pointer,
21
+ :dwX, :ushort,
22
+ :dwY, :ushort,
23
+ :dwXSize, :ushort,
24
+ :dwYSize, :ushort,
25
+ :dwXCountChars, :ushort,
26
+ :dwYCountChars, :ushort,
27
+ :dwFillAttribute, :ushort,
28
+ :dwFlags, :ushort,
29
+ :wShowWindow, :short,
30
+ :cbReserved2, :short,
31
+ :lpReserved2, :pointer,
32
+ :hStdInput, :pointer,
33
+ :hStdOutput, :pointer,
34
+ :hStdError, :pointer
35
+ end
36
+
37
+ class ProcessInformation < FFI::Struct
38
+ layout :hProcess, :pointer,
39
+ :hThread, :pointer,
40
+ :dwProcessId, :ushort,
41
+ :dwThreadId, :ushort
42
+ end
43
+
44
+ class VirtualUI
45
+
46
+ def Create()
47
+
48
+ @off_screen = UI::CreateDesktop("test", nil, nil, 0, 0x02000000, nil)
49
+
50
+ if(@off_screen == nil)
51
+ raise "Could not create a virtual desktop :("
52
+ end
53
+
54
+ $isVirtual = true
55
+
56
+ end
57
+
58
+ def Close()
59
+ $isVirtual = false
60
+ result = UI::CloseDesktop(@off_screen)
61
+
62
+ if(result == 0)
63
+ raise "Could not close the virtual desktop :("
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -1,3 +1,3 @@
1
1
  module Sapphire
2
- VERSION = "0.3.1"
2
+ VERSION = "0.4.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sapphire
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-09-24 00:00:00.000000000Z
12
+ date: 2011-09-30 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: selenium-webdriver
16
- requirement: &9381432 !ruby/object:Gem::Requirement
16
+ requirement: &9888888 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *9381432
24
+ version_requirements: *9888888
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: colorize
27
- requirement: &9381132 !ruby/object:Gem::Requirement
27
+ requirement: &9888636 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *9381132
35
+ version_requirements: *9888636
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: win32console
38
- requirement: &9380832 !ruby/object:Gem::Requirement
38
+ requirement: &9888384 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,7 +43,7 @@ dependencies:
43
43
  version: '0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *9380832
46
+ version_requirements: *9888384
47
47
  description: An automated web acceptance test framework for non-technical resources
48
48
  using selenium-wedriver.
49
49
  email:
@@ -91,6 +91,7 @@ files:
91
91
  - lib/sapphire/DSL/Browser/Tracker.rb
92
92
  - lib/sapphire/DSL/Browser/Transition.rb
93
93
  - lib/sapphire/DSL/Browser/Uncheck.rb
94
+ - lib/sapphire/DSL/Browser/Virtually.rb
94
95
  - lib/sapphire/DSL/Browser/With.rb
95
96
  - lib/sapphire/DSL/Configuration/ConfiguredBrowser.rb
96
97
  - lib/sapphire/DSL/Configuration/ConfiguredUser.rb
@@ -138,6 +139,8 @@ files:
138
139
  - lib/sapphire/Testing/ScenarioResult.rb
139
140
  - lib/sapphire/Testing/TestResult.rb
140
141
  - lib/sapphire/Testing/TestRunnerAdapter.rb
142
+ - lib/sapphire/UI/Functions.rb
143
+ - lib/sapphire/UI/VirtualUI.rb
141
144
  - lib/sapphire/version.rb
142
145
  - lib/sapphire/WebAbstractions/Controls/Base/Control.rb
143
146
  - lib/sapphire/WebAbstractions/Controls/Base/Page.rb