Skip to content

Commit

Permalink
placeholder for open model from file system
Browse files Browse the repository at this point in the history
  • Loading branch information
jon gadsden committed Sep 19, 2022
1 parent 8bc1571 commit a89dece
Show file tree
Hide file tree
Showing 5 changed files with 205 additions and 3 deletions.
11 changes: 8 additions & 3 deletions td.vue/src/router/local.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,20 @@ export const localRoutes = [
name: `${providerType}DiagramEdit`,
component: () => import(/* webpackChunkName: "diagram-edit" */ '../views/DiagramEdit.vue')
},
{
path: `/${providerType}/threatmodel/import`,
name: `${providerType}ThreatModelImport`,
component: () => import(/* webpackChunkName: "threatmodel-import" */ '../views/ImportModel.vue')
},
{
path: `/${providerType}/threatmodel/new`,
name: `${providerType}NewThreatModel`,
component: () => import(/* webpackChunkName: "new-threatmodel" */ '../views/NewThreatModel.vue')
},
{
path: `/${providerType}/threatmodel/import`,
name: `${providerType}ThreatModelImport`,
component: () => import(/* webpackChunkName: "threatmodel-import" */ '../views/ImportModel.vue')
path: `/${providerType}/threatmodel/open`,
name: `${providerType}ThreatModelOpen`,
component: () => import(/* webpackChunkName: "threatmodel-import" */ '../views/OpenModel.vue')
},
{
path: `/${providerType}/:threatmodel/report`,
Expand Down
5 changes: 5 additions & 0 deletions td.vue/src/service/provider/local.provider.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ import { providerTypes } from './providerTypes.js';
const providerType = providerTypes.local;

const getDashboardActions = () => ([
{
to: `/${providerType}/threatmodel/open`,
key: 'openExisting',
icon: 'file-import'
},
{
to: `/${providerType}/threatmodel/import`,
key: 'import',
Expand Down
90 changes: 90 additions & 0 deletions td.vue/src/views/OpenModel.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<template>
<div>
<b-row>
<b-col>
<b-jumbotron class="text-center">
<h4>
{{ $t('dashboard.actions.import') }}
</h4>
</b-jumbotron>
</b-col>
</b-row>
<b-row>
<b-col md=8 offset=2>
<b-form>
<b-form-row>
<b-col>
<b-form-group
id="json-input-group"
:label="$t('threatmodel.jsonPaste')"
label-for="json-input">
<b-form-textarea
id="json-input"
v-model="tmJson"
placeholder="{ ... }"
rows="16"
></b-form-textarea>
</b-form-group>
</b-col>
</b-form-row>
</b-form>
</b-col>
</b-row>
<b-row>
<b-col md=8 offset=2 class="text-right">
<b-btn-group>
<td-form-button
id="td-import-btn"
:isPrimary="true"
:onBtnClick="onImportClick"
icon="file-import"
:text="$t('forms.import')" />
</b-btn-group>
</b-col>
</b-row>
</div>
</template>

<script>
import { mapState } from 'vuex';
import { getProviderType } from '@/service/provider/providers.js';
import TdFormButton from '@/components/FormButton.vue';
import tmActions from '@/store/actions/threatmodel.js';
export default {
name: 'OpenModel',
components: {
TdFormButton
},
computed: mapState({
providerType: state => getProviderType(state.provider.selected)
}),
data() {
return {
tmJson: ''
};
},
methods: {
onImportClick() {
let jsonModel;
try {
jsonModel = JSON.parse(this.tmJson);
} catch (e) {
this.invalidJSONError();
return;
}
this.$store.dispatch(tmActions.selected, jsonModel);
const params = Object.assign({}, this.$route.params, {
threatmodel: jsonModel.summary.title
});
this.$router.push({ name: `${this.providerType}ThreatModel`, params });
},
invalidJSONError() {
this.$toast.error(this.$t('threatmodel.invalidJson'));
}
}
};
</script>
16 changes: 16 additions & 0 deletions td.vue/tests/unit/service/provider/local.provider.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,22 @@ import local from '@/service/provider/local.provider.js';
describe('service/local.provider.js', () => {
describe('getDashboardActions', () => {

describe('open existing', () => {
let action;

beforeEach(() => {
action = local.getDashboardActions().find(x=> x.key === 'openExisting');
});

it('links to the open page', () => {
expect(action.to).toEqual('/local/threatmodel/open');
});

it('uses the folder-open icon', () => {
expect(action.icon).toEqual('file-import');
});
});

describe('import', () => {
let action;

Expand Down
86 changes: 86 additions & 0 deletions td.vue/tests/unit/views/openModel.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { BootstrapVue, BJumbotron, BFormTextarea } from 'bootstrap-vue';
import { createLocalVue, shallowMount } from '@vue/test-utils';
import Vuex from 'vuex';

import ImportModel from '@/views/OpenModel.vue';
import TdFormButton from '@/components/FormButton.vue';

describe('OpenModel.vue', () => {
let wrapper, localVue, mockRouter, mockStore, toast;

beforeEach(() => {
toast = { error: jest.fn() };
localVue = createLocalVue();
localVue.use(BootstrapVue);
localVue.use(Vuex);
mockStore = new Vuex.Store({
state: {
provider: {
selected: 'local'
}
}
});
mockStore.dispatch = jest.fn();
mockRouter = { push: jest.fn() };
wrapper = shallowMount(ImportModel, {
localVue,
store: mockStore,
mocks: {
$t: key => key,
$toast: toast,
$route: { params: { }},
$router: mockRouter
}
});
});

it('shows the jumbotron text', () => {
expect(wrapper.findComponent(BJumbotron).text()).toEqual('dashboard.actions.import');
});

it('has the textarea input', () => {
expect(wrapper.findComponent(BFormTextarea).exists()).toEqual(true);
});

it('has the open button', () => {
expect(wrapper.findComponent(TdFormButton).exists()).toEqual(true);
});

describe('with valid JSON', () => {
const tm = { summary: { title: 'foo' }};
beforeEach(() => {
wrapper.setData({
tmJson: JSON.stringify(tm)
});
wrapper.vm.onImportClick();
});

it('dispatches the selected event', () => {
expect(mockStore.dispatch).toHaveBeenCalledWith('THREATMODEL_SELECTED', tm);
});

it('navigates to the threatmodel view', () => {
expect(mockRouter.push).toHaveBeenCalledWith({
name: 'localThreatModel',
params: { threatmodel: 'foo' }
});
});
});

describe('with invalid json', () => {
beforeEach(() => {
wrapper.setData({
tmJson: 'invalidJson'
});
wrapper.vm.onImportClick();
});

it('dispatches the selected event', () => {
expect(mockStore.dispatch).not.toHaveBeenCalled();
});

it('creates a toast notification', () => {
expect(toast.error).toHaveBeenCalledWith('threatmodel.invalidJson');
});
});
});

0 comments on commit a89dece

Please sign in to comment.