Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ember cli string helpers replacement #8320

Merged
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
stopfstedt marked this conversation as resolved.
Show resolved Hide resolved
Empty file.
15 changes: 15 additions & 0 deletions packages/ilios-common/addon/helpers/capitalize.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { helper } from '@ember/component/helper';
import { capitalize as _capitalize } from '@ember/string';
import { isHTMLSafe } from '@ember/template';

export function capitalize([string]) {
if (isHTMLSafe(string)) {
string = string.toString();
}

string = string || '';

return _capitalize(string);
}

export default helper(capitalize);
14 changes: 14 additions & 0 deletions packages/ilios-common/addon/helpers/html-safe.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { helper } from '@ember/component/helper';
import { isHTMLSafe, htmlSafe as _htmlSafe } from '@ember/template';

export function htmlSafe([string]) {
if (isHTMLSafe(string)) {
string = string.toString();
}

string = string || '';

return _htmlSafe(string);
}

export default helper(htmlSafe);
18 changes: 18 additions & 0 deletions packages/ilios-common/addon/helpers/truncate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { helper } from '@ember/component/helper';
import { isHTMLSafe } from '@ember/template';

export function truncate([string, characterLimit = 140, useEllipsis = true]) {
let limit = useEllipsis ? characterLimit - 3 : characterLimit;

if (isHTMLSafe(string)) {
string = string.toString();
}

if (string && string.length > limit) {
return useEllipsis ? `${string.substring(0, limit)}...` : string.substring(0, limit);
} else {
return string;
}
}

export default helper(truncate);
1 change: 1 addition & 0 deletions packages/ilios-common/app/helpers/capitalize.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from 'ilios-common/helpers/capitalize';
1 change: 1 addition & 0 deletions packages/ilios-common/app/helpers/html-safe.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from 'ilios-common/helpers/html-safe';
1 change: 1 addition & 0 deletions packages/ilios-common/app/helpers/truncate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from 'ilios-common/helpers/truncate';
1 change: 0 additions & 1 deletion packages/ilios-common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
"ember-cli-flash": "^5.1.0",
"ember-cli-htmlbars": "^6.3.0",
"ember-cli-page-object": "^2.3.0",
"ember-cli-string-helpers": "^6.0.1",
"ember-click-outside": "^6.0.0",
"ember-concurrency": "^4.0.2",
"ember-event-helpers": "^0.1.0",
Expand Down
59 changes: 59 additions & 0 deletions packages/test-app/tests/integration/helpers/capitalize-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';
import { htmlSafe } from '@ember/template';

module('Integration | Helper | {{capitalize}}', function (hooks) {
setupRenderingTest(hooks);

test('It capitalizes a single string', async function (assert) {
await render(hbs`{{capitalize 'hi'}}`);

let expected = 'Hi';

assert.dom().hasText(expected, 'capitalizes a single string');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like seeing test messages like these!

});

test('It leaves the capitalization unchanged with correctly capitalized string', async function (assert) {
await render(hbs`{{capitalize 'Harry'}}`);

let expected = 'Harry';

assert.dom().hasText(expected, 'leaves capitalization when string is already capitalized');
});

test('It correctly capitalizes an uncapitalized sentence', async function (assert) {
await render(hbs`{{capitalize 'age is foolish and forgetful when it underestimates youth'}}`);

let expected = 'Age is foolish and forgetful when it underestimates youth';

assert.dom().hasText(expected, 'correctly capitalizes an uncapitalized sentence');
});

test('It correctly handles empty string input', async function (assert) {
await render(hbs`{{capitalize ''}}`);

let expected = '';

assert.dom().hasText(expected, 'renders empty string if input is empty string');
});

test('It correctly handles undefined input', async function (assert) {
await render(hbs`{{capitalize undefined}}`);

let expected = '';

assert.dom().hasText(expected, 'renders empty string if undefined input');
});

test('It handles a SafeString', async function (assert) {
this.set('greeting', htmlSafe('hi'));

await render(hbs`{{capitalize this.greeting}}`);

let expected = 'Hi';

assert.dom().hasText(expected, 'correctly capitalizes a SafeString');
});
});
35 changes: 35 additions & 0 deletions packages/test-app/tests/integration/helpers/html-safe-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { htmlSafe } from '@ember/template';
import { render, find } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';

module('Integration | Helper | {{html-safe}}', function (hooks) {
setupRenderingTest(hooks);

test('It html-safes the html string', async function (assert) {
await render(hbs`{{html-safe '<h1>Hello World</h1>'}}`);

assert.dom('h1').hasText('Hello World', 'html string is correctly rendered');
});

test('It safely renders CSS classes from a property', async function (assert) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's an example where this would be used? I've never used any htmlSafe method on a CSS class before.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something like

get widthStyle() {
const str = `width: ${this.args.percentage}%`;
return htmlSafe(str);
}
where if we don't mark the string as safe Ember will escape it to prevent css injection. If you put the class into the template that's fine, but if you attempt to do work on these properties in a getter or some other JS property Ember will call shenanigans.

this.set('classes', 'error has-error');
this.set('text', 'Hello World');
await render(hbs`<h1 class={{html-safe this.classes}}>{{this.text}}</h1>`);

assert.dom('h1').hasText('Hello World', 'it renders');
assert.deepEqual(
find('h1').getAttribute('class').split(' ').sort(),
['error', 'has-error'].sort(),
'it has the correct CSS classes',
);
});

test('It renders safe-string input', async function (assert) {
const safeString = htmlSafe('<h1>Hello World</h1>');
this.set('text', safeString);
await render(hbs`{{html-safe this.text}}`);
assert.dom('h1').hasText('Hello World', 'html string is correctly rendered');
});
});
78 changes: 78 additions & 0 deletions packages/test-app/tests/integration/helpers/truncate-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';
import { htmlSafe } from '@ember/template';

module('Integration | Helper | {{truncate}}', function (hooks) {
setupRenderingTest(hooks);

test('It truncates to 140 characters if no characterLimit is provided', async function (assert) {
await render(
hbs`{{truncate
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas hendrerit quam enim, in suscipit est rutrum id. Etiam vitae blandit purus, sed semper sem.'
}}`,
);

let expected =
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas hendrerit quam enim, in suscipit est rutrum id. Etiam vitae blandit pur...';

assert.dom().hasText(expected, 'truncates to 140 characters');
});

test('It truncates to characterLimit provided', async function (assert) {
await render(
hbs`{{truncate
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas hendrerit quam enim, in suscipit est rutrum id. Etiam vitae blandit purus, sed semper sem.'
20
}}`,
);

let expected = 'Lorem ipsum dolor...';

assert.dom().hasText(expected, 'truncates to characterLimit');
});

test('It does not truncate if string is not longer than characterLimit', async function (assert) {
await render(
hbs`{{truncate
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas hendrerit quam enim, in suscipit est rutrum id.'
140
}}`,
);

let expected =
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas hendrerit quam enim, in suscipit est rutrum id.';

assert.dom().hasText(expected, 'does not truncate');
});

test('It truncates to characterLimit provided without an ellipsis if useEllipsis is false', async function (assert) {
await render(
hbs`{{truncate
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas hendrerit quam enim, in suscipit est rutrum id. Etiam vitae blandit purus, sed semper sem.'
20
false
}}`,
);

let expected = 'Lorem ipsum dolor si';

assert.dom().hasText(expected, 'truncates to characterLimit without ellipsis');
});

test('It handles a SafeString', async function (assert) {
this.set(
'sentence',
htmlSafe(
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas hendrerit quam enim, in suscipit est rutrum id. Etiam vitae blandit purus, sed semper sem.',
),
);

await render(hbs`{{truncate this.sentence 20}}`);

let expected = 'Lorem ipsum dolor...';

assert.dom().hasText(expected, 'correctly trims a SafeString');
});
});
16 changes: 0 additions & 16 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading