WIP Add activity photo item
Can show one or more photo additions in the activity timeline
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
import Component from '@glimmer/component';
|
||||
import { on } from '@ember/modifier';
|
||||
import { fn } from '@ember/helper';
|
||||
import formatRelativeDate from '../helpers/format-relative-date';
|
||||
import { npubEncode } from 'applesauce-core/helpers/pointers';
|
||||
import Icon from './icon';
|
||||
|
||||
export default class ActivityPhotoItem extends Component {
|
||||
get item() {
|
||||
return this.args.item;
|
||||
}
|
||||
|
||||
get senderName() {
|
||||
return this.item?.senderName;
|
||||
}
|
||||
|
||||
get senderDisplayName() {
|
||||
const name = this.senderName;
|
||||
if (name) return name;
|
||||
const pubkey = this.item?.senderPubkey;
|
||||
if (!pubkey) return 'Someone';
|
||||
try {
|
||||
return `${npubEncode(pubkey).slice(0, 12)}…`;
|
||||
} catch {
|
||||
return `${pubkey.slice(0, 12)}…`;
|
||||
}
|
||||
}
|
||||
|
||||
get senderAvatar() {
|
||||
return this.item?.senderAvatar;
|
||||
}
|
||||
|
||||
get hasPhoto() {
|
||||
return this.photos.length > 0;
|
||||
}
|
||||
|
||||
get photos() {
|
||||
const photos = this.item?.photos;
|
||||
if (photos && photos.length > 0) return photos;
|
||||
const single = this.item?.photo;
|
||||
return single ? [single] : [];
|
||||
}
|
||||
|
||||
get primaryPhoto() {
|
||||
return this.photos[0];
|
||||
}
|
||||
|
||||
get extraPhotoCount() {
|
||||
return Math.max(0, this.photos.length - 1);
|
||||
}
|
||||
|
||||
get photoCountText() {
|
||||
const count = this.photos.length;
|
||||
return count === 1 ? 'a photo' : `${count} photos`;
|
||||
}
|
||||
|
||||
get photoThumbUrl() {
|
||||
return this.primaryPhoto?.thumbUrl || this.primaryPhoto?.url;
|
||||
}
|
||||
|
||||
get placeName() {
|
||||
return this.item?.placeName;
|
||||
}
|
||||
|
||||
get placeNameLoading() {
|
||||
return this.item?.placeNameLoading;
|
||||
}
|
||||
|
||||
<template>
|
||||
<li>
|
||||
<button
|
||||
type="button"
|
||||
class="activity-item"
|
||||
{{on "click" (fn @onSelect @item)}}
|
||||
>
|
||||
<div class="header">
|
||||
<span class="sender-line">
|
||||
<span class="sender-name">{{this.senderDisplayName}}</span>
|
||||
{{! template-lint-disable no-whitespace-for-layout }}
|
||||
<span class="action"> added {{this.photoCountText}}</span>
|
||||
</span>
|
||||
<span class="amount">
|
||||
<Icon
|
||||
@name="feather-camera"
|
||||
@size={{16}}
|
||||
@color="var(--secondary-text-color)"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="context">
|
||||
<div class="context-images">
|
||||
{{#if this.senderAvatar}}
|
||||
<img
|
||||
class="sender-avatar"
|
||||
src={{this.senderAvatar}}
|
||||
alt=""
|
||||
loading="lazy"
|
||||
/>
|
||||
{{else}}
|
||||
<div class="sender-avatar-placeholder">
|
||||
<Icon @name="user" @size={{16}} @color="#999" />
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if this.hasPhoto}}
|
||||
<div class="context-thumb">
|
||||
<img src={{this.photoThumbUrl}} alt="" loading="lazy" />
|
||||
{{#if (gt this.extraPhotoCount 0)}}
|
||||
<span
|
||||
class="context-thumb-badge"
|
||||
>+{{this.extraPhotoCount}}</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="context-text">
|
||||
<span class="activity-place-name">
|
||||
{{#if this.placeName}}
|
||||
{{this.placeName}}
|
||||
{{else if this.placeNameLoading}}
|
||||
<span class="contribution-name-loading">Loading…</span>
|
||||
{{else}}
|
||||
<span class="contribution-name-loading">Unnamed place</span>
|
||||
{{/if}}
|
||||
</span>
|
||||
<span class="activity-date">{{formatRelativeDate
|
||||
@item.createdAt
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</li>
|
||||
</template>
|
||||
}
|
||||
@@ -4,15 +4,78 @@ import { tracked } from '@glimmer/tracking';
|
||||
import { on } from '@ember/modifier';
|
||||
import Icon from './icon';
|
||||
import ActivityZapItem from './activity-zap-item';
|
||||
import ActivityPhotoItem from './activity-photo-item';
|
||||
import Modal from './modal';
|
||||
import NostrConnect from './nostr-connect';
|
||||
import not from 'ember-truth-helpers/helpers/not';
|
||||
import eq from 'ember-truth-helpers/helpers/eq';
|
||||
import restoreScroll from '../modifiers/restore-scroll';
|
||||
import { ActivityEntry } from '../utils/activity';
|
||||
|
||||
export default class ActivityTimelineComponent extends Component {
|
||||
@tracked isNostrConnectModalOpen = false;
|
||||
|
||||
get dummyPhotoEntry() {
|
||||
const entry = new ActivityEntry({
|
||||
photoEventId: 'dummy-photo-event-id',
|
||||
photos: [
|
||||
{
|
||||
thumbUrl: 'https://picsum.photos/seed/marco-photo-1/200/200',
|
||||
url: 'https://picsum.photos/seed/marco-photo-1/800/800',
|
||||
placeIdentifier: 'osm:node:123456789',
|
||||
},
|
||||
],
|
||||
placeIdentifier: 'osm:node:123456789',
|
||||
senderPubkey: 'dummy-sender-pubkey',
|
||||
amountSats: 0,
|
||||
message: null,
|
||||
createdAt: Math.floor(Date.now() / 1000) - 3600,
|
||||
});
|
||||
entry.type = 'photo';
|
||||
entry.senderName = 'Alice Mapper';
|
||||
entry.senderAvatar =
|
||||
'https://api.dicebear.com/7.x/avataaars/svg?seed=alice';
|
||||
entry.placeName = 'Central Park Café';
|
||||
entry.placeNameLoading = false;
|
||||
entry.senderProfileLoading = false;
|
||||
return entry;
|
||||
}
|
||||
|
||||
get dummyMultiPhotoEntry() {
|
||||
const entry = new ActivityEntry({
|
||||
photoEventId: 'dummy-multi-photo-event-id',
|
||||
photos: [
|
||||
{
|
||||
thumbUrl: 'https://picsum.photos/seed/marco-multi-1/200/200',
|
||||
url: 'https://picsum.photos/seed/marco-multi-1/800/800',
|
||||
placeIdentifier: 'osm:node:987654321',
|
||||
},
|
||||
{
|
||||
thumbUrl: 'https://picsum.photos/seed/marco-multi-2/200/200',
|
||||
url: 'https://picsum.photos/seed/marco-multi-2/800/800',
|
||||
placeIdentifier: 'osm:node:987654321',
|
||||
},
|
||||
{
|
||||
thumbUrl: 'https://picsum.photos/seed/marco-multi-3/200/200',
|
||||
url: 'https://picsum.photos/seed/marco-multi-3/800/800',
|
||||
placeIdentifier: 'osm:node:987654321',
|
||||
},
|
||||
],
|
||||
placeIdentifier: 'osm:node:987654321',
|
||||
senderPubkey: 'dummy-multi-sender-pubkey',
|
||||
amountSats: 0,
|
||||
message: null,
|
||||
createdAt: Math.floor(Date.now() / 1000) - 7200,
|
||||
});
|
||||
entry.type = 'photo';
|
||||
entry.senderName = 'Bob Cartographer';
|
||||
entry.senderAvatar = 'https://api.dicebear.com/7.x/avataaars/svg?seed=bob';
|
||||
entry.placeName = 'Riverside Lookout';
|
||||
entry.placeNameLoading = false;
|
||||
entry.senderProfileLoading = false;
|
||||
return entry;
|
||||
}
|
||||
|
||||
@action
|
||||
openNostrConnectModal(event) {
|
||||
event.preventDefault();
|
||||
@@ -69,8 +132,18 @@ export default class ActivityTimelineComponent extends Component {
|
||||
{{#each @items as |item|}}
|
||||
{{#if (eq item.type "zap")}}
|
||||
<ActivityZapItem @item={{item}} @onSelect={{@onSelect}} />
|
||||
{{else if (eq item.type "photo")}}
|
||||
<ActivityPhotoItem @item={{item}} @onSelect={{@onSelect}} />
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
<ActivityPhotoItem
|
||||
@item={{this.dummyPhotoEntry}}
|
||||
@onSelect={{@onSelect}}
|
||||
/>
|
||||
<ActivityPhotoItem
|
||||
@item={{this.dummyMultiPhotoEntry}}
|
||||
@onSelect={{@onSelect}}
|
||||
/>
|
||||
</ul>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
@@ -50,40 +50,40 @@ export default class ActivityZapItem extends Component {
|
||||
<li>
|
||||
<button
|
||||
type="button"
|
||||
class="activity-zap-item"
|
||||
class="activity-item"
|
||||
{{on "click" (fn @onSelect @item)}}
|
||||
>
|
||||
<div class="zap-header">
|
||||
<span class="zap-sender-line">
|
||||
<span class="zap-sender-name">{{this.senderDisplayName}}</span>
|
||||
<div class="header">
|
||||
<span class="sender-line">
|
||||
<span class="sender-name">{{this.senderDisplayName}}</span>
|
||||
{{! template-lint-disable no-whitespace-for-layout }}
|
||||
<span class="zap-action"> zapped your photo</span>
|
||||
<span class="action"> zapped your photo</span>
|
||||
</span>
|
||||
<span class="zap-amount">{{this.item.amountSats}} ⚡</span>
|
||||
<span class="amount">{{this.item.amountSats}} ⚡</span>
|
||||
</div>
|
||||
|
||||
<div class="zap-context">
|
||||
<div class="zap-context-images">
|
||||
<div class="context">
|
||||
<div class="context-images">
|
||||
{{#if this.senderAvatar}}
|
||||
<img
|
||||
class="zap-sender-avatar"
|
||||
class="sender-avatar"
|
||||
src={{this.senderAvatar}}
|
||||
alt=""
|
||||
loading="lazy"
|
||||
/>
|
||||
{{else}}
|
||||
<div class="zap-sender-avatar-placeholder">
|
||||
<div class="sender-avatar-placeholder">
|
||||
<Icon @name="user" @size={{16}} @color="#999" />
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if this.hasPhoto}}
|
||||
<div class="zap-context-thumb">
|
||||
<div class="context-thumb">
|
||||
<img src={{this.photoThumbUrl}} alt="" loading="lazy" />
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="zap-context-text">
|
||||
<span class="zap-place-name">
|
||||
<div class="context-text">
|
||||
<span class="activity-place-name">
|
||||
{{#if this.placeName}}
|
||||
{{this.placeName}}
|
||||
{{else if this.placeNameLoading}}
|
||||
@@ -92,12 +92,14 @@ export default class ActivityZapItem extends Component {
|
||||
<span class="contribution-name-loading">Unnamed place</span>
|
||||
{{/if}}
|
||||
</span>
|
||||
<span class="zap-date">{{formatRelativeDate @item.createdAt}}</span>
|
||||
<span class="activity-date">{{formatRelativeDate
|
||||
@item.createdAt
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{#if this.item.message}}
|
||||
<div class="zap-message">{{this.item.message}}</div>
|
||||
<div class="message">{{this.item.message}}</div>
|
||||
{{/if}}
|
||||
</button>
|
||||
</li>
|
||||
|
||||
+32
-16
@@ -2661,14 +2661,14 @@ button.create-place {
|
||||
}
|
||||
}
|
||||
|
||||
/* Activity Timeline — zap activity list rendered in the sidebar */
|
||||
/* Activity Timeline — activity list rendered in the sidebar */
|
||||
.activity-list {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: -1rem -1rem 0;
|
||||
}
|
||||
|
||||
.activity-zap-item {
|
||||
.activity-item {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
border: none;
|
||||
@@ -2687,7 +2687,7 @@ button.create-place {
|
||||
background: var(--hover-bg);
|
||||
}
|
||||
|
||||
& .zap-sender-avatar {
|
||||
& .sender-avatar {
|
||||
flex-shrink: 0;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
@@ -2696,7 +2696,7 @@ button.create-place {
|
||||
background: #f0f0f0;
|
||||
}
|
||||
|
||||
& .zap-sender-avatar-placeholder {
|
||||
& .sender-avatar-placeholder {
|
||||
flex-shrink: 0;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
@@ -2708,39 +2708,42 @@ button.create-place {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
& .zap-header {
|
||||
& .header {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
& .zap-sender-line {
|
||||
& .sender-line {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
font-size: 0.95rem;
|
||||
|
||||
& .zap-sender-name {
|
||||
& .sender-name {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
& .zap-action {
|
||||
& .action {
|
||||
color: #666;
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
|
||||
& .zap-amount {
|
||||
& .amount {
|
||||
flex-shrink: 0;
|
||||
font-weight: bold;
|
||||
font-size: 0.95rem;
|
||||
color: var(--body-text-color);
|
||||
white-space: nowrap;
|
||||
align-self: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
& .zap-message {
|
||||
& .message {
|
||||
color: var(--body-text-color);
|
||||
font-size: 0.85rem;
|
||||
font-style: italic;
|
||||
@@ -2762,7 +2765,7 @@ button.create-place {
|
||||
}
|
||||
}
|
||||
|
||||
& .zap-context {
|
||||
& .context {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
@@ -2770,19 +2773,20 @@ button.create-place {
|
||||
font-size: 0.8rem;
|
||||
margin-top: 8px;
|
||||
|
||||
& .zap-context-images {
|
||||
& .context-images {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
& .zap-context-thumb {
|
||||
& .context-thumb {
|
||||
flex-shrink: 0;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
background: #f0f0f0;
|
||||
position: relative;
|
||||
|
||||
& img {
|
||||
width: 100%;
|
||||
@@ -2790,16 +2794,28 @@ button.create-place {
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
}
|
||||
|
||||
& .context-thumb-badge {
|
||||
position: absolute;
|
||||
bottom: 2px;
|
||||
right: 2px;
|
||||
background: rgb(0 0 0 / 65%);
|
||||
color: #fff;
|
||||
font-size: 0.7rem;
|
||||
font-weight: bold;
|
||||
padding: 1px 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
& .zap-context-text {
|
||||
& .context-text {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 6px;
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
|
||||
& .zap-place-name {
|
||||
& .activity-place-name {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
@@ -2807,7 +2823,7 @@ button.create-place {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
& .zap-date {
|
||||
& .activity-date {
|
||||
flex-shrink: 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ export class ActivityEntry {
|
||||
type = 'zap';
|
||||
photoEventId;
|
||||
photo;
|
||||
photos = [];
|
||||
placeIdentifier;
|
||||
osmType;
|
||||
osmId;
|
||||
@@ -43,6 +44,7 @@ export class ActivityEntry {
|
||||
constructor({
|
||||
photoEventId,
|
||||
photo,
|
||||
photos,
|
||||
placeIdentifier,
|
||||
senderPubkey,
|
||||
amountSats,
|
||||
@@ -51,6 +53,7 @@ export class ActivityEntry {
|
||||
}) {
|
||||
this.photoEventId = photoEventId;
|
||||
this.photo = photo;
|
||||
this.photos = photos ?? [];
|
||||
this.placeIdentifier = placeIdentifier;
|
||||
this.senderPubkey = senderPubkey;
|
||||
this.amountSats = amountSats;
|
||||
|
||||
@@ -97,12 +97,12 @@ module('Acceptance | activity', function (hooks) {
|
||||
test('activity items are rendered as zap rows', async function (assert) {
|
||||
await visit('/activity');
|
||||
|
||||
await waitFor('.activity-zap-item');
|
||||
assert.dom('.activity-zap-item').exists({ count: 1 });
|
||||
assert.dom('.zap-sender-name').hasText('Alice');
|
||||
assert.dom('.zap-action').includesText('zapped your photo');
|
||||
assert.dom('.zap-amount').includesText('21 ⚡');
|
||||
assert.dom('.zap-message').includesText('Great photo!');
|
||||
await waitFor('.activity-item');
|
||||
assert.dom('.activity-item').exists({ count: 3 });
|
||||
assert.dom('.sender-name').hasText('Alice');
|
||||
assert.dom('.action').includesText('zapped your photo');
|
||||
assert.dom('.amount').includesText('21 ⚡');
|
||||
assert.dom('.message').includesText('Great photo!');
|
||||
});
|
||||
|
||||
test('closing the sidebar returns to index', async function (assert) {
|
||||
@@ -124,9 +124,9 @@ module('Acceptance | activity', function (hooks) {
|
||||
const mapUi = this.owner.lookup('service:map-ui');
|
||||
|
||||
await visit('/activity');
|
||||
await waitFor('.activity-zap-item');
|
||||
await waitFor('.activity-item');
|
||||
|
||||
await click('.activity-zap-item');
|
||||
await click('.activity-item');
|
||||
|
||||
assert.ok(
|
||||
currentURL().includes('/place/osm:node:123'),
|
||||
|
||||
@@ -143,7 +143,7 @@ module('Integration | Component | activity-timeline', function (hooks) {
|
||||
</template>
|
||||
);
|
||||
|
||||
assert.dom('.activity-zap-item').exists({ count: 2 });
|
||||
assert.dom('.activity-item').exists({ count: 4 });
|
||||
assert.dom(this.element).includesText('Alice');
|
||||
assert.dom(this.element).includesText('21 ⚡');
|
||||
assert.dom(this.element).includesText('Bob');
|
||||
|
||||
@@ -36,15 +36,15 @@ module('Integration | Component | activity-zap-item', function (hooks) {
|
||||
</template>
|
||||
);
|
||||
|
||||
assert.dom('.zap-sender-name').hasText('Alice');
|
||||
assert.dom('.zap-action').includesText('zapped your photo');
|
||||
assert.dom('.zap-amount').hasText('21 ⚡');
|
||||
assert.dom('.zap-message').includesText('Great shot!');
|
||||
assert.dom('.sender-name').hasText('Alice');
|
||||
assert.dom('.action').includesText('zapped your photo');
|
||||
assert.dom('.amount').hasText('21 ⚡');
|
||||
assert.dom('.message').includesText('Great shot!');
|
||||
assert
|
||||
.dom('.zap-sender-avatar')
|
||||
.dom('.sender-avatar')
|
||||
.hasAttribute('src', 'https://x.com/avatar.jpg');
|
||||
assert
|
||||
.dom('.zap-context-thumb img')
|
||||
.dom('.context-thumb img')
|
||||
.hasAttribute('src', 'https://x.com/thumb.jpg');
|
||||
});
|
||||
|
||||
@@ -68,8 +68,8 @@ module('Integration | Component | activity-zap-item', function (hooks) {
|
||||
</template>
|
||||
);
|
||||
|
||||
assert.dom('.zap-sender-avatar-placeholder').exists();
|
||||
assert.dom('.zap-sender-avatar').doesNotExist();
|
||||
assert.dom('.sender-avatar-placeholder').exists();
|
||||
assert.dom('.sender-avatar').doesNotExist();
|
||||
});
|
||||
|
||||
test('it omits the message line when there is no message', async function (assert) {
|
||||
@@ -91,7 +91,7 @@ module('Integration | Component | activity-zap-item', function (hooks) {
|
||||
</template>
|
||||
);
|
||||
|
||||
assert.dom('.zap-message').doesNotExist();
|
||||
assert.dom('.message').doesNotExist();
|
||||
});
|
||||
|
||||
test('it omits the context thumbnail when there is no photo', async function (assert) {
|
||||
@@ -113,8 +113,8 @@ module('Integration | Component | activity-zap-item', function (hooks) {
|
||||
</template>
|
||||
);
|
||||
|
||||
assert.dom('.zap-context-thumb').doesNotExist();
|
||||
assert.dom('.zap-context-text').exists();
|
||||
assert.dom('.context-thumb').doesNotExist();
|
||||
assert.dom('.context-text').exists();
|
||||
});
|
||||
|
||||
test('clicking the item fires @onSelect with the item', async function (assert) {
|
||||
@@ -141,7 +141,7 @@ module('Integration | Component | activity-zap-item', function (hooks) {
|
||||
</template>
|
||||
);
|
||||
|
||||
await click('.activity-zap-item');
|
||||
await click('.activity-item');
|
||||
|
||||
assert.strictEqual(selected, this.item);
|
||||
});
|
||||
@@ -168,7 +168,7 @@ module('Integration | Component | activity-zap-item', function (hooks) {
|
||||
);
|
||||
|
||||
assert
|
||||
.dom('.zap-context-text')
|
||||
.dom('.context-text')
|
||||
.includesText('Café Central', 'Resolved place name is displayed');
|
||||
assert
|
||||
.dom('.contribution-name-loading')
|
||||
@@ -197,7 +197,7 @@ module('Integration | Component | activity-zap-item', function (hooks) {
|
||||
);
|
||||
|
||||
assert
|
||||
.dom('.zap-context-text .contribution-name-loading')
|
||||
.dom('.context-text .contribution-name-loading')
|
||||
.hasText('Loading…', 'Loading state is displayed');
|
||||
});
|
||||
|
||||
@@ -223,11 +223,11 @@ module('Integration | Component | activity-zap-item', function (hooks) {
|
||||
);
|
||||
|
||||
assert
|
||||
.dom('.zap-context-text .contribution-name-loading')
|
||||
.dom('.context-text .contribution-name-loading')
|
||||
.hasText('Unnamed place', 'Fallback name is displayed');
|
||||
});
|
||||
|
||||
test('it displays place name in zap-place-name and date in zap-date', async function (assert) {
|
||||
test('it displays place name in activity-place-name and date in activity-date', async function (assert) {
|
||||
this.item = new ActivityEntry({
|
||||
photoEventId: 'photo-1',
|
||||
photo: null,
|
||||
@@ -248,14 +248,14 @@ module('Integration | Component | activity-zap-item', function (hooks) {
|
||||
</template>
|
||||
);
|
||||
|
||||
const placeNameEl = this.element.querySelector('.zap-place-name');
|
||||
const dateEl = this.element.querySelector('.zap-date');
|
||||
const placeNameEl = this.element.querySelector('.activity-place-name');
|
||||
const dateEl = this.element.querySelector('.activity-date');
|
||||
|
||||
assert.ok(placeNameEl, 'zap-place-name element exists');
|
||||
assert.ok(dateEl, 'zap-date element exists');
|
||||
assert.ok(placeNameEl, 'activity-place-name element exists');
|
||||
assert.ok(dateEl, 'activity-date element exists');
|
||||
assert.ok(
|
||||
placeNameEl.textContent.includes('Café Central'),
|
||||
'Place name is in zap-place-name'
|
||||
'Place name is in activity-place-name'
|
||||
);
|
||||
assert.ok(dateEl.textContent.includes('hr ago'), 'Date contains hr ago');
|
||||
assert.notOk(
|
||||
@@ -290,7 +290,9 @@ module('Integration | Component | activity-zap-item', function (hooks) {
|
||||
</template>
|
||||
);
|
||||
|
||||
assert.dom('.zap-place-name').exists('zap-place-name element exists');
|
||||
assert.dom('.zap-date').hasText('1 hr ago', 'Date is still visible');
|
||||
assert
|
||||
.dom('.activity-place-name')
|
||||
.exists('activity-place-name element exists');
|
||||
assert.dom('.activity-date').hasText('1 hr ago', 'Date is still visible');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user