Merge branch 'main' into toolbar
This commit is contained in:
73 files changed
+1060
-740
No files matched your search
@@ -12,8 +12,5 @@ insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.hbs]
|
||||
insert_final_newline = false
|
||||
|
||||
[*.{diff,md}]
|
||||
trim_trailing_whitespace = false
|
||||
@@ -56,5 +56,10 @@ module.exports = {
|
||||
plugins: ['node'],
|
||||
extends: ['plugin:node/recommended'],
|
||||
},
|
||||
{
|
||||
// Test files:
|
||||
files: ['tests/**/*-test.{js,ts}'],
|
||||
extends: ['plugin:qunit/recommended'],
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -1,4 +1,3 @@
|
||||
import Ember from 'ember';
|
||||
import config from '../config/environment';
|
||||
import { authHandler, deauthHandler } from './route-handlers/auth';
|
||||
import { pickRandomStatusString } from './factories/session';
|
||||
@@ -6,6 +5,8 @@ import { Response } from 'miragejs';
|
||||
import initializeMockIPC from './scenarios/ipc';
|
||||
import makeBooleanFilter from './helpers/bexpr-filter';
|
||||
|
||||
const isTesting = config.environment === 'test';
|
||||
|
||||
export default function () {
|
||||
initializeMockIPC(this);
|
||||
|
||||
@@ -417,7 +418,7 @@ export default function () {
|
||||
// update alternate sessions to auth user.
|
||||
// But only if not in testing mode.
|
||||
// In tests, we need deterministic statuses.
|
||||
if (!Ember.testing) {
|
||||
if (!isTesting) {
|
||||
sessions.all().models.forEach((session) => {
|
||||
session.update({
|
||||
status: pickRandomStatusString(),
|
||||
@@ -446,7 +447,7 @@ export default function () {
|
||||
);
|
||||
this.get('/sessions/:id', function ({ sessions }, { params: { id } }) {
|
||||
const session = sessions.find(id);
|
||||
if (!Ember.testing) {
|
||||
if (!isTesting) {
|
||||
session.update({
|
||||
status: pickRandomStatusString(),
|
||||
});
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import Ember from 'ember';
|
||||
import config from 'ember-get-config';
|
||||
import { datatype } from 'faker';
|
||||
|
||||
const isTesting = config.environment === 'test';
|
||||
|
||||
export default function initializeMockIPC(server) {
|
||||
/**
|
||||
* We strive to make this application runnable in a regular web browser, since
|
||||
@@ -149,7 +150,7 @@ export default function initializeMockIPC(server) {
|
||||
*
|
||||
* Initializes mock IPC only in a non-Electron non-testing context.
|
||||
*/
|
||||
if (!config.isElectron && !Ember.testing) {
|
||||
if (!config.isElectron && !isTesting) {
|
||||
const mockIPC = new MockIPC();
|
||||
window.addEventListener('message', async function (event) {
|
||||
if (event.origin !== window.location.origin) return;
|
||||
|
||||
@@ -43,12 +43,11 @@
|
||||
"broccoli-asset-rev": "^3.0.0",
|
||||
"doctoc": "^2.0.1",
|
||||
"ember-auto-import": "^1.12.0",
|
||||
"ember-cli": "~3.28.0",
|
||||
"ember-cli": "~3.28.3",
|
||||
"ember-cli-dependency-checker": "^3.2.0",
|
||||
"ember-cli-inject-live-reload": "^2.1.0",
|
||||
"ember-cli-sri": "^2.1.1",
|
||||
"ember-cli-terser": "^4.0.2",
|
||||
"ember-cli-update": "^0.54.6",
|
||||
"ember-copy": "^2.0.1",
|
||||
"ember-disable-prototype-extensions": "^1.1.3",
|
||||
"ember-export-application-global": "^2.0.1",
|
||||
@@ -58,7 +57,7 @@
|
||||
"ember-page-title": "^6.2.2",
|
||||
"ember-qunit": "^5.1.4",
|
||||
"ember-resolver": "^8.0.3",
|
||||
"ember-source": "~3.24.0",
|
||||
"ember-source": "~3.28.4",
|
||||
"ember-source-channel-url": "^3.0.0",
|
||||
"ember-template-lint": "^3.7.0",
|
||||
"ember-try": "^1.4.0",
|
||||
@@ -67,6 +66,7 @@
|
||||
"eslint-plugin-ember": "^10.5.4",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"eslint-plugin-qunit": "^6.2.0",
|
||||
"loader.js": "^4.7.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"prettier": "^2.4.0",
|
||||
@@ -74,7 +74,7 @@
|
||||
"qunit-dom": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10 <=15"
|
||||
"node": ">=12 <=17"
|
||||
},
|
||||
"ember": {
|
||||
"edition": "octane"
|
||||
|
||||
@@ -47,7 +47,7 @@ module('Unit | Model | base', function (hooks) {
|
||||
assert.notEqual(model.scopeID, scope.id);
|
||||
model.scopeModel = scope;
|
||||
assert.equal(model.scopeID, scope.id);
|
||||
assert.equal(model.scope.isOrg, true);
|
||||
assert.true(model.scope.isOrg);
|
||||
});
|
||||
|
||||
test('it has a displayName attribute', function (assert) {
|
||||
@@ -78,18 +78,18 @@ module('Unit | Model | base', function (hooks) {
|
||||
},
|
||||
});
|
||||
const model = store.peekRecord('user', '1');
|
||||
assert.equal(model.canSave, false);
|
||||
assert.equal(model.cannotSave, true);
|
||||
assert.false(model.canSave);
|
||||
assert.true(model.cannotSave);
|
||||
// Should be able to save if dirty
|
||||
model.name = 'User';
|
||||
assert.equal(model.hasDirtyAttributes, true);
|
||||
assert.equal(model.canSave, true);
|
||||
assert.equal(model.cannotSave, false);
|
||||
assert.true(model.hasDirtyAttributes);
|
||||
assert.true(model.canSave);
|
||||
assert.false(model.cannotSave);
|
||||
// Should not be able to save while currently saving
|
||||
model.transitionTo('updated.inFlight');
|
||||
assert.equal(model.isSaving, true);
|
||||
assert.equal(model.canSave, false);
|
||||
assert.equal(model.cannotSave, true);
|
||||
assert.true(model.isSaving);
|
||||
assert.false(model.canSave);
|
||||
assert.true(model.cannotSave);
|
||||
model.transitionTo('loaded');
|
||||
});
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ module('Unit | Service | storage', function (hooks) {
|
||||
assert.equal(service.getItem('foo'), 'bar');
|
||||
});
|
||||
|
||||
test("it's in-memory storage is implicitly refreshed for every test case", function (assert) {
|
||||
test("it's in-memory storage is implicitly refreshed for every test case, and thus values from previous runs are not present", function (assert) {
|
||||
assert.expect(1);
|
||||
const service = this.owner.lookup('service:storage');
|
||||
assert.notOk(service.getItem('foo'));
|
||||
|
||||
@@ -12,8 +12,5 @@ insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.hbs]
|
||||
insert_final_newline = false
|
||||
|
||||
[*.{diff,md}]
|
||||
trim_trailing_whitespace = false
|
||||
@@ -56,5 +56,10 @@ module.exports = {
|
||||
plugins: ['node'],
|
||||
extends: ['plugin:node/recommended'],
|
||||
},
|
||||
{
|
||||
// Test files:
|
||||
files: ['tests/**/*-test.{js,ts}'],
|
||||
extends: ['plugin:qunit/recommended'],
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -36,12 +36,11 @@
|
||||
"core": "*",
|
||||
"doctoc": "^2.0.1",
|
||||
"ember-auto-import": "^1.12.0",
|
||||
"ember-cli": "~3.28.0",
|
||||
"ember-cli": "~3.28.3",
|
||||
"ember-cli-dependency-checker": "^3.2.0",
|
||||
"ember-cli-inject-live-reload": "^2.1.0",
|
||||
"ember-cli-sri": "^2.1.1",
|
||||
"ember-cli-terser": "^4.0.2",
|
||||
"ember-cli-update": "^0.54.6",
|
||||
"ember-cookies": "^0.5.2",
|
||||
"ember-disable-prototype-extensions": "^1.1.3",
|
||||
"ember-export-application-global": "^2.0.1",
|
||||
@@ -50,7 +49,7 @@
|
||||
"ember-page-title": "^6.2.2",
|
||||
"ember-qunit": "^5.1.4",
|
||||
"ember-resolver": "^8.0.3",
|
||||
"ember-source": "~3.24.0",
|
||||
"ember-source": "~3.28.4",
|
||||
"ember-source-channel-url": "^3.0.0",
|
||||
"ember-template-lint": "^3.7.0",
|
||||
"ember-try": "^1.4.0",
|
||||
@@ -59,6 +58,7 @@
|
||||
"eslint-plugin-ember": "^10.5.4",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"eslint-plugin-qunit": "^6.2.0",
|
||||
"loader.js": "^4.7.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"prettier": "^2.4.0",
|
||||
@@ -66,7 +66,7 @@
|
||||
"qunit-dom": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10 <=15"
|
||||
"node": ">=12 <=17"
|
||||
},
|
||||
"ember": {
|
||||
"edition": "octane"
|
||||
|
||||
@@ -12,8 +12,5 @@ insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.hbs]
|
||||
insert_final_newline = false
|
||||
|
||||
[*.{diff,md}]
|
||||
trim_trailing_whitespace = false
|
||||
@@ -56,5 +56,10 @@ module.exports = {
|
||||
plugins: ['node'],
|
||||
extends: ['plugin:node/recommended'],
|
||||
},
|
||||
{
|
||||
// Test files:
|
||||
files: ['tests/**/*-test.{js,ts}'],
|
||||
extends: ['plugin:qunit/recommended'],
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -0,0 +1,17 @@
|
||||
import { registerDeprecationHandler } from '@ember/debug';
|
||||
import config from 'ember-get-config';
|
||||
|
||||
const isTesting = config.environment === 'test';
|
||||
|
||||
export function initialize(/* application */) {
|
||||
if (isTesting) {
|
||||
// Disable all deprecations for now in tests.
|
||||
registerDeprecationHandler((/*message, options, next*/) => {
|
||||
return;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
initialize,
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export { default, initialize } from 'core/initializers/deprecations';
|
||||
@@ -50,7 +50,7 @@
|
||||
"broccoli-asset-rev": "^3.0.0",
|
||||
"doctoc": "^2.0.1",
|
||||
"ember-auto-import": "^1.12.0",
|
||||
"ember-cli": "~3.28.0",
|
||||
"ember-cli": "~3.28.3",
|
||||
"ember-cli-dependency-checker": "^3.2.0",
|
||||
"ember-cli-inject-live-reload": "^2.1.0",
|
||||
"ember-cli-sri": "^2.1.1",
|
||||
@@ -63,7 +63,7 @@
|
||||
"ember-page-title": "^6.2.2",
|
||||
"ember-qunit": "^5.1.4",
|
||||
"ember-resolver": "^8.0.3",
|
||||
"ember-source": "~3.24.0",
|
||||
"ember-source": "~3.28.4",
|
||||
"ember-source-channel-url": "^3.0.0",
|
||||
"ember-template-lint": "^3.7.0",
|
||||
"ember-try": "^1.4.0",
|
||||
@@ -72,6 +72,7 @@
|
||||
"eslint-plugin-ember": "^10.5.4",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"eslint-plugin-qunit": "^6.2.0",
|
||||
"faker": "^5.5.3",
|
||||
"loader.js": "^4.7.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
@@ -80,7 +81,7 @@
|
||||
"qunit-dom": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10 <=15"
|
||||
"node": ">=12 <=17"
|
||||
},
|
||||
"ember": {
|
||||
"edition": "octane"
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import Application from '@ember/application';
|
||||
|
||||
import config from 'dummy/config/environment';
|
||||
import { initialize } from 'dummy/initializers/deprecations';
|
||||
import { module, test } from 'qunit';
|
||||
import Resolver from 'ember-resolver';
|
||||
import { run } from '@ember/runloop';
|
||||
|
||||
module('Unit | Initializer | deprecations', function (hooks) {
|
||||
hooks.beforeEach(function () {
|
||||
this.TestApplication = class TestApplication extends Application {
|
||||
modulePrefix = config.modulePrefix;
|
||||
podModulePrefix = config.podModulePrefix;
|
||||
Resolver = Resolver;
|
||||
};
|
||||
this.TestApplication.initializer({
|
||||
name: 'initializer under test',
|
||||
initialize,
|
||||
});
|
||||
|
||||
this.application = this.TestApplication.create({ autoboot: false });
|
||||
});
|
||||
|
||||
hooks.afterEach(function () {
|
||||
run(this.application, 'destroy');
|
||||
});
|
||||
|
||||
// TODO: Replace this with your real tests.
|
||||
test('it works', async function (assert) {
|
||||
await this.application.boot();
|
||||
|
||||
assert.ok(true);
|
||||
});
|
||||
});
|
||||
@@ -12,8 +12,5 @@ insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.hbs]
|
||||
insert_final_newline = false
|
||||
|
||||
[*.{diff,md}]
|
||||
trim_trailing_whitespace = false
|
||||
@@ -58,5 +58,10 @@ module.exports = {
|
||||
plugins: ['node'],
|
||||
extends: ['plugin:node/recommended'],
|
||||
},
|
||||
{
|
||||
// Test files:
|
||||
files: ['tests/**/*-test.{js,ts}'],
|
||||
extends: ['plugin:qunit/recommended'],
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -1,20 +1,46 @@
|
||||
{{!
|
||||
Ember's LinkTo component won't accept nullish @query or @model, so we have to
|
||||
overcompensate by duplicating it four times, one for every combination.
|
||||
This is really unpleasant.
|
||||
}}
|
||||
{{#if @model}}
|
||||
<LinkTo
|
||||
...attributes
|
||||
@route={{@route}}
|
||||
@query={{@query}}
|
||||
@model={{@model}}
|
||||
class="rose-dropdown-link {{if @style (concat "rose-dropdown-link-" @style)}}"
|
||||
>
|
||||
{{yield}}
|
||||
</LinkTo>
|
||||
{{#if @query}}
|
||||
<LinkTo
|
||||
...attributes
|
||||
@route={{@route}}
|
||||
@query={{@query}}
|
||||
@model={{@model}}
|
||||
class="rose-dropdown-link {{if @style (concat "rose-dropdown-link-" @style)}}"
|
||||
>
|
||||
{{yield}}
|
||||
</LinkTo>
|
||||
{{else}}
|
||||
<LinkTo
|
||||
...attributes
|
||||
@route={{@route}}
|
||||
@model={{@model}}
|
||||
class="rose-dropdown-link {{if @style (concat "rose-dropdown-link-" @style)}}"
|
||||
>
|
||||
{{yield}}
|
||||
</LinkTo>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
<LinkTo
|
||||
...attributes
|
||||
@route={{@route}}
|
||||
@query={{@query}}
|
||||
class="rose-dropdown-link {{if @style (concat "rose-dropdown-link-" @style)}}"
|
||||
>
|
||||
{{yield}}
|
||||
</LinkTo>
|
||||
{{#if @query}}
|
||||
<LinkTo
|
||||
...attributes
|
||||
@route={{@route}}
|
||||
@query={{@query}}
|
||||
class="rose-dropdown-link {{if @style (concat "rose-dropdown-link-" @style)}}"
|
||||
>
|
||||
{{yield}}
|
||||
</LinkTo>
|
||||
{{else}}
|
||||
<LinkTo
|
||||
...attributes
|
||||
@route={{@route}}
|
||||
class="rose-dropdown-link {{if @style (concat "rose-dropdown-link-" @style)}}"
|
||||
>
|
||||
{{yield}}
|
||||
</LinkTo>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
@@ -0,0 +1,12 @@
|
||||
{{#each @items as |item|}}
|
||||
{{yield (hash
|
||||
item=item
|
||||
checkbox=(component 'rose/form/checkbox'
|
||||
name=@name
|
||||
disabled=@disabled
|
||||
inline=@inline
|
||||
checked=(includes item @selectedItems)
|
||||
onChange=(fn this.toggleItem item)
|
||||
)
|
||||
)}}
|
||||
{{/each}}
|
||||
@@ -0,0 +1,37 @@
|
||||
import Component from '@glimmer/component';
|
||||
import { tracked } from '@glimmer/tracking';
|
||||
import { action } from '@ember/object';
|
||||
|
||||
/**
|
||||
* A checkbox group represents an array of arbitrary items, which differs from
|
||||
* single checkboxes which represent boolean values. When checkboxes within a
|
||||
* checkbox are toggled, their associated item is toggled within the group's
|
||||
* array value.
|
||||
*
|
||||
* The term "item" is used to disambiguate it from "value", which has an
|
||||
* existing meaning in the context of form fields. However, items
|
||||
* are just arbitrary values.
|
||||
*/
|
||||
export default class RoseFormCheckboxGroupComponent extends Component {
|
||||
// =actions
|
||||
|
||||
/**
|
||||
* Returns a new copy of the @selectedItems array where the given item is:
|
||||
* - removed from the array, if it was already present
|
||||
* - or added to the array, if it was not already present
|
||||
*/
|
||||
@action
|
||||
toggleItem(item) {
|
||||
const selectedItems = this.args.selectedItems || [];
|
||||
const currentItems = [...selectedItems];
|
||||
|
||||
if (currentItems.includes(item)) {
|
||||
const i = currentItems.indexOf(item);
|
||||
currentItems.splice(i, 1);
|
||||
} else {
|
||||
currentItems.push(item);
|
||||
}
|
||||
|
||||
if (this.args.onChange) this.args.onChange(currentItems);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
import { Meta, Story, Preview } from '@storybook/addon-docs/blocks';
|
||||
import { hbs } from 'ember-cli-htmlbars';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import { text, boolean, select, object } from '@storybook/addon-knobs';
|
||||
|
||||
<Meta title="Rose|Form/Checkbox/Group" component="Form/Checkbox/Group" />
|
||||
|
||||
# Form checkboxfield group
|
||||
|
||||
Renders a form checkboxfield group.
|
||||
|
||||
```htmlbars
|
||||
<Rose::Form::Checkbox::Group
|
||||
@name='checkbox-group'
|
||||
@items={{this.items}}
|
||||
@selectedItems={{this.selectedItems}}
|
||||
@onChange={{fn this.onChange}}
|
||||
as |group|
|
||||
>
|
||||
<group.checkbox
|
||||
@label={{group.item.name}}
|
||||
value={{group.item.id}} />
|
||||
</Rose::Form::Checkbox::Group>
|
||||
```
|
||||
<Preview>
|
||||
<Story name="Basic" height="10rem">{{
|
||||
template: hbs`
|
||||
<Rose::Form::Checkbox::Group
|
||||
@name={{name}}
|
||||
@inline={{inline}}
|
||||
@disabled={{disabled}}
|
||||
@items={{items}}
|
||||
@selectedItems={{selectedItems}}
|
||||
@onChange={{onChange}}
|
||||
as |group|
|
||||
>
|
||||
<group.checkbox
|
||||
@label={{group.item.name}}
|
||||
value={{group.item.id}} />
|
||||
</Rose::Form::Checkbox::Group>
|
||||
`,
|
||||
context: {
|
||||
inline: boolean('inline', true),
|
||||
disabled: boolean('disabled', false),
|
||||
items: object('items', [
|
||||
{ id: 1, name: 'Foo' },
|
||||
{ id: 2, name: 'Bar' },
|
||||
{ id: 3, name: 'Baz' },
|
||||
]),
|
||||
selectedItems: object('selectedItems', []),
|
||||
onChange: action('changed'),
|
||||
}
|
||||
}}</Story>
|
||||
</Preview>
|
||||
@@ -6,6 +6,7 @@
|
||||
id={{this.id}}
|
||||
name={{@name}}
|
||||
disabled={{@disabled}}
|
||||
onChange={{@onChange}}
|
||||
@type="checkbox"
|
||||
@checked={{if @checked true false}}
|
||||
aria-describedby="{{if @helperText (concat 'helper-text-' this.id)}} {{if @error (concat 'errors-' this.id)}}" />
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from 'rose/components/rose/form/checkbox/group';
|
||||
@@ -38,6 +38,7 @@
|
||||
"emberx-select": "github:adopted-ember-addons/emberx-select#bc5f774"
|
||||
},
|
||||
"devDependencies": {
|
||||
"ember-get-config": "^0.3.0",
|
||||
"@babel/core": "^7.15.5",
|
||||
"@ember/optional-features": "^2.0.0",
|
||||
"@ember/test-helpers": "^2.4.2",
|
||||
@@ -50,6 +51,7 @@
|
||||
"@storybook/addons": "^6.3.9",
|
||||
"@storybook/api": "^6.3.12",
|
||||
"@storybook/cli": "^6.3.10",
|
||||
"@storybook/components": "^6.3.12",
|
||||
"@storybook/ember": "^6.3.8",
|
||||
"@storybook/ember-cli-storybook": "^0.4.0",
|
||||
"babel-eslint": "^10.1.0",
|
||||
@@ -57,13 +59,13 @@
|
||||
"broccoli-asset-rev": "^3.0.0",
|
||||
"doctoc": "^2.0.1",
|
||||
"ember-auto-import": "^1.12.0",
|
||||
"ember-cli": "~3.28.0",
|
||||
"ember-cli": "~3.28.3",
|
||||
"ember-cli-dependency-checker": "^3.2.0",
|
||||
"ember-cli-inject-live-reload": "^2.1.0",
|
||||
"ember-cli-sass": "^10.0.1",
|
||||
"ember-cli-sri": "^2.1.1",
|
||||
"ember-cli-terser": "^4.0.2",
|
||||
"ember-cli-update": "^0.54.6",
|
||||
"ember-composable-helpers": "^4.5.0",
|
||||
"ember-disable-prototype-extensions": "^1.1.3",
|
||||
"ember-export-application-global": "^2.0.1",
|
||||
"ember-inline-svg": "^1.0.0",
|
||||
@@ -73,7 +75,7 @@
|
||||
"ember-page-title": "^6.2.2",
|
||||
"ember-qunit": "^5.1.4",
|
||||
"ember-resolver": "^8.0.3",
|
||||
"ember-source": "~3.24.0",
|
||||
"ember-source": "~3.28.4",
|
||||
"ember-source-channel-url": "^3.0.0",
|
||||
"ember-template-lint": "^3.7.0",
|
||||
"ember-try": "^1.4.0",
|
||||
@@ -82,6 +84,7 @@
|
||||
"eslint-plugin-ember": "^10.5.4",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"eslint-plugin-qunit": "^6.2.0",
|
||||
"loader.js": "^4.7.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"prettier": "^2.4.0",
|
||||
@@ -90,10 +93,11 @@
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"sass": "^1.41.0",
|
||||
"sass-lint": "^1.13.1"
|
||||
"sass-lint": "^1.13.1",
|
||||
"webpack": "^5.59.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10 <=15"
|
||||
"node": ">=12 <=17"
|
||||
},
|
||||
"ember": {
|
||||
"edition": "octane"
|
||||
|
||||
@@ -1,12 +1,28 @@
|
||||
import Controller from '@ember/controller';
|
||||
import { tracked } from '@glimmer/tracking';
|
||||
import { action } from '@ember/object';
|
||||
|
||||
const possibleItems = [
|
||||
{ id: 1, name: 'foo' },
|
||||
{ id: 2, name: 'bar' },
|
||||
{ id: 3, name: 'baz' },
|
||||
];
|
||||
|
||||
export default class IndexController extends Controller {
|
||||
color = 'green';
|
||||
// =attributes
|
||||
|
||||
@tracked items = [...possibleItems];
|
||||
@tracked selectedItems = [possibleItems[2]];
|
||||
|
||||
// =actions
|
||||
|
||||
@action
|
||||
actionHandler(/*value*/) {
|
||||
// eslint-disable-next-line no-console
|
||||
//console.log('action handled');
|
||||
checkboxGroupChanged(selected) {
|
||||
this.selectedItems = [...selected];
|
||||
}
|
||||
|
||||
@action
|
||||
clearSelected() {
|
||||
this.selectedItems = [];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { registerDeprecationHandler } from '@ember/debug';
|
||||
import config from 'ember-get-config';
|
||||
|
||||
const isTesting = config.environment === 'test';
|
||||
|
||||
export function initialize(/* application */) {
|
||||
if (isTesting) {
|
||||
// Disable all deprecations for now in tests.
|
||||
registerDeprecationHandler((/*message, options, next*/) => {
|
||||
return;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
initialize,
|
||||
};
|
||||
@@ -1,3 +1,28 @@
|
||||
<h2>Checkbox Group</h2>
|
||||
<Rose::Form::Checkbox::Group
|
||||
@items={{this.items}}
|
||||
@selectedItems={{this.selectedItems}}
|
||||
@onChange={{this.checkboxGroupChanged}}
|
||||
as |group|
|
||||
>
|
||||
<group.checkbox
|
||||
@label={{group.item.name}}
|
||||
value={{group.item.id}} />
|
||||
</Rose::Form::Checkbox::Group>
|
||||
|
||||
<p>
|
||||
Items selected:
|
||||
{{#each this.selectedItems as |selected|}}
|
||||
{{selected.id}},
|
||||
{{/each}}
|
||||
</p>
|
||||
|
||||
<Rose::Button @style='primary' {{on 'click' this.clearSelected}}>
|
||||
Clear Selected Items
|
||||
</Rose::Button>
|
||||
|
||||
<Rose::Separator />
|
||||
|
||||
<h2>KeyValue Dropdown</h2>
|
||||
<Rose::Dropdown
|
||||
@text="Credential library details"
|
||||
|
||||
@@ -22,7 +22,8 @@ module('Integration | Component | rose/badge', function (hooks) {
|
||||
});
|
||||
|
||||
test('it styles content using @style', async function (assert) {
|
||||
let styles = [
|
||||
assert.expect(14);
|
||||
const styles = [
|
||||
'outline',
|
||||
'dark',
|
||||
'informational',
|
||||
|
||||
@@ -23,7 +23,7 @@ module('Integration | Component | rose/button', function (hooks) {
|
||||
|
||||
test('it is disabled when @disabled={{true}}', async function (assert) {
|
||||
await render(hbs`<Rose::Button @disabled={{true}} />`);
|
||||
assert.equal(find('button').disabled, true);
|
||||
assert.true(find('button').disabled);
|
||||
});
|
||||
|
||||
test('it adds a style class', async function (assert) {
|
||||
|
||||
@@ -23,7 +23,7 @@ module('Integration | Component | rose/dropdown/button', function (hooks) {
|
||||
|
||||
test('it is disabled when @disabled={{true}}', async function (assert) {
|
||||
await render(hbs`<Rose::Dropdown::Button @disabled={{true}} />`);
|
||||
assert.equal(find('button').disabled, true);
|
||||
assert.true(find('button').disabled);
|
||||
});
|
||||
|
||||
test('it adds a style class', async function (assert) {
|
||||
|
||||
@@ -60,17 +60,17 @@ module('Integration | Component | rose/form/checkbox', function (hooks) {
|
||||
|
||||
test('it is not checked by default', async function (assert) {
|
||||
await render(hbs`<Rose::Form::Checkbox />`);
|
||||
assert.equal(find('input').checked, false);
|
||||
assert.false(find('input').checked);
|
||||
});
|
||||
|
||||
test('it is not disabled by default', async function (assert) {
|
||||
await render(hbs`<Rose::Form::Checkbox />`);
|
||||
assert.equal(find('input').disabled, false);
|
||||
assert.false(find('input').disabled);
|
||||
});
|
||||
|
||||
test('it is checked when @checked={{true}}', async function (assert) {
|
||||
await render(hbs`<Rose::Form::Checkbox @checked={{true}} />`);
|
||||
assert.equal(find('input').checked, true);
|
||||
assert.true(find('input').checked);
|
||||
});
|
||||
|
||||
test('it marks error when @error={{true}}', async function (assert) {
|
||||
@@ -80,6 +80,6 @@ module('Integration | Component | rose/form/checkbox', function (hooks) {
|
||||
|
||||
test('it is disabled when @disabled={{true}}', async function (assert) {
|
||||
await render(hbs`<Rose::Form::Checkbox @disabled={{true}} />`);
|
||||
assert.equal(find('input').disabled, true);
|
||||
assert.true(find('input').disabled);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,100 @@
|
||||
import { module, test } from 'qunit';
|
||||
import { setupRenderingTest } from 'ember-qunit';
|
||||
import { render, findAll, click } from '@ember/test-helpers';
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
|
||||
module('Integration | Component | rose/form/checkbox/group', function (hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
let items;
|
||||
let selectedItems;
|
||||
|
||||
hooks.beforeEach(function () {
|
||||
items = [
|
||||
{ id: 1, name: 'Foo' },
|
||||
{ id: 2, name: 'Bar' },
|
||||
{ id: 3, name: 'Baz' },
|
||||
];
|
||||
selectedItems = [items[2]];
|
||||
});
|
||||
|
||||
test('it renders checkboxes equal in length to an array of items', async function (assert) {
|
||||
assert.expect(1);
|
||||
this.items = items;
|
||||
await render(hbs`
|
||||
<Rose::Form::Checkbox::Group
|
||||
@items={{this.items}}
|
||||
as |group|
|
||||
>
|
||||
<group.checkbox
|
||||
@label={{group.item.name}}
|
||||
value={{group.item.id}} />
|
||||
</Rose::Form::Checkbox::Group>
|
||||
`);
|
||||
assert.equal(findAll('input').length, 3);
|
||||
});
|
||||
|
||||
test('it checks checkboxes for items present in a selectedItems array', async function (assert) {
|
||||
assert.expect(1);
|
||||
this.items = items;
|
||||
this.selectedItems = selectedItems;
|
||||
await render(hbs`
|
||||
<Rose::Form::Checkbox::Group
|
||||
@items={{this.items}}
|
||||
@selectedItems={{this.selectedItems}}
|
||||
as |group|
|
||||
>
|
||||
<group.checkbox
|
||||
@label={{group.item.name}}
|
||||
value={{group.item.id}} />
|
||||
</Rose::Form::Checkbox::Group>
|
||||
`);
|
||||
assert.equal(findAll(':checked').length, 1);
|
||||
});
|
||||
|
||||
test('it fires onChange when items are checked, passing an array of selected items', async function (assert) {
|
||||
assert.expect(2);
|
||||
this.items = items;
|
||||
this.selectedItems = selectedItems;
|
||||
this.onChange = (newlySelectedItems) => {
|
||||
assert.equal(selectedItems.length, 1);
|
||||
assert.equal(newlySelectedItems.length, 2);
|
||||
};
|
||||
await render(hbs`
|
||||
<Rose::Form::Checkbox::Group
|
||||
@items={{this.items}}
|
||||
@selectedItems={{this.selectedItems}}
|
||||
@onChange={{this.onChange}}
|
||||
as |group|
|
||||
>
|
||||
<group.checkbox
|
||||
@label={{group.item.name}}
|
||||
value={{group.item.id}} />
|
||||
</Rose::Form::Checkbox::Group>
|
||||
`);
|
||||
await click('.rose-form-checkbox:first-child input');
|
||||
});
|
||||
|
||||
test('it fires onChange when items are unchecked, passing an array of selected items', async function (assert) {
|
||||
assert.expect(2);
|
||||
this.items = items;
|
||||
this.selectedItems = selectedItems;
|
||||
this.onChange = (newlySelectedItems) => {
|
||||
assert.equal(selectedItems.length, 1);
|
||||
assert.equal(newlySelectedItems.length, 0);
|
||||
};
|
||||
await render(hbs`
|
||||
<Rose::Form::Checkbox::Group
|
||||
@items={{this.items}}
|
||||
@selectedItems={{this.selectedItems}}
|
||||
@onChange={{this.onChange}}
|
||||
as |group|
|
||||
>
|
||||
<group.checkbox
|
||||
@label={{group.item.name}}
|
||||
value={{group.item.id}} />
|
||||
</Rose::Form::Checkbox::Group>
|
||||
`);
|
||||
await click('.rose-form-checkbox:last-child input');
|
||||
});
|
||||
});
|
||||
@@ -43,13 +43,13 @@ module('Integration | Component | rose/form/radio/group', function (hooks) {
|
||||
</Rose::Form::Radio::Group>
|
||||
`);
|
||||
|
||||
assert.equal(findAll('[type="radio"]')[0].checked, false);
|
||||
assert.equal(findAll('[type="radio"]')[1].checked, true);
|
||||
assert.false(findAll('[type="radio"]')[0].checked);
|
||||
assert.true(findAll('[type="radio"]')[1].checked);
|
||||
|
||||
await click(findAll('[type="radio"]')[0]);
|
||||
|
||||
assert.equal(findAll('[type="radio"]')[0].checked, true);
|
||||
assert.equal(findAll('[type="radio"]')[1].checked, false);
|
||||
assert.true(findAll('[type="radio"]')[0].checked);
|
||||
assert.false(findAll('[type="radio"]')[1].checked);
|
||||
});
|
||||
|
||||
test('it reflects active radiofield value in @selectedValue and triggers a @changed function', async function (assert) {
|
||||
@@ -100,19 +100,19 @@ module('Integration | Component | rose/form/radio/group', function (hooks) {
|
||||
</Rose::Form::Radio::Group>
|
||||
`);
|
||||
|
||||
assert.equal(findAll('[type="radio"]')[0].checked, false);
|
||||
assert.equal(findAll('[type="radio"]')[1].checked, false);
|
||||
assert.false(findAll('[type="radio"]')[0].checked);
|
||||
assert.false(findAll('[type="radio"]')[1].checked);
|
||||
|
||||
this.set('selectedValue', 'flamingo');
|
||||
assert.equal(findAll('[type="radio"]')[0].checked, false);
|
||||
assert.equal(findAll('[type="radio"]')[1].checked, true);
|
||||
assert.false(findAll('[type="radio"]')[0].checked);
|
||||
assert.true(findAll('[type="radio"]')[1].checked);
|
||||
|
||||
this.set('selectedValue', 'pegion');
|
||||
assert.equal(findAll('[type="radio"]')[0].checked, true);
|
||||
assert.equal(findAll('[type="radio"]')[1].checked, false);
|
||||
assert.true(findAll('[type="radio"]')[0].checked);
|
||||
assert.false(findAll('[type="radio"]')[1].checked);
|
||||
|
||||
this.set('selectedValue', 'dog');
|
||||
assert.equal(findAll('[type="radio"]')[0].checked, false);
|
||||
assert.equal(findAll('[type="radio"]')[1].checked, false);
|
||||
assert.false(findAll('[type="radio"]')[0].checked);
|
||||
assert.false(findAll('[type="radio"]')[1].checked);
|
||||
});
|
||||
});
|
||||
@@ -28,25 +28,25 @@ module('Integration | Component | rose/form/radio/radio', function (hooks) {
|
||||
await render(
|
||||
hbs`<Rose::Form::Radio::Radio @value="tree" @selectedValue="tree"/>`
|
||||
);
|
||||
assert.equal(await find('input').checked, true);
|
||||
assert.true(await find('input').checked);
|
||||
});
|
||||
|
||||
test('it is not checked when @value and @selectedValue values are different', async function (assert) {
|
||||
await render(hbs`<Rose::Form::Radio::Radio @value="tree"/>`);
|
||||
assert.equal(await find('input').checked, false);
|
||||
assert.false(await find('input').checked);
|
||||
|
||||
await render(hbs`<Rose::Form::Radio::Radio @selectedValue="tree"/>`);
|
||||
assert.equal(await find('input').checked, false);
|
||||
assert.false(await find('input').checked);
|
||||
|
||||
await render(
|
||||
hbs`<Rose::Form::Radio::Radio @value="root" @selectedValue="tree"/>`
|
||||
);
|
||||
assert.equal(await find('input').checked, false);
|
||||
assert.false(await find('input').checked);
|
||||
});
|
||||
|
||||
test('it is not disabled by default', async function (assert) {
|
||||
await render(hbs`<Rose::Form::Radio::Radio />`);
|
||||
assert.equal(await find('input').disabled, false);
|
||||
assert.false(await find('input').disabled);
|
||||
});
|
||||
|
||||
test('it is not in error state by default', async function (assert) {
|
||||
@@ -56,7 +56,7 @@ module('Integration | Component | rose/form/radio/radio', function (hooks) {
|
||||
|
||||
test('it is disabled when @disabled={{true}}', async function (assert) {
|
||||
await render(hbs`<Rose::Form::Radio::Radio @disabled={{true}}/>`);
|
||||
assert.equal(await find('input').disabled, true);
|
||||
assert.true(await find('input').disabled);
|
||||
});
|
||||
|
||||
test('it is in error state when @error={{true}}', async function (assert) {
|
||||
|
||||
@@ -7,6 +7,7 @@ module('Integration | Modifier | on-click-outside', function (hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
test('it fires event when an outside element is clicked', async function (assert) {
|
||||
assert.expect(2);
|
||||
this.set('clickedOutside', (element, event) => {
|
||||
assert.ok(element);
|
||||
assert.equal(event.target.id, 'outside');
|
||||
|
||||
+1
-1
@@ -89,6 +89,6 @@
|
||||
}
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10 <=15"
|
||||
"node": ">=12 <=17"
|
||||
}
|
||||
}
|
||||
@@ -12,8 +12,5 @@ insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.hbs]
|
||||
insert_final_newline = false
|
||||
|
||||
[*.{diff,md}]
|
||||
trim_trailing_whitespace = false
|
||||
@@ -55,5 +55,10 @@ module.exports = {
|
||||
'node/no-unpublished-require': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
// Test files:
|
||||
files: ['tests/**/*-test.{js,ts}'],
|
||||
extends: ['plugin:qunit/recommended'],
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -81,7 +81,7 @@
|
||||
@label={{t 'form.disable_discovered_config_validation.label'}}
|
||||
@helperText={{t 'form.disable_discovered_config_validation.help'}}
|
||||
@checked={{@model.attributes.disable_discovered_config_validation}}
|
||||
onChange={{fn
|
||||
@onChange={{fn
|
||||
(mut @model.attributes.disable_discovered_config_validation)
|
||||
(if @model.attributes.disable_discovered_config_validation false true)
|
||||
}}
|
||||
|
||||
@@ -145,7 +145,7 @@
|
||||
@label={{t 'resources.credential-store.form.tls_skip_verify.label'}}
|
||||
@helperText={{t 'resources.credential-store.form.tls_skip_verify.help'}}
|
||||
@checked={{@model.attributes.tls_skip_verify}}
|
||||
onChange={{fn
|
||||
@onChange={{fn
|
||||
(mut @model.attributes.tls_skip_verify)
|
||||
(if @model.attributes.tls_skip_verify false true)
|
||||
}}
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
<row.headerCell>
|
||||
<form.checkbox
|
||||
@label={{user.displayName}}
|
||||
onChange={{fn this.toggleMember user}}
|
||||
@onChange={{fn this.toggleMember user}}
|
||||
/>
|
||||
{{#if user.accountName}}
|
||||
{{!
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
<form.checkbox
|
||||
@label={{host.id}}
|
||||
@description={{host.description}}
|
||||
onChange={{fn this.toggleHost host}}
|
||||
@onChange={{fn this.toggleHost host}}
|
||||
/>
|
||||
</row.cell>
|
||||
<row.cell>{{host.name}}</row.cell>
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
<row.headerCell>
|
||||
<form.checkbox
|
||||
@label={{principal.displayName}}
|
||||
onChange={{fn this.togglePrincipal principal}}
|
||||
@onChange={{fn this.togglePrincipal principal}}
|
||||
/>
|
||||
{{#if principal.accountName}}
|
||||
{{!
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
<form.checkbox
|
||||
@label={{credentialLibrary.id}}
|
||||
@description={{credentialLibrary.description}}
|
||||
onChange={{fn this.toggleCredentialLibrary credentialLibrary}}
|
||||
@onChange={{fn this.toggleCredentialLibrary credentialLibrary}}
|
||||
/>
|
||||
</row.headerCell>
|
||||
<row.cell>{{credentialLibrary.name}}</row.cell>
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<form.checkbox
|
||||
@label={{hostSet.id}}
|
||||
@description={{hostSet.description}}
|
||||
onChange={{fn this.toggleHostSet hostSet}}
|
||||
@onChange={{fn this.toggleHostSet hostSet}}
|
||||
/>
|
||||
</row.cell>
|
||||
<row.cell>{{hostSet.name}}</row.cell>
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<form.checkbox
|
||||
@label={{account.id}}
|
||||
@description={{account.description}}
|
||||
onChange={{fn this.toggleAccount account}}
|
||||
@onChange={{fn this.toggleAccount account}}
|
||||
/>
|
||||
</row.cell>
|
||||
<row.cell>{{account.accountName}}</row.cell>
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
"ember-a11y-testing": "^4.2.0",
|
||||
"ember-auto-import": "^1.12.0",
|
||||
"ember-breadcrumbs": "^0.2.3",
|
||||
"ember-cli": "~3.28.0",
|
||||
"ember-cli": "~3.28.3",
|
||||
"ember-cli-app-version": "^5.0.0",
|
||||
"ember-cli-babel": "^7.26.6",
|
||||
"ember-cli-code-coverage": "^1.0.3",
|
||||
@@ -63,7 +63,6 @@
|
||||
"ember-cli-sri": "^2.1.1",
|
||||
"ember-cli-template-lint": "^2.0.2",
|
||||
"ember-cli-terser": "^4.0.2",
|
||||
"ember-cli-update": "^0.54.6",
|
||||
"ember-concurrency": "^1.3.0",
|
||||
"ember-exam": "^6.1.0",
|
||||
"ember-export-application-global": "^2.0.1",
|
||||
@@ -75,7 +74,7 @@
|
||||
"ember-page-title": "^6.2.2",
|
||||
"ember-qunit": "^5.1.4",
|
||||
"ember-resolver": "^8.0.3",
|
||||
"ember-source": "~3.24.0",
|
||||
"ember-source": "~3.28.4",
|
||||
"ember-template-lint": "^3.7.0",
|
||||
"ember-template-lint-plugin-prettier": "^2.0.0",
|
||||
"eslint": "^7.32.0",
|
||||
@@ -83,6 +82,7 @@
|
||||
"eslint-plugin-ember": "^10.5.4",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"eslint-plugin-qunit": "^6.2.0",
|
||||
"faker": "^5.5.3",
|
||||
"loader.js": "^4.7.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
@@ -95,7 +95,7 @@
|
||||
"sinon": "^11.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10 <=15"
|
||||
"node": ">=12 <=17"
|
||||
},
|
||||
"ember": {
|
||||
"edition": "octane"
|
||||
|
||||
@@ -150,12 +150,12 @@ module('Acceptance | accounts | create', function (hooks) {
|
||||
await fillIn('[name="name"]', 'new account');
|
||||
await click('form [type="submit"]');
|
||||
await a11yAudit();
|
||||
assert.ok(
|
||||
find('[role="alert"]').textContent.trim(),
|
||||
assert.equal(
|
||||
find('.rose-notification-body').textContent.trim(),
|
||||
'The request was invalid.',
|
||||
'Displays primary error message.'
|
||||
);
|
||||
assert.ok(
|
||||
assert.equal(
|
||||
find('.rose-form-error-message').textContent.trim(),
|
||||
'Name is required.',
|
||||
'Displays field-level errors.'
|
||||
|
||||
@@ -93,8 +93,8 @@ module('Acceptance | accounts | delete', function (hooks) {
|
||||
await visit(urls.account);
|
||||
await click('.rose-layout-page-actions .rose-dropdown-button-danger');
|
||||
await a11yAudit();
|
||||
assert.ok(
|
||||
find('[role="alert"]').textContent.trim(),
|
||||
assert.equal(
|
||||
find('.rose-notification-body').textContent.trim(),
|
||||
'Oops.',
|
||||
'Displays primary error message.'
|
||||
);
|
||||
|
||||
@@ -100,13 +100,13 @@ module('Acceptance | accounts | set password', function (hooks) {
|
||||
// NOTE: since set password is a tabbed route with easy navigation away
|
||||
// from the form, and the form does not directly operate on a model instance,
|
||||
// a "cancel" flow doesn't make much sense. Disabling for now.
|
||||
// test('can cancel setting new password', async function (assert) {
|
||||
// assert.expect(1);
|
||||
// await visit(urls.setPassword);
|
||||
// await fillIn('[name="password"]', 'update password');
|
||||
// await click('form button:not([type="submit"])');
|
||||
// assert.notOk(find('[name="password"]').textContent.trim());
|
||||
// });
|
||||
test.skip('can cancel setting new password', async function (assert) {
|
||||
assert.expect(1);
|
||||
await visit(urls.setPassword);
|
||||
await fillIn('[name="password"]', 'update password');
|
||||
await click('form button:not([type="submit"])');
|
||||
assert.notOk(find('[name="password"]').textContent.trim());
|
||||
});
|
||||
|
||||
test('errors are displayed when setting password fails', async function (assert) {
|
||||
assert.expect(1);
|
||||
|
||||
@@ -103,8 +103,8 @@ module('Acceptance | accounts | update', function (hooks) {
|
||||
await fillIn('[name="name"]', 'save account');
|
||||
await click('form [type="submit"]');
|
||||
await a11yAudit();
|
||||
assert.ok(
|
||||
find('[role="alert"]').textContent.trim(),
|
||||
assert.equal(
|
||||
find('.rose-notification-body').textContent.trim(),
|
||||
'Oops.',
|
||||
'Displays primary error message.'
|
||||
);
|
||||
@@ -136,12 +136,12 @@ module('Acceptance | accounts | update', function (hooks) {
|
||||
await fillIn('[name="name"]', 'existing account');
|
||||
await click('form [type="submit"]');
|
||||
await a11yAudit();
|
||||
assert.ok(
|
||||
find('[role="alert"]').textContent.trim(),
|
||||
assert.equal(
|
||||
find('.rose-notification-body').textContent.trim(),
|
||||
'The request was invalid.',
|
||||
'Displays primary error message.'
|
||||
);
|
||||
assert.ok(
|
||||
assert.equal(
|
||||
find('.rose-form-error-message').textContent.trim(),
|
||||
'Name is required.',
|
||||
'Displays field-level errors.'
|
||||
|
||||
@@ -72,8 +72,8 @@ module('Acceptance | auth methods | delete', function (hooks) {
|
||||
await visit(urls.authMethod);
|
||||
await click('.rose-layout-page-actions .rose-dropdown-button-danger');
|
||||
await a11yAudit();
|
||||
assert.ok(
|
||||
find('[role="alert"]').textContent.trim(),
|
||||
assert.equal(
|
||||
find('.rose-notification-body').textContent.trim(),
|
||||
'Oops.',
|
||||
'Displays primary error message.'
|
||||
);
|
||||
|
||||
@@ -102,38 +102,38 @@ module('Acceptance | auth methods | oidc', function (hooks) {
|
||||
});
|
||||
|
||||
// FIXME: How to mock just one request routed to /auth-methods and let everything else passthrough?
|
||||
// test('errors are displayed when state update fails', async function (assert) {
|
||||
// assert.expect(2);
|
||||
// this.server.post('/auth-methods/:idMethod', (_, request) => {
|
||||
// // Only respond to state update with error
|
||||
// if (request.params.idMethod.match(/(change-state)/i)) {
|
||||
// return new Response(
|
||||
// 400,
|
||||
// {},
|
||||
// {
|
||||
// status: 400,
|
||||
// code: 'error',
|
||||
// message: 'Sorry!',
|
||||
// }
|
||||
// );
|
||||
// }
|
||||
// return request;
|
||||
// });
|
||||
// const newState = 'inactive';
|
||||
// await visit(urls.authMethod);
|
||||
// await click('.rose-layout-page-actions .rose-dropdown-trigger');
|
||||
// await click(`.rose-dropdown[open] input[value="${newState}"]`);
|
||||
// // debugger;
|
||||
// const authMethod = this.server.db.authMethods.find(instances.authMethod.id);
|
||||
// assert.notEqual(
|
||||
// newState,
|
||||
// authMethod.attributes.state,
|
||||
// 'Auth method state is not be updated.'
|
||||
// );
|
||||
// assert.ok(
|
||||
// find('[role="alert"]').textContent.trim(),
|
||||
// 'Sorry!',
|
||||
// 'Displays error message.'
|
||||
// );
|
||||
// });
|
||||
test.skip('errors are displayed when state update fails', async function (assert) {
|
||||
assert.expect(2);
|
||||
this.server.post('/auth-methods/:idMethod', (_, request) => {
|
||||
// Only respond to state update with error
|
||||
if (request.params.idMethod.match(/(change-state)/i)) {
|
||||
return new Response(
|
||||
400,
|
||||
{},
|
||||
{
|
||||
status: 400,
|
||||
code: 'error',
|
||||
message: 'Sorry!',
|
||||
}
|
||||
);
|
||||
}
|
||||
return request;
|
||||
});
|
||||
const newState = 'inactive';
|
||||
await visit(urls.authMethod);
|
||||
await click('.rose-layout-page-actions .rose-dropdown-trigger');
|
||||
await click(`.rose-dropdown[open] input[value="${newState}"]`);
|
||||
// debugger;
|
||||
const authMethod = this.server.db.authMethods.find(instances.authMethod.id);
|
||||
assert.notEqual(
|
||||
newState,
|
||||
authMethod.attributes.state,
|
||||
'Auth method state is not be updated.'
|
||||
);
|
||||
assert.ok(
|
||||
find('.rose-notification-body').textContent.trim(),
|
||||
'Sorry!',
|
||||
'Displays error message.'
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -102,50 +102,12 @@ module('Acceptance | auth methods | update', function (hooks) {
|
||||
await fillIn('[name="name"]', 'existing auth method');
|
||||
await click('form [type="submit"]');
|
||||
await a11yAudit();
|
||||
assert.ok(
|
||||
find('[role="alert"]').textContent.trim(),
|
||||
assert.equal(
|
||||
find('.rose-notification-body').textContent.trim(),
|
||||
'The request was invalid.',
|
||||
'Displays primary error message.'
|
||||
);
|
||||
assert.ok(
|
||||
find('.rose-form-error-message').textContent.trim(),
|
||||
'Name is required.',
|
||||
'Displays field-level errors.'
|
||||
);
|
||||
});
|
||||
|
||||
test('saving an existing auth method with invalid fields displays error messages', async function (assert) {
|
||||
assert.expect(2);
|
||||
this.server.patch('/auth-methods/:id', () => {
|
||||
return new Response(
|
||||
400,
|
||||
{},
|
||||
{
|
||||
status: 400,
|
||||
code: 'invalid_argument',
|
||||
message: 'The request was invalid.',
|
||||
details: {
|
||||
request_fields: [
|
||||
{
|
||||
name: 'name',
|
||||
description: 'Name is required.',
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
);
|
||||
});
|
||||
await visit(urls.authMethod);
|
||||
await click('form [type="button"]', 'Activate edit mode');
|
||||
await fillIn('[name="name"]', 'existing auth method');
|
||||
await click('form [type="submit"]');
|
||||
await a11yAudit();
|
||||
assert.ok(
|
||||
find('[role="alert"]').textContent.trim(),
|
||||
'The request was invalid.',
|
||||
'Displays primary error message.'
|
||||
);
|
||||
assert.ok(
|
||||
assert.equal(
|
||||
find('.rose-form-error-message').textContent.trim(),
|
||||
'Name is required.',
|
||||
'Displays field-level errors.'
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
fillIn,
|
||||
click,
|
||||
find,
|
||||
//findAll,
|
||||
findAll,
|
||||
getRootElement,
|
||||
//setupOnerror,
|
||||
} from '@ember/test-helpers';
|
||||
@@ -300,23 +300,23 @@ module('Acceptance | authentication', function (hooks) {
|
||||
// This test is disabled because it is no longer relevant. On deauth,
|
||||
// the page is reloaded. If the user was viewing a route requiring
|
||||
// authentication, they will be redirected accordingly.
|
||||
// test('deauthentication redirects to first global authenticate method', async function (assert) {
|
||||
// assert.expect(3);
|
||||
// await visit(authMethodAuthenticateURL);
|
||||
// await fillIn('[name="identification"]', 'test');
|
||||
// await fillIn('[name="password"]', 'test');
|
||||
// await click('[type="submit"]');
|
||||
// assert.ok(currentSession().isAuthenticated);
|
||||
// // Open header utilities dropdown
|
||||
// await click('.rose-header-utilities .rose-dropdown summary');
|
||||
// // Find and click on last element in dropdown - should be deauthenticate button
|
||||
// const menu = findAll(
|
||||
// '.rose-header-utilities .rose-dropdown .rose-dropdown-content button'
|
||||
// );
|
||||
// await click(menu[menu.length - 1]);
|
||||
// assert.notOk(currentSession().isAuthenticated);
|
||||
// assert.equal(currentURL(), authMethodGlobalAuthenticateURL);
|
||||
// });
|
||||
test.skip('deauthentication redirects to first global authenticate method', async function (assert) {
|
||||
assert.expect(3);
|
||||
await visit(authMethodAuthenticateURL);
|
||||
await fillIn('[name="identification"]', 'test');
|
||||
await fillIn('[name="password"]', 'test');
|
||||
await click('[type="submit"]');
|
||||
assert.ok(currentSession().isAuthenticated);
|
||||
// Open header utilities dropdown
|
||||
await click('.rose-header-utilities .rose-dropdown summary');
|
||||
// Find and click on last element in dropdown - should be deauthenticate button
|
||||
const menu = findAll(
|
||||
'.rose-header-utilities .rose-dropdown .rose-dropdown-content button'
|
||||
);
|
||||
await click(menu[menu.length - 1]);
|
||||
assert.notOk(currentSession().isAuthenticated);
|
||||
assert.equal(currentURL(), authMethodGlobalAuthenticateURL);
|
||||
});
|
||||
|
||||
test('401 responses result in deauthentication', async function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
@@ -109,12 +109,12 @@ module('Acceptance | groups | create', function (hooks) {
|
||||
await visit(urls.newGroup);
|
||||
await fillIn('[name="name"]', 'group name');
|
||||
await click('[type="submit"]');
|
||||
assert.ok(
|
||||
find('[role="alert"]').textContent.trim(),
|
||||
assert.equal(
|
||||
find('.rose-notification-body').textContent.trim(),
|
||||
'The request was invalid.',
|
||||
'Displays primary error message.'
|
||||
);
|
||||
assert.ok(
|
||||
assert.equal(
|
||||
find('.rose-form-error-message').textContent.trim(),
|
||||
'Name is required.',
|
||||
'Displays field-level errors.'
|
||||
|
||||
@@ -76,8 +76,8 @@ module('Acceptance | groups | delete', function (hooks) {
|
||||
});
|
||||
await visit(urls.group);
|
||||
await click('.rose-layout-page-actions .rose-dropdown-button-danger');
|
||||
assert.ok(
|
||||
find('[role="alert"]').textContent.trim(),
|
||||
assert.equal(
|
||||
find('.rose-notification-body').textContent.trim(),
|
||||
'Oops.',
|
||||
'Displays primary error message.'
|
||||
);
|
||||
|
||||
@@ -95,12 +95,12 @@ module('Acceptance | groups | update', function (hooks) {
|
||||
await click('form [type="button"]', 'Activate edit mode');
|
||||
await fillIn('[name="name"]', 'random string');
|
||||
await click('[type="submit"]');
|
||||
assert.ok(
|
||||
find('[role="alert"]').textContent.trim(),
|
||||
assert.equal(
|
||||
find('.rose-notification-body').textContent.trim(),
|
||||
'The request was invalid.',
|
||||
'Displays primary error message.'
|
||||
);
|
||||
assert.ok(
|
||||
assert.equal(
|
||||
find('.rose-form-error-message').textContent.trim(),
|
||||
'Name is required.',
|
||||
'Displays field-level errors.'
|
||||
|
||||
@@ -88,8 +88,8 @@ module('Acceptance | roles | delete', function (hooks) {
|
||||
});
|
||||
await visit(urls.role);
|
||||
await click('.rose-layout-page-actions .rose-dropdown-button-danger');
|
||||
assert.ok(
|
||||
find('[role="alert"]').textContent.trim(),
|
||||
assert.equal(
|
||||
find('.rose-notification-body').textContent.trim(),
|
||||
'Oops.',
|
||||
'Displays primary error message.'
|
||||
);
|
||||
|
||||
@@ -107,12 +107,12 @@ module('Acceptance | roles | update', function (hooks) {
|
||||
await click('form [type="button"]', 'Activate edit mode');
|
||||
await fillIn('[name="name"]', 'random string');
|
||||
await click('[type="submit"]');
|
||||
assert.ok(
|
||||
find('[role="alert"]').textContent.trim(),
|
||||
assert.equal(
|
||||
find('.rose-notification-body').textContent.trim(),
|
||||
'The request was invalid.',
|
||||
'Displays primary error message.'
|
||||
);
|
||||
assert.ok(
|
||||
assert.equal(
|
||||
find('.rose-form-error-message').textContent.trim(),
|
||||
'Name is required.',
|
||||
'Displays field-level errors.'
|
||||
|
||||
@@ -97,12 +97,12 @@ module('Acceptance | users | create', function (hooks) {
|
||||
await visit(newUserURL);
|
||||
await fillIn('[name="name"]', 'User name');
|
||||
await click('[type="submit"]');
|
||||
assert.ok(
|
||||
find('[role="alert"]').textContent.trim(),
|
||||
assert.equal(
|
||||
find('.rose-notification-body').textContent.trim(),
|
||||
'The request was invalid.',
|
||||
'Displays primary error message.'
|
||||
);
|
||||
assert.ok(
|
||||
assert.equal(
|
||||
find('.rose-form-error-message').textContent.trim(),
|
||||
'Name is required.',
|
||||
'Displays field-level errors.'
|
||||
|
||||
@@ -77,8 +77,8 @@ module('Acceptance | users | delete', function (hooks) {
|
||||
});
|
||||
await visit(userURL);
|
||||
await click('.rose-layout-page-actions .rose-dropdown-button-danger');
|
||||
assert.ok(
|
||||
find('[role="alert"]').textContent.trim(),
|
||||
assert.equal(
|
||||
find('.rose-notification-body').textContent.trim(),
|
||||
'Oops.',
|
||||
'Displays primary error message.'
|
||||
);
|
||||
|
||||
@@ -96,12 +96,12 @@ module('Acceptance | users | update', function (hooks) {
|
||||
await click('form [type="button"]', 'Activate edit mode');
|
||||
await fillIn('[name="name"]', 'User name');
|
||||
await click('[type="submit"]');
|
||||
assert.ok(
|
||||
find('[role="alert"]').textContent.trim(),
|
||||
assert.equal(
|
||||
find('.rose-notification-body').textContent.trim(),
|
||||
'The request was invalid.',
|
||||
'Displays primary error message.'
|
||||
);
|
||||
assert.ok(
|
||||
assert.equal(
|
||||
find('.rose-form-error-message').textContent.trim(),
|
||||
'Name is required.',
|
||||
'Displays field-level errors.'
|
||||
|
||||
@@ -12,8 +12,5 @@ insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.hbs]
|
||||
insert_final_newline = false
|
||||
|
||||
[*.{diff,md}]
|
||||
trim_trailing_whitespace = false
|
||||
@@ -56,5 +56,10 @@ module.exports = {
|
||||
'node/no-unpublished-require': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
// Test files:
|
||||
files: ['tests/**/*-test.{js,ts}'],
|
||||
extends: ['plugin:qunit/recommended'],
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -72,7 +72,7 @@
|
||||
"ember-a11y-testing": "^4.2.0",
|
||||
"ember-auto-import": "^1.12.0",
|
||||
"ember-autofocus-modifier": "^2.0.0",
|
||||
"ember-cli": "~3.28.0",
|
||||
"ember-cli": "~3.28.3",
|
||||
"ember-cli-app-version": "^5.0.0",
|
||||
"ember-cli-babel": "^7.26.6",
|
||||
"ember-cli-code-coverage": "^1.0.3",
|
||||
@@ -95,7 +95,7 @@
|
||||
"ember-page-title": "^6.2.2",
|
||||
"ember-qunit": "^5.1.4",
|
||||
"ember-resolver": "^8.0.3",
|
||||
"ember-source": "~3.24.0",
|
||||
"ember-source": "~3.28.4",
|
||||
"ember-template-lint": "^3.7.0",
|
||||
"ember-template-lint-plugin-prettier": "^2.0.0",
|
||||
"eslint": "^7.32.0",
|
||||
@@ -103,6 +103,7 @@
|
||||
"eslint-plugin-ember": "^10.5.4",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"eslint-plugin-qunit": "^6.2.0",
|
||||
"faker": "^5.5.3",
|
||||
"loader.js": "^4.7.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
@@ -117,7 +118,7 @@
|
||||
"stylelint-config-sass-guidelines": "^8.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10 <=15"
|
||||
"node": ">=12 <=17"
|
||||
},
|
||||
"ember": {
|
||||
"edition": "octane"
|
||||
|
||||
@@ -4,12 +4,19 @@ const { _electron: electron } = require('playwright');
|
||||
const helpers = require('./test-helpers');
|
||||
|
||||
let electronApp = null;
|
||||
// Subdirectory within tests/end2end/screenshots where the screenshots of this test suite will be stored.
|
||||
const screenshotsDirectory = 'authentication/';
|
||||
// Path where the Boundary Desktop client binary is generated
|
||||
const executablePath = helpers.returnExecutablePath(
|
||||
process.platform,
|
||||
process.arch
|
||||
);
|
||||
|
||||
// Set login variables
|
||||
const originValue = 'http://localhost:9200';
|
||||
const loginUsername = 'admin';
|
||||
const loginPassword = 'password';
|
||||
|
||||
test.beforeEach(async () => {
|
||||
electronApp = await electron.launch({
|
||||
executablePath: executablePath,
|
||||
@@ -34,29 +41,15 @@ test.describe('Authentication end to end test suite', async () => {
|
||||
await boundaryWindow.evaluate(() =>
|
||||
window.localStorage.setItem('desktop:origin', null)
|
||||
);
|
||||
const originValue = 'http://localhost:9200';
|
||||
const authLoginNameValue = 'admin';
|
||||
const authLoginPasswordValue = 'password';
|
||||
|
||||
// Fill the origin input
|
||||
await boundaryWindow.waitForSelector('[name=host]');
|
||||
await boundaryWindow.fill('[name=host]', originValue);
|
||||
// Take screenshot
|
||||
await boundaryWindow.screenshot({
|
||||
path: helpers.generateScreenshotPath(
|
||||
screenshotsDirectory,
|
||||
'fillOrigin'
|
||||
),
|
||||
fullPage: true,
|
||||
});
|
||||
// Perform login
|
||||
await helpers.login(
|
||||
boundaryWindow,
|
||||
originValue,
|
||||
loginUsername,
|
||||
loginPassword
|
||||
);
|
||||
|
||||
// Click the submit button
|
||||
await boundaryWindow.waitForSelector('button[type="submit"]');
|
||||
await helpers.click(boundaryWindow, 'button[type="submit"]');
|
||||
|
||||
// Fill user & password
|
||||
await boundaryWindow.fill('[name="identification"]', authLoginNameValue);
|
||||
await boundaryWindow.fill('[name="password"]', authLoginPasswordValue);
|
||||
// Take screenshot
|
||||
await boundaryWindow.screenshot({
|
||||
path: helpers.generateScreenshotPath(
|
||||
@@ -126,32 +119,13 @@ test.describe('Authentication end to end test suite', async () => {
|
||||
await boundaryWindow.evaluate(() =>
|
||||
window.localStorage.setItem('desktop:origin', null)
|
||||
);
|
||||
const originValue = 'http://localhost:9200';
|
||||
const authLoginNameValue = 'admin';
|
||||
const authLoginPasswordValue = '123456';
|
||||
|
||||
// Fill the origin input
|
||||
await boundaryWindow.fill('[name=host]', originValue);
|
||||
// Take screenshot
|
||||
await boundaryWindow.screenshot({
|
||||
path: helpers.generateScreenshotPath(
|
||||
screenshotsDirectory,
|
||||
'fillOrigin'
|
||||
),
|
||||
fullPage: true,
|
||||
});
|
||||
|
||||
// Click the submit button
|
||||
await boundaryWindow.waitForSelector('button[type="submit"]');
|
||||
await helpers.click(boundaryWindow, 'button[type="submit"]');
|
||||
|
||||
// Fill user & password
|
||||
await boundaryWindow.fill('[name="identification"]', authLoginNameValue);
|
||||
await boundaryWindow.fill('[name="password"]', authLoginPasswordValue);
|
||||
|
||||
// Click submit
|
||||
await boundaryWindow.waitForSelector('button[type="submit"]');
|
||||
await helpers.click(boundaryWindow, 'button[type="submit"]');
|
||||
// Perform login
|
||||
await helpers.login(
|
||||
boundaryWindow,
|
||||
originValue,
|
||||
loginUsername,
|
||||
'123456789'
|
||||
);
|
||||
|
||||
// Wait for the notification
|
||||
await boundaryWindow.waitForSelector('.rose-notification-body');
|
||||
|
||||
@@ -4,12 +4,19 @@ const { _electron: electron } = require('playwright');
|
||||
const helpers = require('./test-helpers');
|
||||
|
||||
let electronApp = null;
|
||||
// Subdirectory within tests/end2end/screenshots where the screenshots of this test suite will be stored.
|
||||
const screenshotsDirectory = 'targets/';
|
||||
// Path where the Boundary Desktop client binary is generated
|
||||
const executablePath = helpers.returnExecutablePath(
|
||||
process.platform,
|
||||
process.arch
|
||||
);
|
||||
|
||||
// Set login variables
|
||||
const originValue = 'http://localhost:9200';
|
||||
const loginUsername = 'admin';
|
||||
const loginPassword = 'password';
|
||||
|
||||
test.beforeEach(async () => {
|
||||
electronApp = await electron.launch({
|
||||
executablePath: executablePath,
|
||||
@@ -28,30 +35,19 @@ test.afterEach(async () => {
|
||||
test.describe('Targets end to end test suite', async () => {
|
||||
test('Connects to a target', async () => {
|
||||
const boundaryWindow = await electronApp.firstWindow(); // The window that contains the app.
|
||||
|
||||
// Override local storage origin
|
||||
await boundaryWindow.evaluate(() =>
|
||||
window.localStorage.setItem('desktop:origin', null)
|
||||
);
|
||||
|
||||
const originValue = 'http://localhost:9200';
|
||||
const authLoginNameValue = 'admin';
|
||||
const authLoginPasswordValue = 'password';
|
||||
|
||||
// Fill the origin input
|
||||
await boundaryWindow.waitForSelector('[name=host]');
|
||||
await boundaryWindow.fill('[name=host]', originValue);
|
||||
|
||||
// Click the submit button
|
||||
await boundaryWindow.waitForSelector('button[type="submit"]');
|
||||
await helpers.click(boundaryWindow, 'button[type="submit"]');
|
||||
|
||||
// Fill user & password
|
||||
await boundaryWindow.fill('[name="identification"]', authLoginNameValue);
|
||||
await boundaryWindow.fill('[name="password"]', authLoginPasswordValue);
|
||||
|
||||
// Click submit
|
||||
await boundaryWindow.waitForSelector('button[type="submit"]');
|
||||
await helpers.click(boundaryWindow, 'button[type="submit"]');
|
||||
// Perform the login
|
||||
await helpers.login(
|
||||
boundaryWindow,
|
||||
originValue,
|
||||
loginUsername,
|
||||
loginPassword
|
||||
);
|
||||
|
||||
// Check we are in Targets
|
||||
await boundaryWindow.waitForURL('**/#/scopes/global/projects/targets');
|
||||
|
||||
@@ -46,9 +46,34 @@ exports.returnExecutablePath = (platform, arch) => {
|
||||
/**
|
||||
* Performs a click with a workarouind due to an error with plain playwright click.
|
||||
* More info about the issue here: https://github.com/microsoft/playwright/issues/1808
|
||||
* @param {*} appWindow The current electron window.
|
||||
* @param {*} selector The DOM element selector.
|
||||
* @param {object} appWindow The electron window to perform the action.
|
||||
* @param {string} selector The DOM element selector.
|
||||
*/
|
||||
exports.click = async (appWindow, selector) => {
|
||||
await appWindow.$eval(selector, (element) => element.click());
|
||||
};
|
||||
|
||||
/**
|
||||
* Performs login on the app window provided with the credentials provided.
|
||||
* @param {object} appWindow The electron window to perform the action.
|
||||
* @param {string} origin URL origin to set.
|
||||
* @param {string} username Username to login.
|
||||
* @param {string} password Password to login.
|
||||
*/
|
||||
exports.login = async (appWindow, origin, username, password) => {
|
||||
// Fill the origin input
|
||||
await appWindow.waitForSelector('[name=host]');
|
||||
await appWindow.fill('[name=host]', origin);
|
||||
|
||||
// Click the set origin submit button
|
||||
await appWindow.waitForSelector('button[type="submit"]');
|
||||
await this.click(appWindow, 'button[type="submit"]');
|
||||
|
||||
// Fill user & password
|
||||
await appWindow.fill('[name="identification"]', username);
|
||||
await appWindow.fill('[name="password"]', password);
|
||||
|
||||
// Click submit
|
||||
await appWindow.waitForSelector('button[type="submit"]');
|
||||
await this.click(appWindow, 'button[type="submit"]');
|
||||
};
|
||||
@@ -13,7 +13,7 @@ module('Integration | Component | dialog-detail', function (hooks) {
|
||||
|
||||
test('it renders with content', async function (assert) {
|
||||
await render(hbs`
|
||||
<DialogDetail>
|
||||
<DialogDetail as |dialogDetail|>
|
||||
<dialogDetail.notification />
|
||||
<dialogDetail.body>
|
||||
<h2>Test</h2>
|
||||
|
||||
@@ -73,7 +73,7 @@ module('Unit | Service | ipc', function (hooks) {
|
||||
});
|
||||
});
|
||||
|
||||
test('IPCRequests reject if receiving an Error instance, where the rejection value is the parsed JSON Error message', async (assert) => {
|
||||
test('IPCRequests reject if receiving an Error instance, where the rejection value is the parsed JSON Error message', async function (assert) {
|
||||
assert.expect(1);
|
||||
const stringifiedPayload = JSON.stringify({
|
||||
foo: 'bar',
|
||||
|
||||
Reference in new issue
Block a user