Add timestamps to properly cache invalidate and add spec

pull/8115/head
Oliver Günther 5 years ago
parent b70830483c
commit 442d26f14f
No known key found for this signature in database
GPG Key ID: A3A8BDAD7C0C552C
  1. 6
      db/migrate/20200310092237_add_timestamps_to_bcf.rb
  2. 3
      frontend/src/app/modules/bim/bcf/bcf-wp-single-view/bcf-wp-single-view.component.sass
  3. 48
      frontend/src/app/modules/bim/bcf/bcf-wp-single-view/bcf-wp-single-view.component.ts
  4. 10
      modules/bim/spec/features/bim_navigation_spec.rb
  5. 12
      modules/bim/spec/features/model_viewer_spec.rb
  6. 8
      modules/bim/spec/features/show_default_spec.rb
  7. 91
      modules/bim/spec/features/viewer/create_viewpoint_spec.rb
  8. 32
      modules/bim/spec/spec_helper.rb
  9. 83
      modules/bim/spec/support/components/xeokit_model_tree.rb
  10. 6
      modules/bim/spec/support/pages/ifc_models/bcf_details_page.rb
  11. 41
      modules/bim/spec/support/pages/ifc_models/show_default.rb

@ -0,0 +1,6 @@
class AddTimestampsToBcf < ActiveRecord::Migration[6.0]
def change
add_timestamps :bcf_issues, default: DateTime.now
add_timestamps :bcf_viewpoints, default: DateTime.now
end
end

@ -16,6 +16,7 @@ ngx-gallery ::ng-deep
color: var(--content-link-color)
// Disable red border on active thumbnails
.ngx-gallery-active
.ngx-gallery-active,
.ngx-gallery-thumbnail
border: none !important

@ -10,6 +10,7 @@ import {CurrentProjectService} from "core-components/projects/current-project.se
import {I18nService} from "core-app/modules/common/i18n/i18n.service";
import {ViewerBridgeService} from "core-app/modules/bim/bcf/bcf-viewer-bridge/viewer-bridge.service";
import {WorkPackageCacheService} from "core-components/work-packages/work-package-cache.service";
import {untilComponentDestroyed} from "ng2-rx-componentdestroyed";
export type ViewPoint = { snapshotId:string, snapshotFullPath:string };
@ -101,22 +102,18 @@ export class BcfWpSingleViewComponent implements OnInit, OnDestroy {
}
ngOnInit():void {
this.viewpoints = (this.workPackage.bcfViewpoints || []).map((vp:HalLink) => {
const viewpointResource = this.bcfApi.parse(vp.href!) as BcfViewpointPaths;
return {
snapshotId: viewpointResource.id,
snapshotFullPath: `${vp.href}/snapshot`
} as ViewPoint;
});
this.galleryImages = this.viewpoints.map(viewpoint => {
return {
small: viewpoint.snapshotFullPath,
medium: viewpoint.snapshotFullPath,
big: viewpoint.snapshotFullPath,
};
});
this.wpCache
.observe(this.workPackage.id!)
.pipe(
untilComponentDestroyed(this)
)
.subscribe(wp => {
this.workPackage = wp;
if (wp.bcfViewpoints) {
this.setViewpoints();
}
});
}
ngOnDestroy():void {
@ -180,4 +177,23 @@ export class BcfWpSingleViewComponent implements OnInit, OnDestroy {
.toPromise()
.then(resource => resource.guid);
}
private setViewpoints() {
this.viewpoints = this.workPackage.bcfViewpoints.map((vp:HalLink) => {
const viewpointResource = this.bcfApi.parse(vp.href!) as BcfViewpointPaths;
return {
snapshotId: viewpointResource.id,
snapshotFullPath: `${vp.href}/snapshot`
} as ViewPoint;
});
this.galleryImages = this.viewpoints.map(viewpoint => {
return {
small: viewpoint.snapshotFullPath,
medium: viewpoint.snapshotFullPath,
big: viewpoint.snapshotFullPath,
};
});
}
}

@ -26,11 +26,7 @@
# See docs/COPYRIGHT.rdoc for more details.
#++
require 'spec_helper'
require_relative '../support/pages/ifc_models/show'
require_relative '../support/pages/ifc_models/show_default'
require_relative '../support/pages/ifc_models/bcf_details_page'
require_relative '../spec_helper'
describe 'BIM navigation spec', type: :feature, js: true do
let(:project) { FactoryBot.create :project, enabled_module_names: [:bim, :work_package_tracking] }
@ -51,7 +47,7 @@ describe 'BIM navigation spec', type: :feature, js: true do
let(:card_view) { ::Pages::WorkPackageCards.new(project) }
let(:details_view) { ::Pages::BcfDetailsPage.new(work_package, project) }
let(:model_tree) { ::Components::XeokitModelTree.new }
shared_examples 'can switch from split to viewer to list-only' do
before do
@ -72,7 +68,7 @@ describe 'BIM navigation spec', type: :feature, js: true do
model_page.model_viewer_visible true
model_page.model_viewer_shows_a_toolbar true
model_page.page_shows_a_toolbar true
model_page.sidebar_shows_viewer_menu true
model_tree.sidebar_shows_viewer_menu true
expect(page).to have_selector('.wp-cards-container')
card_view.expect_work_package_listed work_package

@ -26,10 +26,7 @@
# See docs/COPYRIGHT.rdoc for more details.
#++
require 'spec_helper'
require_relative '../support/pages/ifc_models/show'
require_relative '../support/pages/ifc_models/show_default'
require_relative '../spec_helper'
describe 'model viewer', type: :feature, js: true do
let(:project) { FactoryBot.create :project, enabled_module_names: [:bim, :work_package_tracking] }
@ -50,6 +47,7 @@ describe 'model viewer', type: :feature, js: true do
end
let(:show_model_page) { Pages::IfcModels::Show.new(project, model.id) }
let(:model_tree) { ::Components::XeokitModelTree.new }
let(:card_view) { ::Pages::WorkPackageCards.new(project) }
context 'with all permissions' do
@ -64,7 +62,7 @@ describe 'model viewer', type: :feature, js: true do
show_model_page.model_viewer_visible true
show_model_page.model_viewer_shows_a_toolbar true
show_model_page.page_shows_a_toolbar true
show_model_page.sidebar_shows_viewer_menu true
model_tree.sidebar_shows_viewer_menu true
end
it 'shows a work package list as cards next to the viewer' do
@ -91,7 +89,7 @@ describe 'model viewer', type: :feature, js: true do
show_model_page.model_viewer_visible true
show_model_page.model_viewer_shows_a_toolbar true
show_model_page.page_shows_a_toolbar false
show_model_page.sidebar_shows_viewer_menu true
model_tree.sidebar_shows_viewer_menu true
end
end
@ -116,7 +114,7 @@ describe 'model viewer', type: :feature, js: true do
show_model_page.model_viewer_visible false
show_model_page.model_viewer_shows_a_toolbar false
show_model_page.page_shows_a_toolbar false
show_model_page.sidebar_shows_viewer_menu false
model_tree.sidebar_shows_viewer_menu false
end
it 'shows no work package list next to the viewer' do

@ -26,10 +26,7 @@
# See docs/COPYRIGHT.rdoc for more details.
#++
require 'spec_helper'
require_relative '../support/pages/ifc_models/index'
require_relative '../support/pages/ifc_models/show_default'
require_relative '../spec_helper'
describe 'show default model', type: :feature, js: true do
let(:project) { FactoryBot.create :project, enabled_module_names: %i[bim work_package_tracking] }
@ -50,6 +47,7 @@ describe 'show default model', type: :feature, js: true do
uploader: user)
end
let(:model_is_default) { true }
let(:model_tree) { ::Components::XeokitModelTree.new }
before do
login_as(user)
@ -75,7 +73,7 @@ describe 'show default model', type: :feature, js: true do
show_default_page.model_viewer_visible true
show_default_page.model_viewer_shows_a_toolbar true
show_default_page.page_shows_a_toolbar true
show_default_page.sidebar_shows_viewer_menu true
model_tree.sidebar_shows_viewer_menu true
end
end

@ -0,0 +1,91 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2020 the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2017 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See docs/COPYRIGHT.rdoc for more details.
#++
require_relative '../../spec_helper'
describe 'Create viewpoint from BCF details page', type: :feature, js: true do
let(:project) { FactoryBot.create :project, enabled_module_names: [:bim, :work_package_tracking] }
let(:user) { FactoryBot.create :admin }
let!(:work_package) { FactoryBot.create(:work_package, project: project) }
let!(:bcf) { FactoryBot.create :bcf_issue, work_package: work_package }
let!(:model) do
FactoryBot.create(:ifc_model_minimal_converted,
title: 'minimal',
project: project,
uploader: user)
end
let(:show_model_page) { Pages::IfcModels::ShowDefault.new(project) }
let(:card_view) { ::Pages::WorkPackageCards.new(project) }
let(:bcf_details) { ::Pages::BcfDetailsPage.new(work_package, project) }
let(:model_tree) { ::Components::XeokitModelTree.new }
before do
login_as(user)
end
it 'can create a viewpoint from the BCF details page' do
show_model_page.visit!
show_model_page.finished_loading
card_view.expect_work_package_listed work_package
card_view.open_full_screen_by_details work_package
# Expect no viewpoint
bcf_details.ensure_page_loaded
bcf_details.expect_viewpoint_count 0
# Uncheck the second checkbox for testing
model_tree.select_sidebar_tab 'Objects'
model_tree.expect_checked 'minimal'
model_tree.expand_tree
item, checkbox = model_tree.all_checkboxes.second
text = item.text
checkbox.uncheck
bcf_details.add_viewpoint
bcf_details.expect_viewpoint_count 1
page.driver.browser.navigate.refresh
bcf_details.ensure_page_loaded
bcf_details.expect_viewpoint_count 1
bcf_details.show_current_viewpoint
sleep 1
# Uncheck the second checkbox for testing
model_tree.select_sidebar_tab 'Objects'
model_tree.expect_checked 'minimal'
model_tree.expand_tree
model_tree.expect_unchecked text
end
end

@ -0,0 +1,32 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2020 the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2017 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See docs/COPYRIGHT.rdoc for more details.
#++
# -- load spec_helper from OpenProject core
require 'spec_helper'
Dir[File.join(File.dirname(__FILE__), 'support/**/*.rb')].each { |f| require f }

@ -0,0 +1,83 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2020 the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2017 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See docs/COPYRIGHT.rdoc for more details.
#++
module Components
class XeokitModelTree
include Capybara::DSL
include RSpec::Matchers
def initialize; end
def sidebar_shows_viewer_menu(visible)
selector = '.xeokit-tab'
tabs = ['Models', 'Objects', 'Classes', 'Storeys']
tabs.each do |tab|
element_visible? visible, selector, tab
end
end
def select_sidebar_tab(tab)
selector = '.xeokit-tab'
page.find(selector, text: tab).click
end
def expand_tree
page.all('.xeokit-tree-panel a.plus').map(&:click)
end
def expect_checked(label)
page
.find('.xeokit-tree-panel li span', text: label, wait: 10)
.sibling('input[type=checkbox]:checked')
end
def expect_unchecked(label)
page
.find('.xeokit-tree-panel li span', text: label, wait: 10)
.sibling('input[type=checkbox]:not(:checked)')
end
def all_checkboxes
page
.all('.xeokit-tree-panel li span')
.map { |item| [item, item.sibling('input[type=checkbox]')] }
end
def expect_tree_panel_selected(selected, tab = 'Models')
within (".xeokit-#{tab.downcase}.xeokit-tree-panel") do
if selected
expect(page.find('input', match: :first)).to be_checked
else
expect(page.find('input', match: :first)).not_to be_checked
end
end
end
end
end

@ -31,7 +31,7 @@ require 'support/pages/work_packages/split_work_package'
module Pages
class BcfDetailsPage < Pages::SplitWorkPackage
def expect_viewpoint_count(number)
expect(page).to have_selector('.ngx-gallery-thumbnail', count: number, wait: 10)
expect(page).to have_selector('.ngx-gallery-thumbnail', count: number, wait: 20)
end
def next_viewpoint
@ -46,6 +46,10 @@ module Pages
page.find('.icon-watched.ngx-gallery-icon-content').click
end
def add_viewpoint
page.find('a.button', text: 'Viewpoint').click
end
protected
def path(tab = 'overview')

@ -66,47 +66,6 @@ module Pages
end
end
def sidebar_shows_viewer_menu(visible)
selector = '.xeokit-tab'
tabs = ['Models', 'Objects', 'Classes', 'Storeys']
tabs.each do |tab|
element_visible? visible, selector, tab
end
end
def select_sidebar_tab(tab)
selector = '.xeokit-tab'
page.find(selector, text: tab).click
end
def expand_tree
page.all('.xeokit-tree-panel a.plus').map(&:click)
end
def expect_checked(label)
page
.find('.xeokit-tree-panel li span', text: label, wait: 10)
.sibling('input[type=checkbox]:checked')
end
def all_checkboxes
page
.all('.xeokit-tree-panel li span')
.map { |item| [item, item.sibling('input[type=checkbox]')] }
end
def expect_tree_panel_selected(selected, tab = 'Models')
within (".xeokit-#{tab.downcase}.xeokit-tree-panel") do
if selected
expect(page.find('input', match: :first)).to be_checked
else
expect(page.find('input', match: :first)).not_to be_checked
end
end
end
def page_shows_a_toolbar(visible)
toolbar_items.each do |button|
element_visible? visible, '.toolbar-item', button

Loading…
Cancel
Save