4797-workerNotificationManager #107
|
@ -13,5 +13,6 @@
|
|||
],
|
||||
"[vue]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
}
|
||||
},
|
||||
"cSpell.words": ["axios"]
|
||||
alexm marked this conversation as resolved
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
"test:unit:ci": "vitest run"
|
||||
},
|
||||
"dependencies": {
|
||||
"@quasar/cli": "^2.2.1",
|
||||
"@quasar/cli": "^2.3.0",
|
||||
"@quasar/extras": "^1.16.4",
|
||||
"axios": "^1.4.0",
|
||||
"chromium": "^3.0.3",
|
||||
|
|
|
@ -89,6 +89,7 @@ async function fetch(data) {
|
|||
watch(formData, () => (hasChanges.value = true), { deep: true });
|
||||
|
||||
emit('onFetch', data);
|
||||
return data;
|
||||
}
|
||||
|
||||
async function reset() {
|
||||
|
|
|
@ -249,9 +249,6 @@ function goToAction() {
|
|||
.grid-style-transition {
|
||||
transition: transform 0.28s, background-color 0.28s;
|
||||
}
|
||||
.maxwidth {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
<i18n>
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
<script setup>
|
||||
import { reactive, watch } from 'vue';
|
||||
|
||||
const customer = reactive({
|
||||
name: '',
|
||||
});
|
||||
|
||||
watch(() => customer.name);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<QPage class="q-pa-md">
|
||||
<QCard class="q-pa-md">
|
||||
<QForm @submit="onSubmit" @reset="onReset" class="q-gutter-md">
|
||||
<QInput
|
||||
filled
|
||||
v-model="customer.name"
|
||||
label="Your name *"
|
||||
hint="Name and surname"
|
||||
lazy-rules
|
||||
:rules="[(val) => (val && val.length > 0) || 'Please type something']"
|
||||
/>
|
||||
|
||||
<QInput
|
||||
filled
|
||||
type="number"
|
||||
v-model="age"
|
||||
label="Your age *"
|
||||
lazy-rules
|
||||
:rules="[
|
||||
(val) => (val !== null && val !== '') || 'Please type your age',
|
||||
(val) => (val > 0 && val < 100) || 'Please type a real age',
|
||||
]"
|
||||
/>
|
||||
|
||||
<div>
|
||||
<QBtn label="Submit" type="submit" color="primary" />
|
||||
<QBtn
|
||||
label="Reset"
|
||||
type="reset"
|
||||
color="primary"
|
||||
flat
|
||||
class="q-ml-sm"
|
||||
/>
|
||||
</div>
|
||||
</QForm>
|
||||
</QCard>
|
||||
</QPage>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.card {
|
||||
width: 100%;
|
||||
max-width: 60em;
|
||||
}
|
||||
</style>
|
|
@ -1,10 +1,12 @@
|
|||
<script setup>
|
||||
import axios from 'axios';
|
||||
import { useQuasar } from 'quasar';
|
||||
import { computed, onMounted, onUpdated, ref } from 'vue';
|
||||
import { computed, ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useRoute } from 'vue-router';
|
||||
|
||||
import CrudModel from 'components/CrudModel.vue';
|
||||
|
||||
const $props = defineProps({
|
||||
id: {
|
||||
type: Number,
|
||||
|
@ -12,131 +14,139 @@ const $props = defineProps({
|
|||
default: null,
|
||||
},
|
||||
});
|
||||
const entityId = computed(() => $props.id || route.params.id);
|
||||
|
||||
onMounted(() => fetch());
|
||||
onUpdated(() => fetch());
|
||||
|
||||
const route = useRoute();
|
||||
const { t } = useI18n();
|
||||
const quasar = useQuasar();
|
||||
|
||||
const notifications = ref([]);
|
||||
|
||||
async function fetch() {
|
||||
try {
|
||||
await axios
|
||||
.get(`NotificationSubscriptions/${entityId.value}/getList`)
|
||||
.then(async (res) => {
|
||||
if (res.data) {
|
||||
notifications.value = res.data;
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
async function disableNotification(notification) {
|
||||
await axios
|
||||
.delete(`NotificationSubscriptions/${notification.id}`)
|
||||
.catch(() => (notification.active = true))
|
||||
.then((res) => {
|
||||
if (res.data) {
|
||||
notification.id = null;
|
||||
notification.active = false;
|
||||
quasar.notify({
|
||||
type: 'positive',
|
||||
message: t('worker.notificationsManager.unsubscribed'),
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
const entityId = computed(() => $props.id || route.params.id);
|
||||
const URL_KEY = 'NotificationSubscriptions';
|
||||
const active = ref();
|
||||
const available = ref();
|
||||
|
||||
async function toggleNotification(notification) {
|
||||
try {
|
||||
if (!notification.active) {
|
||||
await disableNotification(notification);
|
||||
await axios.delete(`${URL_KEY}/${notification.id}`);
|
||||
swapEntry(active.value, available.value, notification.notificationFk);
|
||||
} else {
|
||||
await axios
|
||||
.post(`NotificationSubscriptions`, {
|
||||
const { data } = await axios.post(URL_KEY, {
|
||||
notificationFk: notification.notificationFk,
|
||||
userFk: entityId.value,
|
||||
})
|
||||
.catch(() => (notification.active = false))
|
||||
.then((res) => {
|
||||
if (res.data) {
|
||||
notification.id = res.data.id;
|
||||
});
|
||||
notification.id = data.id;
|
||||
|
||||
swapEntry(available.value, active.value, notification.notificationFk);
|
||||
}
|
||||
|
||||
quasar.notify({
|
||||
type: 'positive',
|
||||
message: t('worker.notificationsManager.subscribed'),
|
||||
message: t(
|
||||
`worker.notificationsManager.${notification.active ? '' : 'un'}subscribed`
|
||||
),
|
||||
});
|
||||
} catch {
|
||||
notification.active = !notification.active;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const swapEntry = (from, to, key) => {
|
||||
const element = from.get(key);
|
||||
to.set(key, element);
|
||||
from.delete(key);
|
||||
};
|
||||
|
||||
function setNotifications(data) {
|
||||
active.value = new Map(data.active);
|
||||
available.value = new Map(data.available);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<QPage>
|
||||
<QCard class="q-pa-md">
|
||||
<QList>
|
||||
<div
|
||||
v-show="
|
||||
notifications.filter(
|
||||
(notification) => notification.active == true
|
||||
).length
|
||||
"
|
||||
<CrudModel
|
||||
auto-load
|
||||
alexm marked this conversation as resolved
jsegarra
commented
NotificationSubscriptions aparece 4 veces en este fichero, como verias de hacer una const para que sólo esté 1 vez? NotificationSubscriptions aparece 4 veces en este fichero, como verias de hacer una const para que sólo esté 1 vez?
|
||||
:data-key="URL_KEY"
|
||||
:url="`${URL_KEY}/${entityId}/getList`"
|
||||
:default-reset="false"
|
||||
:default-remove="false"
|
||||
:default-save="false"
|
||||
@on-fetch="setNotifications"
|
||||
>
|
||||
<QItemLabel header class="text-h6">
|
||||
{{ t('worker.notificationsManager.activeNotifications') }}
|
||||
</QItemLabel>
|
||||
<QItem>
|
||||
<template #body>
|
||||
<div
|
||||
v-for="notification in notifications.filter(
|
||||
(notification) => notification.active == true
|
||||
)"
|
||||
:key="notification.id"
|
||||
v-for="(notifications, index) in [
|
||||
[...active.values()],
|
||||
[...available.values()],
|
||||
]"
|
||||
:key="notifications"
|
||||
>
|
||||
<QChip
|
||||
:key="notification.id"
|
||||
:label="notification.name"
|
||||
text-color="white"
|
||||
color="primary"
|
||||
class="q-mr-sm"
|
||||
removable
|
||||
@remove="disableNotification(notification)"
|
||||
/>
|
||||
</div>
|
||||
</QItem>
|
||||
</div>
|
||||
<div v-show="notifications.length">
|
||||
<QItemLabel header class="text-h6">
|
||||
{{ t('worker.notificationsManager.availableNotifications') }}
|
||||
</QItemLabel>
|
||||
<div class="row">
|
||||
<QItem
|
||||
class="col-3"
|
||||
:key="notification.notificationFk"
|
||||
<QList class="notificationList">
|
||||
<TransitionGroup>
|
||||
<QCard
|
||||
v-for="notification in notifications"
|
||||
:key="notification.notificationFk"
|
||||
class="q-pa-md"
|
||||
>
|
||||
<QItem>
|
||||
<QItemSection avatar>
|
||||
<QBtn
|
||||
round
|
||||
icon="mail"
|
||||
:color="notification.active ? 'green' : 'grey'"
|
||||
/>
|
||||
</QItemSection>
|
||||
<QItemSection>
|
||||
<QItemLabel>{{ notification.name }}</QItemLabel>
|
||||
<QItemLabel caption>{{
|
||||
notification.description
|
||||
}}</QItemLabel>
|
||||
<QItemLabel caption>
|
||||
{{ notification.description }}
|
||||
</QItemLabel>
|
||||
</QItemSection>
|
||||
<QItemSection side top>
|
||||
<QToggle
|
||||
checked-icon="check"
|
||||
unchecked-icon="close"
|
||||
indeterminate-icon="block"
|
||||
v-model="notification.active"
|
||||
color="green"
|
||||
@update:model-value="toggleNotification(notification)"
|
||||
/>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
</div>
|
||||
</div>
|
||||
</QList>
|
||||
</QCard>
|
||||
</QPage>
|
||||
</TransitionGroup>
|
||||
</QList>
|
||||
<QSeparator
|
||||
color="primary"
|
||||
class="q-my-lg"
|
||||
v-if="!index && available.size && active.size"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</CrudModel>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.notificationList {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
grid-gap: 10px;
|
||||
|
||||
.v-enter-active,
|
||||
.v-leave-active {
|
||||
transition: opacity 0.5s ease;
|
||||
}
|
||||
|
||||
.v-enter-from,
|
||||
.v-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: $breakpoint-md) {
|
||||
.notificationList {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: $breakpoint-xs) {
|
||||
.notificationList {
|
||||
grid-template-columns: repeat(1, 1fr);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -10,7 +10,7 @@ export default {
|
|||
component: RouterView,
|
||||
redirect: { name: 'CustomerMain' },
|
||||
menus: {
|
||||
main: ['CustomerList', 'CustomerPayments', 'CustomerCreate'],
|
||||
main: ['CustomerList', 'CustomerPayments'],
|
||||
card: ['CustomerBasicData'],
|
||||
},
|
||||
children: [
|
||||
|
@ -27,7 +27,7 @@ export default {
|
|||
title: 'list',
|
||||
icon: 'view_list',
|
||||
},
|
||||
component: () => import('src/pages/Customer/CustomerList.vue')
|
||||
component: () => import('src/pages/Customer/CustomerList.vue'),
|
||||
},
|
||||
{
|
||||
path: 'payments',
|
||||
|
@ -36,17 +36,7 @@ export default {
|
|||
title: 'webPayments',
|
||||
icon: 'vn:onlinepayment',
|
||||
},
|
||||
component: () => import('src/pages/Customer/CustomerPayments.vue')
|
||||
},
|
||||
{
|
||||
path: 'create',
|
||||
name: 'CustomerCreate',
|
||||
meta: {
|
||||
title: 'createCustomer',
|
||||
icon: 'vn:addperson',
|
||||
roles: ['developer'],
|
||||
},
|
||||
component: () => import('src/pages/Customer/CustomerCreate.vue'),
|
||||
component: () => import('src/pages/Customer/CustomerPayments.vue'),
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -63,7 +53,8 @@ export default {
|
|||
title: 'summary',
|
||||
icon: 'launch',
|
||||
},
|
||||
component: () => import('src/pages/Customer/Card/CustomerSummary.vue'),
|
||||
component: () =>
|
||||
import('src/pages/Customer/Card/CustomerSummary.vue'),
|
||||
},
|
||||
{
|
||||
path: 'basic-data',
|
||||
|
@ -72,7 +63,8 @@ export default {
|
|||
title: 'basicData',
|
||||
icon: 'vn:settings',
|
||||
},
|
||||
component: () => import('src/pages/Customer/Card/CustomerBasicData.vue'),
|
||||
component: () =>
|
||||
import('src/pages/Customer/Card/CustomerBasicData.vue'),
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
|
@ -11,7 +11,7 @@ export default {
|
|||
redirect: { name: 'WorkerMain' },
|
||||
menus: {
|
||||
main: ['WorkerList'],
|
||||
// card: ['WorkerNotificationsManager'],
|
||||
card: ['WorkerNotificationsManager'],
|
||||
},
|
||||
children: [
|
||||
{
|
||||
|
@ -46,15 +46,16 @@ export default {
|
|||
},
|
||||
component: () => import('src/pages/Worker/Card/WorkerSummary.vue'),
|
||||
},
|
||||
// {
|
||||
// name: 'WorkerNotificationsManager',
|
||||
// path: 'notifications',
|
||||
// meta: {
|
||||
// title: 'notifications',
|
||||
// icon: 'notifications',
|
||||
// },
|
||||
// component: () => import('src/pages/Worker/Card/WorkerNotificationsManager.vue'),
|
||||
// },
|
||||
{
|
||||
name: 'WorkerNotificationsManager',
|
||||
path: 'notifications',
|
||||
meta: {
|
||||
title: 'notifications',
|
||||
icon: 'notifications',
|
||||
},
|
||||
component: () =>
|
||||
import('src/pages/Worker/Card/WorkerNotificationsManager.vue'),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
|
|
@ -1,36 +1,79 @@
|
|||
xdescribe('WorkerNotificationsManager', () => {
|
||||
describe('WorkerNotificationsManager', () => {
|
||||
const salesPersonId = 18;
|
||||
const developerId = 9;
|
||||
|
||||
const activeList = ':nth-child(1) > .q-list';
|
||||
const availableList = ':nth-child(2) > .q-list';
|
||||
const firstActiveNotification =
|
||||
':nth-child(1) > .q-list > :nth-child(1) > .q-item > .q-toggle > .q-toggle__inner';
|
||||
const firstAvailableNotification =
|
||||
':nth-child(2) > .q-list > :nth-child(1) > .q-item > .q-toggle > .q-toggle__inner';
|
||||
|
||||
beforeEach(() => {
|
||||
const workerId = 1110;
|
||||
cy.viewport(1280, 720);
|
||||
});
|
||||
|
||||
it('should throw an error if you try to change a notification that is not yours', () => {
|
||||
cy.login('developer');
|
||||
cy.visit(`/#/worker/${salesPersonId}/notifications`);
|
||||
cy.get(firstAvailableNotification).click();
|
||||
cy.notificationHas(
|
||||
'.q-notification__message',
|
||||
'The notification subscription of this worker cant be modified'
|
||||
);
|
||||
});
|
||||
|
||||
it('should active a notification that is yours', () => {
|
||||
cy.login('developer');
|
||||
cy.visit(`/#/worker/${developerId}/notifications`);
|
||||
cy.waitForElement(activeList);
|
||||
cy.waitForElement(availableList);
|
||||
|
||||
cy.get(activeList)
|
||||
.children()
|
||||
.its('length')
|
||||
.then((beforeSize) => {
|
||||
cy.get(firstAvailableNotification).click();
|
||||
cy.get(activeList)
|
||||
.children()
|
||||
.should('have.length', beforeSize + 1);
|
||||
});
|
||||
});
|
||||
|
||||
it('should deactivate a notification that is yours', () => {
|
||||
cy.login('developer');
|
||||
cy.visit(`/#/worker/${developerId}/notifications`);
|
||||
cy.waitForElement(activeList);
|
||||
cy.waitForElement(availableList);
|
||||
|
||||
cy.get(availableList)
|
||||
.children()
|
||||
.its('length')
|
||||
.then((beforeSize) => {
|
||||
cy.get(firstActiveNotification).click();
|
||||
cy.get(availableList)
|
||||
.children()
|
||||
.should('have.length', beforeSize + 1);
|
||||
});
|
||||
});
|
||||
|
||||
it('should active a notification if you are their boss', () => {
|
||||
cy.login('salesBoss');
|
||||
cy.visit(`/#/worker/${workerId}/notifications`);
|
||||
});
|
||||
cy.visit(`/#/worker/${salesPersonId}/notifications`);
|
||||
cy.waitForElement(activeList);
|
||||
cy.waitForElement(availableList);
|
||||
|
||||
it('should unsubscribe 2 notifications, check the unsubscription has been saved, subscribe to other one and should check the data has been saved', () => {
|
||||
cy.get('.q-chip').should('have.length', 3);
|
||||
cy.get('.q-toggle__thumb').eq(0).click();
|
||||
cy.get('.q-notification__message').should(
|
||||
'have.text',
|
||||
'Unsubscribed from the notification'
|
||||
);
|
||||
cy.get('.q-chip > .q-icon').eq(0).click();
|
||||
cy.get(activeList)
|
||||
.children()
|
||||
.its('length')
|
||||
.then((beforeSize) => {
|
||||
cy.get(firstAvailableNotification).click();
|
||||
cy.get(activeList)
|
||||
.children()
|
||||
.should('have.length', beforeSize + 1);
|
||||
|
||||
cy.reload();
|
||||
|
||||
cy.get('.q-chip').should('have.length', 1);
|
||||
cy.get('.q-toggle__thumb').should('have.length', 3).eq(0).click();
|
||||
cy.get('.q-notification__message').should(
|
||||
'have.text',
|
||||
'Subscribed to the notification'
|
||||
);
|
||||
cy.get('.q-toggle__thumb').should('have.length', 3).eq(1).click();
|
||||
cy.get('.q-notification__message').should(
|
||||
'have.text',
|
||||
'Subscribed to the notification'
|
||||
);
|
||||
|
||||
cy.reload();
|
||||
|
||||
cy.get('.q-chip').should('have.length', 3);
|
||||
//Rollback
|
||||
cy.get(firstActiveNotification).click();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -91,6 +91,10 @@ Cypress.Commands.add('clickConfirm', () => {
|
|||
cy.get('.q-btn--unelevated > .q-btn__content > .block').click();
|
||||
});
|
||||
|
||||
Cypress.Commands.add('notificationHas', (selector, text) => {
|
||||
cy.get(selector).should('have.text', text);
|
||||
});
|
||||
|
||||
Cypress.Commands.add('fillRow', (rowSelector, data) => {
|
||||
// Usar el selector proporcionado para obtener la fila deseada
|
||||
cy.waitForElement('tbody');
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
import { vi, describe, expect, it, beforeAll, afterEach } from 'vitest';
|
||||
import { createWrapper, axios } from 'app/test/vitest/helper';
|
||||
import { createWrapper } from 'app/test/vitest/helper';
|
||||
import WorkerNotificationsManager from 'src/pages/Worker/Card/WorkerNotificationsManager.vue';
|
||||
import { ref } from 'vue';
|
||||
|
||||
describe('WorkerNotificationsManager', () => {
|
||||
let vm;
|
||||
const entityId = 1110;
|
||||
|
||||
beforeAll(() => {
|
||||
vm = createWrapper(WorkerNotificationsManager, {
|
||||
propsData: {
|
||||
id: entityId,
|
||||
global: {
|
||||
stubs: ['CrudModel'],
|
||||
},
|
||||
}).vm;
|
||||
});
|
||||
|
@ -18,83 +18,16 @@ describe('WorkerNotificationsManager', () => {
|
|||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('fetch()', () => {
|
||||
it('should fetch notification subscriptions and role mappings', async () => {
|
||||
vi.spyOn(axios, 'get')
|
||||
.mockResolvedValueOnce({
|
||||
data: [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Name 1',
|
||||
description: 'Description 1',
|
||||
notificationFk: 1,
|
||||
active: true
|
||||
},
|
||||
],
|
||||
});
|
||||
await vm.fetch();
|
||||
describe('swapEntry()', () => {
|
||||
it('should swap notification', async () => {
|
||||
const from = ref(new Map());
|
||||
const to = ref(new Map());
|
||||
from.value.set(1, { notificationFk: 1 });
|
||||
to.value.set(2, { notificationFk: 2 });
|
||||
|
||||
expect(axios.get).toHaveBeenCalledWith(`NotificationSubscriptions/${entityId}/getList`);
|
||||
expect(vm.notifications).toEqual([
|
||||
{
|
||||
id: 1,
|
||||
notificationFk: 1,
|
||||
name: 'Name 1',
|
||||
description: 'Description 1',
|
||||
active: true,
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('disableNotification()', () => {
|
||||
it('should disable the notification', async () => {
|
||||
vi.spyOn(axios, 'delete').mockResolvedValue({ data: { count: 1 } });
|
||||
vi.spyOn(vm.quasar, 'notify');
|
||||
const subscriptionId = 1;
|
||||
vm.notifications = [{ id: 1, active: true }];
|
||||
|
||||
await vm.disableNotification(vm.notifications[0]);
|
||||
|
||||
expect(axios.delete).toHaveBeenCalledWith(
|
||||
`NotificationSubscriptions/${subscriptionId}`
|
||||
);
|
||||
expect(vm.notifications[0].id).toBeNull();
|
||||
expect(vm.notifications[0].id).toBeFalsy();
|
||||
expect(vm.quasar.notify).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ type: 'positive' })
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('toggleNotification()', () => {
|
||||
it('should activate the notification', async () => {
|
||||
vi.spyOn(axios, 'post').mockResolvedValue({
|
||||
data: { id: 1, notificationFk: 1 },
|
||||
});
|
||||
vm.notifications = [{ id: null, active: true, notificationFk: 1 }];
|
||||
|
||||
await vm.toggleNotification(vm.notifications[0]);
|
||||
|
||||
expect(axios.post).toHaveBeenCalledWith('NotificationSubscriptions', {
|
||||
notificationFk: 1,
|
||||
userFk: entityId,
|
||||
});
|
||||
expect(vm.notifications[0].id).toBe(1);
|
||||
expect(vm.notifications[0].active).toBeTruthy();
|
||||
expect(vm.quasar.notify).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ type: 'positive' })
|
||||
);
|
||||
});
|
||||
|
||||
it('should disable the notification', async () => {
|
||||
vi.spyOn(vm, 'disableNotification');
|
||||
vm.notifications = [{ id: 1, active: false, notificationFk: 1 }];
|
||||
|
||||
await vm.toggleNotification(vm.notifications[0]);
|
||||
|
||||
expect(vm.notifications[0].id).toBe(null);
|
||||
expect(vm.notifications[0].active).toBeFalsy();
|
||||
await vm.swapEntry(from.value, to.value, 1);
|
||||
expect(to.value.size).toBe(2);
|
||||
expect(from.value.size).toBe(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue
Este archivo seguro que hay que subirlo?
Creo que se puede poner a nivel de usuario.
Pero por si alguien mas lo usa. Que todos tengamos que darle la primera vez a que no te lo marque
Creo que se puede poner a nivel de usuario.
Pero por si alguien mas lo usa. Que todos tengamos que darle la primera vez a que no te lo marque