Class: Continuum::AMPReportingService

Inherits:
Object
  • Object
show all
Defined in:
src/lib/continuum/amp_reporting_service.rb

Overview

This class encapsulates all functionality for submitting accessibility concerns identified using Continuum to AMP.

Reporting test results from Continuum to AMP is accomplished through a kind of state machine, where you set the active AMP instance, organization, asset, report, and module to use; once these are set, they remain set for as long as they’re not set again and for as long as Continuum is initialized. Depending on the report and module management strategies you decide to use—see ReportManagementStrategy and ModuleManagementStrategy, respectively—invoking #submit_accessibility_concerns_to_amp will first create, overwrite, and/or delete reports and modules from AMP, then publish your test results to the active AMP module. You can set the active report and module management strategies using #active_report_management_strategy and #active_module_management_strategy, respectively. Only once all of these active items are set should you invoke #submit_accessibility_concerns_to_amp using the list of accessibility concerns you’d like to report.

More on report and module management strategies

They are designed with two primary use cases in mind: continuous integration (CI) workflows (where you usually want to retain the results of previously published reports), and more manual workflows (e.g. when Continuum is run from a developer’s local workstation, where you usually don’t want to retain the results of previously published reports). Choosing the correct report and module management strategies to meet your business objectives is critical to using Continuum’s AMP reporting functionality correctly, so please consult our support documentation for more information.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(driver) ⇒ AMPReportingService

Returns a new instance of AMPReportingService.

Parameters:

  • driver (Selenium::WebDriver::Driver)

    The selenium driver instance



71
72
73
74
75
76
77
78
79
80
81
# File 'src/lib/continuum/amp_reporting_service.rb', line 71

def initialize(driver)
  @driver = driver
  @active_instance = Continuum.configuration.amp_instance_url
  @active_organization_id = nil
  @active_asset_id = nil
  @suppress_sensitive_data = false
  @active_report = nil
  @active_module = nil
  @active_report_management_strategy = nil
  @active_module_management_strategy = nil
end

Instance Attribute Details

#active_moduleModule? (readonly)

Gets the active module. This is nil if #set_active_module_by_id or #set_active_module_by_name hasn’t been invoked to set an active module yet. Use this to access the active module’s metadata, e.g. its ID in AMP, its name, etc.

Returns:

  • (Module, nil)

    The active module



56
57
58
# File 'src/lib/continuum/amp_reporting_service.rb', line 56

def active_module
  @active_module
end

#active_module_management_strategyModuleManagementStrategy? (readonly)

Gets the active module management strategy. This is nil if #set_active_module_management_strategy hasn’t been invoked yet.

Returns:



68
69
70
# File 'src/lib/continuum/amp_reporting_service.rb', line 68

def active_module_management_strategy
  @active_module_management_strategy
end

#active_reportReport? (readonly)

Gets the active report. This is nil if #set_active_report_by_id or #set_active_report_by_name hasn’t been invoked to set an active report yet. Use this to access the active report’s metadata, e.g. its ID in AMP, its name, etc.

Returns:

  • (Report, nil)

    The active report



48
49
50
# File 'src/lib/continuum/amp_reporting_service.rb', line 48

def active_report
  @active_report
end

#active_report_management_strategyReportManagementStrategy? (readonly)

Gets the active report management strategy. This is nil if #set_active_report_management_strategy hasn’t been invoked yet.

Returns:



62
63
64
# File 'src/lib/continuum/amp_reporting_service.rb', line 62

def active_report_management_strategy
  @active_report_management_strategy
end

#driverSelenium::WebDriver::Driver

Returns:

  • (Selenium::WebDriver::Driver)


40
41
42
# File 'src/lib/continuum/amp_reporting_service.rb', line 40

def driver
  @driver
end

Instance Method Details

#set_active_asset(asset_id) ⇒ Object

Validates the specified ID of an existing asset in AMP, then sets it as the active asset in Continuum such that next time #submit_accessibility_concerns_to_amp is invoked, test results will be submitted to this active asset. Make sure you first set the active organization for this asset prior to invoking this function using #set_active_organization.

Parameters:

  • asset_id (Integer)

    The ID of the AMP asset to make active

Raises:

  • (Error)

    If the active organization has not been set yet

  • (TypeError)

    If the specified asset ID is nil or non-integer

  • (HttpErrorException)

    If an error is encountered while attempting to connect to AMP to validate the specified asset ID

  • (NotFoundException)

    If the specified asset may not exist in the active AMP instance or is otherwise not accessible



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'src/lib/continuum/amp_reporting_service.rb', line 128

def set_active_asset(asset_id)
  unless @active_organization_id
    raise Error.new('Active organization has not been set')
  end

  unless asset_id.is_a?(Integer)
    raise TypeError.new('Active asset cannot be nil')
  end

  query_params = {
    'assetId' => asset_id
  }

  response = NetworkUtil.get_from_amp('/api/cont/asset/validate', query_params, true)

  unless response_valid?(response)
    message = response['message'] ? "; #{response['message']}" : ''
    raise NotFoundException.new(
      "Asset with ID '#{asset_id}' not found in active AMP instance '#{@active_instance}'#{message}'"
    )
  end

  @active_asset_id = asset_id
  @suppress_sensitive_data = !!response['suppressSensitiveData']
end

#set_active_module_by_id(module_id) ⇒ Object

Validates the specified ID of an existing module in AMP, then sets it as the active module in Continuum such that next time #submit_accessibility_concerns_to_amp is invoked, test results will be submitted to this active module. Make sure you first set the active organization, asset, and report for this module prior to invoking this method using #set_active_organization, #set_active_asset, and #set_active_report_by_id or #set_active_report_by_name, respectively. While using ReportManagementStrategy::OVERWRITE as your report management strategy, use #set_active_module_by_name instead of this method; see the documentation for ReportManagementStrategy::OVERWRITE for details as to why.

Parameters:

  • module_id (Integer)

    The ID of the AMP module to make active

Raises:

  • (Error)

    If the active organization, asset, report or module ID is not set

  • (TypeError)

    If the specified module ID is nil or non-integer

  • (HttpErrorException)

    If an error is encountered while attempting to connect to AMP to validate the specified module ID

  • (NotFoundException)

    If the specified module may not exist in the active AMP report



202
203
204
# File 'src/lib/continuum/amp_reporting_service.rb', line 202

def set_active_module_by_id(module_id)
  get_module_details_from_amp(module_id: module_id)
end

#set_active_module_by_name(module_name, module_location) ⇒ Integer?

Sets the active module in AMP to submit test results to next time #submit_accessibility_concerns_to_amp is invoked. The module name specified is validated if the active report already exists in AMP, but unlike #set_active_module_by_id, this method will not throw an exception if the specified module does not yet exist in AMP; it will be created next time #submit_accessibility_concerns_to_amp is invoked. Make sure you first set the active organization, asset, and report for this module prior to invoking this method using #set_active_organization, #set_active_asset, and #set_active_report_by_id or #set_active_report_by_name, respectively.

Parameters:

  • module_name (String)

    The name of the AMP module to make active

  • module_location (String)

    The name of the location in the website or app being tested; this can be a fully qualified URL, or simply a page title like “Login Page”

Returns:

  • (Integer, nil)

    The ID of the AMP module, if it already exists; Nil if the module does not yet exist in AMP

Raises:

  • (Error)

    If the active organization, asset, report or module name and location is not set

  • (TypeError)

    If the specified module name or module location is nil or non-string

  • (HttpErrorException)

    If an error is encountered while attempting to connect to AMP to validate the specified module ID



223
224
225
# File 'src/lib/continuum/amp_reporting_service.rb', line 223

def set_active_module_by_name(module_name, module_location)
  return get_module_details_from_amp(module_name: module_name, module_location: module_location)
end

#set_active_module_management_strategy(module_management_strategy) ⇒ Object

Sets the active module management strategy to use next time #submit_accessibility_concerns_to_amp is invoked. Choosing the correct report and module management strategies to meet your business objectives is critical to using Continuum’s AMP reporting functionality correctly, so please consult our support documentation for more information.

Parameters:



245
246
247
# File 'src/lib/continuum/amp_reporting_service.rb', line 245

def set_active_module_management_strategy(module_management_strategy)
  @active_module_management_strategy = module_management_strategy
end

#set_active_organization(organization_id) ⇒ Object

Validates the specified ID of an existing organization in AMP, then sets it as the active organization in Continuum such that next time #submit_accessibility_concerns_to_amp is invoked, test results will be submitted to this active organization.

Parameters:

  • organization_id (Integer)

    The ID of the AMP organization to make active

Raises:

  • (TypeError)

    If the specified organization ID is nil or non-integer

  • (HttpErrorException)

    If an error is encountered while attempting to connect to AMP to validate the specified organization ID

  • (NotFoundException)

    If the specified organization may not exist in the active AMP instance or is otherwise not accessible



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'src/lib/continuum/amp_reporting_service.rb', line 95

def set_active_organization(organization_id)
  unless organization_id.is_a?(Integer)
    raise TypeError.new('Active organization cannot be nil')
  end

  query_params = {
    'organizationId' => organization_id
  }

  response = NetworkUtil.get_from_amp('/api/cont/organization/validate', query_params, true)

  unless response_valid?(response)
    message = response['message'] ? "; #{response['message']}" : ''
    raise NotFoundException.new(
      "Organization with ID '#{organization_id}' not found in active AMP instance '#{@active_instance}'#{message}'"
    )
  end

  @active_organization_id = organization_id
end

#set_active_report_by_id(report_id) ⇒ Object

Validates the specified ID of an existing report in AMP, then sets it as the active report in Continuum such that next time #submit_accessibility_concerns_to_amp is invoked, test results will be submitted to this active report. Make sure you first set the active organization and asset for this report prior to invoking this method using #set_active_organization and #set_active_asset, respectively.

Parameters:

  • report_id (Integer)

    The ID of the AMP report to make active

Raises:

  • (Error)

    If the active organization or asset is not set

  • (TypeError)

    If the specified report ID is nil or non-integer

  • (HttpErrorException)

    If an error is encountered while attempting to connect to AMP to validate the specified report ID

  • (NotFoundException)

    If the specified report may not exist in the active AMP instance or is otherwise not accessible



166
167
168
# File 'src/lib/continuum/amp_reporting_service.rb', line 166

def set_active_report_by_id(report_id)
  get_report_details_from_amp(report_id: report_id)
end

#set_active_report_by_name(report_name) ⇒ Integer?

Sets the active report in AMP to submit test results to next time #submit_accessibility_concerns_to_amp is invoked. The report name specified is validated, but unlike #set_active_report_by_id, this method will not throw an exception if the specified report does not yet exist in AMP; it will be created next time #submit_accessibility_concerns_to_amp is invoked. Make sure you first set the active organization and asset for this report prior to invoking this method using #set_active_organization and #set_active_asset, respectively.

Parameters:

  • report_name (String)

    The name of the AMP report to make active

Returns:

  • (Integer, nil)

    The ID of the AMP report, if it already exists; Nil if the report does not yet exist in AMP

Raises:

  • (Error)

    If the active organization or asset is not set

  • (HttpErrorException)

    If an error is encountered while attempting to connect to AMP to validate the specified report name



184
185
186
# File 'src/lib/continuum/amp_reporting_service.rb', line 184

def set_active_report_by_name(report_name)
  return get_report_details_from_amp(report_name: report_name)
end

#set_active_report_management_strategy(report_management_strategy) ⇒ Object

Sets the active report management strategy to use next time #submit_accessibility_concerns_to_amp is invoked. Choosing the correct report and module management strategies to meet your business objectives is critical to using Continuum’s AMP reporting functionality correctly, so please consult our support documentation for more information.

Parameters:



234
235
236
# File 'src/lib/continuum/amp_reporting_service.rb', line 234

def set_active_report_management_strategy(report_management_strategy)
  @active_report_management_strategy = report_management_strategy
end

#submit_accessibility_concerns_to_amp(accessibility_concerns) ⇒ Boolean

Submits accessibility concerns to the active AMP instance, organization, asset, report, and module. Make sure to set the active AMP organization (via #set_active_organization), asset (via #set_active_asset), report (via #set_active_report_by_id or #set_active_report_by_name), and module (via #set_active_module_by_id or #set_active_module_by_name) prior to invoking this method. The active instance, organization, and asset must all already exist in AMP prior to invoking this method, otherwise an exception will be thrown; reports and modules don’t need to exist in AMP yet, as they will be created if necessary. Also, make sure to set your desired report and module management strategies prior to invoking this method using #set_active_report_management_strategy and #set_active_module_management_strategy, respectively, according to your use case. Choosing the correct report and module management strategies to meet your business objectives is critical to using Continuum’s AMP reporting functionality correctly, so please consult our support documentation for more information.

Parameters:

  • accessibility_concerns (Array<AccessibilityConcern>)

    The list of accessibility concerns to submit to AMP

Returns:

  • (Boolean)

    ‘true` if uploading of the specified accessibility concerns to AMP succeeded; `false` if it did not

Raises:

  • (Error)

    If the active instance, organization, asset, report, or module is not set

  • (HttpErrorException)

    If an error is encountered while attempting to connect to AMP to validate the active organization, asset, report, or module

  • (NotFoundException)

    If the active instance, organization, or asset may not exist in AMP as specified, or if an error occurs while attempting to create the necessary report or module in AMP (if applicable)



268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
# File 'src/lib/continuum/amp_reporting_service.rb', line 268

def submit_accessibility_concerns_to_amp(accessibility_concerns)
  # Validate active organization
  set_active_organization(@active_organization_id)

  # Validate active asset
  set_active_asset(@active_asset_id)

  # Validate accessibility concerns are set
  unless accessibility_concerns && accessibility_concerns.size > 0
    raise Error.new('Unable to submit accessibility concerns to AMP, none given.')
  end

  # Validate or create active report
  report_exists_in_amp = false
  if @active_report && @active_report.id && @active_report_management_strategy != ReportManagementStrategy::UNIQUE
    # The active report already has an ID, so verify it still exists in AMP; if it doesn't, abort
    set_active_report_by_id(@active_report.id)
    report_exists_in_amp = true
  else
    # User has requested we guarantee the creation of a new report by modifying
    # the report name they've specified
    if @active_report && @active_report.name && @active_report_management_strategy == ReportManagementStrategy::UNIQUE
      @active_report.name << " (#{DateTime.now.iso8601})"
    end

    # The active report may or may not exist in AMP as no ID was specified, so check and create it if necessary
    set_active_report_by_name(@active_report ? @active_report.name : nil)

    if @active_report.id
      report_exists_in_amp = true
    else
      new_report = create_report(@active_report.name)
      unless new_report
        raise NotFoundException.new("Could not create new report '#{@active_report.name}' in AMP")
      end
      @active_report = new_report

      if @active_module
        # When the time comes, ensure a new module is created for this new report
        @active_module.id = nil
      end
    end
  end

  if report_exists_in_amp && @active_report_management_strategy == ReportManagementStrategy::OVERWRITE
    success = delete_all_modules_in_report(@active_report.id)
    if success
      # Assuming the active module already existed in the active report when they were specified by
      # the user, the active module's ID is no longer valid as this module was just deleted from AMP
      # Clearing out the active module ID here means the active module will get recreated in AMP later on
      # in the same active report as though the user had not specified an ID, which is what we want
      @active_module.id = nil
    else
      report_identifier_text = @active_report.name ? "'#{@active_report.name}'" : "ID #{@active_report.id}"
      raise NotFoundException.new("Could not delete existing modules for report #{report_identifier_text} in AMP")
    end
  end

  # Validate or create active module
  module_exists_in_amp = false
  overwrite_existing_accessibility_concerns = false

  if @active_module && @active_module.id
    # The active module already has an ID, so verify it still exists in AMP
    set_active_module_by_id(@active_module.id)
    module_exists_in_amp = true
  else
    # The active module may or may not exist in AMP as no ID was specified, so check and create it if necessary
    set_active_module_by_name(
      @active_module ? @active_module.name : nil,
      @active_module ? @active_module.location : nil
    )

    if @active_module.id
      module_exists_in_amp = true
    else
      # Module does not yet exist in AMP, so create it
      new_module = create_module(@active_module.name, @active_module.location)
      unless new_module
        raise NotFoundException.new("Could not create new module '#{@active_module.name}' in AMP")
      end
      @active_module = new_module
    end
  end

  if module_exists_in_amp
    if @active_module_management_strategy == ModuleManagementStrategy::ABORT
      logger.info(%{
        The active module already exists in AMP! Aborting reporting to AMP per specified
        module management strategy of ABORT.
      })
      return false
    elsif @active_module_management_strategy == ModuleManagementStrategy::OVERWRITE
      overwrite_existing_accessibility_concerns = true
    end
  end

  # At this point, the active organization, asset, report, and module should all exist in AMP
  # (if they didn't already before)

  # submit module screenshot to AMP
  unless @suppress_sensitive_data
    screenshot_data_uri = "data:image/png;base64,#{@driver.screenshot_as(:base64)}"
    NetworkUtil.post_to_amp('/api/cont/module/screenshot', {
      'moduleID' => @active_module.id.to_s,
      'data' => screenshot_data_uri
    }, true)
  end

  # Gather the accessibility concerns to be submitted to AMP,
  # i.e. just the ones that match the media type of the report
  records = convert_accessibility_concerns_to_amp_format(accessibility_concerns)

  # Actually submit test results to AMP
  body_params = {
    'reportID' => @active_report.id,
    'moduleID' => @active_module.id,
    'overwrite' => overwrite_existing_accessibility_concerns,
    'records' => records
  }

  body_params['moduleName'] = @active_module.name if @active_module.name
  body_params['moduleLocation'] = @active_module.location if @active_module.location

  response = NetworkUtil.post_to_amp('/api/cont/module/upload', body_params, true)
  module_id = response['moduleId'].to_i

  if module_id.is_a?(Integer)
    return module_id > 0
  else
    return false
  end
end