adapt jasmine specs to the new structure
This commit is contained in:
parent
a3477b7691
commit
200887ca45
3 changed files with 234 additions and 235 deletions
|
|
@ -1,76 +1,252 @@
|
||||||
|
/* Copyright (c) 2010-2012, Diaspora Inc. This file is
|
||||||
|
* licensed under the Affero General Public License version 3 or later. See
|
||||||
|
* the COPYRIGHT file.
|
||||||
|
*/
|
||||||
|
|
||||||
describe("app.views.Publisher", function() {
|
describe("app.views.Publisher", function() {
|
||||||
beforeEach(function() {
|
context("plain publisher", function() {
|
||||||
// should be jasmine helper
|
|
||||||
loginAs({name: "alice", avatar : {small : "http://avatar.com/photo.jpg"}});
|
|
||||||
|
|
||||||
spec.loadFixture("aspects_index");
|
|
||||||
this.view = new app.views.Publisher();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("#open", function() {
|
|
||||||
it("removes the 'closed' class from the publisher element", function() {
|
|
||||||
expect($(this.view.el)).toHaveClass("closed");
|
|
||||||
this.view.open($.Event());
|
|
||||||
expect($(this.view.el)).not.toHaveClass("closed");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("#close", function() {
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
this.view.open($.Event());
|
// should be jasmine helper
|
||||||
|
loginAs({name: "alice", avatar : {small : "http://avatar.com/photo.jpg"}});
|
||||||
|
|
||||||
|
spec.loadFixture("aspects_index");
|
||||||
|
this.view = new app.views.Publisher();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("removes the 'active' class from the publisher element", function(){
|
describe("#open", function() {
|
||||||
this.view.close($.Event());
|
it("removes the 'closed' class from the publisher element", function() {
|
||||||
expect($(this.view.el)).toHaveClass("closed");
|
expect($(this.view.el)).toHaveClass("closed");
|
||||||
})
|
this.view.open($.Event());
|
||||||
|
expect($(this.view.el)).not.toHaveClass("closed");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it("resets the element's height", function() {
|
describe("#close", function() {
|
||||||
$(this.view.el).find("#status_message_fake_text").height(100);
|
beforeEach(function() {
|
||||||
this.view.close($.Event());
|
this.view.open($.Event());
|
||||||
expect($(this.view.el).find("#status_message_fake_text").attr("style")).not.toContain("height");
|
});
|
||||||
|
|
||||||
|
it("removes the 'active' class from the publisher element", function(){
|
||||||
|
this.view.close($.Event());
|
||||||
|
expect($(this.view.el)).toHaveClass("closed");
|
||||||
|
})
|
||||||
|
|
||||||
|
it("resets the element's height", function() {
|
||||||
|
$(this.view.el).find("#status_message_fake_text").height(100);
|
||||||
|
this.view.close($.Event());
|
||||||
|
expect($(this.view.el).find("#status_message_fake_text").attr("style")).not.toContain("height");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("#clear", function() {
|
||||||
|
it("calls close", function(){
|
||||||
|
spyOn(this.view, "close");
|
||||||
|
|
||||||
|
this.view.clear($.Event());
|
||||||
|
expect(this.view.close).toHaveBeenCalled();
|
||||||
|
})
|
||||||
|
|
||||||
|
it("clears all textareas", function(){
|
||||||
|
_.each(this.view.$("textarea"), function(element){
|
||||||
|
$(element).val('this is some stuff');
|
||||||
|
expect($(element).val()).not.toBe("");
|
||||||
|
});
|
||||||
|
|
||||||
|
this.view.clear($.Event());
|
||||||
|
|
||||||
|
_.each(this.view.$("textarea"), function(element){
|
||||||
|
expect($(element).val()).toBe("");
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
it("removes all photos from the dropzone area", function(){
|
||||||
|
var self = this;
|
||||||
|
_.times(3, function(){
|
||||||
|
self.view.el_photozone.append($("<li>"))
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(this.view.el_photozone.html()).not.toBe("");
|
||||||
|
this.view.clear($.Event());
|
||||||
|
expect(this.view.el_photozone.html()).toBe("");
|
||||||
|
})
|
||||||
|
|
||||||
|
it("removes all photo values appended by the photo uploader", function(){
|
||||||
|
$(this.view.el).prepend("<input name='photos[]' value='3'/>")
|
||||||
|
var photoValuesInput = this.view.$("input[name='photos[]']");
|
||||||
|
|
||||||
|
photoValuesInput.val("3")
|
||||||
|
this.view.clear($.Event());
|
||||||
|
expect(this.view.$("input[name='photos[]']").length).toBe(0);
|
||||||
|
})
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("#clear", function() {
|
context("#toggleService", function(){
|
||||||
it("calls close", function(){
|
beforeEach( function(){
|
||||||
spyOn(this.view, "close");
|
spec.loadFixture('aspects_index_services');
|
||||||
|
this.view = new app.views.Publisher();
|
||||||
|
});
|
||||||
|
|
||||||
this.view.clear($.Event());
|
it("toggles the 'dim' class on a clicked item", function() {
|
||||||
expect(this.view.close);
|
var first = $(".service_icon").eq(0);
|
||||||
})
|
var second = $(".service_icon").eq(1);
|
||||||
|
|
||||||
it("clears all textareas", function(){
|
expect(first.hasClass('dim')).toBeTruthy();
|
||||||
_.each(this.view.$("textarea"), function(element){
|
expect(second.hasClass('dim')).toBeTruthy();
|
||||||
$(element).val('this is some stuff');
|
|
||||||
expect($(element).val()).not.toBe("");
|
first.trigger('click');
|
||||||
|
|
||||||
|
expect(first.hasClass('dim')).toBeFalsy();
|
||||||
|
expect(second.hasClass('dim')).toBeTruthy();
|
||||||
|
|
||||||
|
first.trigger('click');
|
||||||
|
|
||||||
|
expect(first.hasClass('dim')).toBeTruthy();
|
||||||
|
expect(second.hasClass('dim')).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("#_createCounter", function() {
|
||||||
|
it("gets called in when you toggle service icons", function(){
|
||||||
|
spyOn(this.view, '_createCounter');
|
||||||
|
$(".service_icon").first().trigger('click');
|
||||||
|
expect(this.view._createCounter).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.view.clear($.Event());
|
it("removes the 'old' .counter span", function(){
|
||||||
|
spyOn($.fn, "remove");
|
||||||
_.each(this.view.$("textarea"), function(element){
|
$(".service_icon").first().trigger('click');
|
||||||
expect($(element).val()).toBe("");
|
expect($.fn.remove).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
it("removes all photos from the dropzone area", function(){
|
describe("#_toggleServiceField", function() {
|
||||||
var self = this;
|
it("gets called when you toggle service icons", function(){
|
||||||
_.times(3, function(){
|
spyOn(this.view, '_toggleServiceField');
|
||||||
self.view.$("#photodropzone").append($("<li>"))
|
$(".service_icon").first().trigger('click');
|
||||||
|
expect(this.view._toggleServiceField).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(this.view.$("#photodropzone").html()).not.toBe("");
|
it("toggles the hidden input field", function(){
|
||||||
this.view.clear($.Event());
|
expect($('input[name="services[]"]').length).toBe(0);
|
||||||
expect(this.view.$("#photodropzone").html()).toBe("");
|
$(".service_icon").first().trigger('click');
|
||||||
})
|
expect($('input[name="services[]"]').length).toBe(1);
|
||||||
|
$(".service_icon").first().trigger('click');
|
||||||
|
expect($('input[name="services[]"]').length).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
it("removes all photo values appended by the photo uploader", function(){
|
it("toggles the correct input", function() {
|
||||||
$(this.view.el).prepend("<input name='photos[]' value='3'/>")
|
var first = $(".service_icon").eq(0);
|
||||||
var photoValuesInput = this.view.$("input[name='photos[]']");
|
var second = $(".service_icon").eq(1);
|
||||||
|
|
||||||
photoValuesInput.val("3")
|
first.trigger('click');
|
||||||
this.view.clear($.Event());
|
second.trigger('click');
|
||||||
expect(this.view.$("input[name='photos[]']").length).toBe(0);
|
|
||||||
})
|
expect($('input[name="services[]"]').length).toBe(2);
|
||||||
|
|
||||||
|
first.trigger('click');
|
||||||
|
|
||||||
|
var prov1 = first.attr('id');
|
||||||
|
var prov2 = second.attr('id');
|
||||||
|
|
||||||
|
expect($('input[name="services[]"][value="'+prov1+'"]').length).toBe(0);
|
||||||
|
expect($('input[name="services[]"][value="'+prov2+'"]').length).toBe(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
context("aspect selection", function(){
|
||||||
|
beforeEach( function(){
|
||||||
|
spec.loadFixture('status_message_new');
|
||||||
|
|
||||||
|
this.radio_els = $('#publisher .dropdown li.radio');
|
||||||
|
this.check_els = $('#publisher .dropdown li.aspect_selector');
|
||||||
|
|
||||||
|
this.view = new app.views.Publisher();
|
||||||
|
this.view.open();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("initializes with 'all_aspects'", function(){
|
||||||
|
expect(this.radio_els.first().hasClass('selected')).toBeFalsy();
|
||||||
|
expect(this.radio_els.last().hasClass('selected')).toBeTruthy();
|
||||||
|
|
||||||
|
_.each(this.check_els, function(el){
|
||||||
|
expect($(el).hasClass('selected')).toBeFalsy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("toggles the selected entry visually", function(){
|
||||||
|
this.check_els.last().trigger('click');
|
||||||
|
|
||||||
|
_.each(this.radio_els, function(el){
|
||||||
|
expect($(el).hasClass('selected')).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(this.check_els.first().hasClass('selected')).toBeFalsy();
|
||||||
|
expect(this.check_els.last().hasClass('selected')).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("#_updateSelectedAspectIds", function(){
|
||||||
|
beforeEach(function(){
|
||||||
|
this.li = $('<li data-aspect_id="42" />');
|
||||||
|
this.view.$('.dropdown_list').append(this.li);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("gets called when aspects are selected", function(){
|
||||||
|
spyOn(this.view, "_updateSelectedAspectIds");
|
||||||
|
this.check_els.last().trigger('click');
|
||||||
|
expect(this.view._updateSelectedAspectIds).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("removes a previous selection and inserts the current one", function() {
|
||||||
|
var selected = this.view.$('input[name="aspect_ids[]"]');
|
||||||
|
expect(selected.length).toBe(1);
|
||||||
|
expect(selected.first().val()).toBe('all_aspects');
|
||||||
|
|
||||||
|
this.li.trigger('click');
|
||||||
|
|
||||||
|
selected = this.view.$('input[name="aspect_ids[]"]');
|
||||||
|
expect(selected.length).toBe(1);
|
||||||
|
expect(selected.first().val()).toBe('42');
|
||||||
|
});
|
||||||
|
|
||||||
|
it("toggles the same item", function() {
|
||||||
|
expect(this.view.$('input[name="aspect_ids[]"]').length).toBe(1);
|
||||||
|
|
||||||
|
this.li.trigger('click');
|
||||||
|
expect(this.view.$('input[name="aspect_ids[]"]').length).toBe(1);
|
||||||
|
|
||||||
|
this.li.trigger('click');
|
||||||
|
expect(this.view.$('input[name="aspect_ids[]"]').length).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("keeps other fields with different values", function() {
|
||||||
|
var li2 = $("<li data-aspect_id=99></li>");
|
||||||
|
this.view.$('.dropdown_list').append(li2);
|
||||||
|
|
||||||
|
this.li.trigger('click');
|
||||||
|
expect(this.view.$('input[name="aspect_ids[]"]').length).toBe(1);
|
||||||
|
|
||||||
|
li2.trigger('click');
|
||||||
|
expect(this.view.$('input[name="aspect_ids[]"]').length).toBe(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("#_addHiddenAspectInput", function(){
|
||||||
|
it("gets called when aspects are selected", function(){
|
||||||
|
spyOn(this.view, "_addHiddenAspectInput");
|
||||||
|
this.check_els.last().trigger('click');
|
||||||
|
expect(this.view._addHiddenAspectInput).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("adds a hidden input to the form", function(){
|
||||||
|
var id = 42;
|
||||||
|
|
||||||
|
this.view._addHiddenAspectInput(id);
|
||||||
|
var input = this.view.$('input[name="aspect_ids[]"][value="'+id+'"]');
|
||||||
|
|
||||||
|
expect(input.length).toBe(1);
|
||||||
|
expect(input.val()).toBe('42');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,11 @@ describe("bookmarklet", function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('verifies the publisher is loaded', function(){
|
it('verifies the publisher is loaded', function(){
|
||||||
expect(typeof Publisher === "object").toBeTruthy();
|
expect(typeof app.publisher === "object").toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('verifies we are using the bookmarklet', function(){
|
it('verifies we are using the bookmarklet', function(){
|
||||||
expect(Publisher.bookmarklet).toBeTruthy();
|
expect(app.publisher.options.bookmarklet).toBeTruthy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,177 +0,0 @@
|
||||||
/* Copyright (c) 2010-2011, Diaspora Inc. This file is
|
|
||||||
* licensed under the Affero General Public License version 3 or later. See
|
|
||||||
* the COPYRIGHT file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
describe("Publisher", function() {
|
|
||||||
|
|
||||||
Publisher.open = function(){ this.form().removeClass("closed"); }
|
|
||||||
|
|
||||||
describe("toggleCounter", function(){
|
|
||||||
beforeEach( function(){
|
|
||||||
spec.loadFixture('aspects_index_services');
|
|
||||||
});
|
|
||||||
|
|
||||||
it("gets called in when you toggle service icons", function(){
|
|
||||||
spyOn(Publisher, 'createCounter');
|
|
||||||
Publisher.toggleServiceField($(".service_icon").first());
|
|
||||||
expect(Publisher.createCounter).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("removes the .counter span", function(){
|
|
||||||
spyOn($.fn, "remove");
|
|
||||||
Publisher.createCounter($(".service_icon").first());
|
|
||||||
expect($.fn.remove).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("bindAspectToggles", function() {
|
|
||||||
beforeEach( function(){
|
|
||||||
spec.loadFixture('status_message_new');
|
|
||||||
Publisher.open();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('gets called on initialize', function(){
|
|
||||||
spyOn(Publisher, 'bindAspectToggles');
|
|
||||||
Publisher.initialize();
|
|
||||||
expect(Publisher.bindAspectToggles).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('correctly initializes an all_aspects state', function(){
|
|
||||||
Publisher.initialize();
|
|
||||||
|
|
||||||
expect($("#publisher .dropdown .dropdown_list li.radio").first().hasClass("selected")).toBeFalsy();
|
|
||||||
expect($("#publisher .dropdown .dropdown_list li.radio").last().hasClass("selected")).toBeTruthy();
|
|
||||||
|
|
||||||
$.each($("#publihser .dropdown .dropdown_list li.aspect_selector"), function(index, element){
|
|
||||||
expect($(element).hasClass("selected")).toBeFalsy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('toggles selected only on the clicked icon', function(){
|
|
||||||
Publisher.initialize();
|
|
||||||
|
|
||||||
$("#publisher .dropdown .dropdown_list li.aspect_selector").last().click();
|
|
||||||
|
|
||||||
$.each($("#publisher .dropdown .dropdown_list li.radio"), function(index, element){
|
|
||||||
expect($(element).hasClass("selected")).toBeFalsy();
|
|
||||||
});
|
|
||||||
|
|
||||||
expect($("#publisher .dropdown .dropdown_list li.aspect_selector").first().hasClass("selected")).toBeFalsy();
|
|
||||||
expect($("#publisher .dropdown .dropdown_list li.aspect_selector").last().hasClass("selected")).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('calls toggleAspectIds with the clicked element', function(){
|
|
||||||
spyOn(Publisher, 'toggleAspectIds');
|
|
||||||
Publisher.bindAspectToggles();
|
|
||||||
var aspectBadge = $("#publisher .dropdown .dropdown_list li").last();
|
|
||||||
aspectBadge.click();
|
|
||||||
expect(Publisher.toggleAspectIds.mostRecentCall.args[0].get(0)).toEqual(aspectBadge.get(0));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('toggleAspectIds', function(){
|
|
||||||
beforeEach( function(){
|
|
||||||
spec.loadFixture('status_message_new');
|
|
||||||
li = $("<li data-aspect_id=42></li>");
|
|
||||||
});
|
|
||||||
|
|
||||||
it('adds a hidden field to the form if there is not one already', function(){
|
|
||||||
expect($('#publisher [name="aspect_ids[]"]').length).toBe(1);
|
|
||||||
expect($('#publisher [name="aspect_ids[]"]').last().attr('value')).toBe('all_aspects');
|
|
||||||
Publisher.toggleAspectIds(li);
|
|
||||||
expect($('#publisher [name="aspect_ids[]"]').length).toBe(1);
|
|
||||||
expect($('#publisher [name="aspect_ids[]"]').last().attr('value')).toBe('42');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('removes the hidden field if its already there', function() {
|
|
||||||
expect($('#publisher [name="aspect_ids[]"]').length).toBe(1);
|
|
||||||
|
|
||||||
Publisher.toggleAspectIds(li);
|
|
||||||
expect($('#publisher [name="aspect_ids[]"]').length).toBe(1);
|
|
||||||
|
|
||||||
Publisher.toggleAspectIds(li);
|
|
||||||
expect($('#publisher [name="aspect_ids[]"]').length).toBe(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('does not remove a hidden field with a different value', function() {
|
|
||||||
var li2 = $("<li data-aspect_id=99></li>");
|
|
||||||
|
|
||||||
Publisher.toggleAspectIds(li);
|
|
||||||
expect($('#publisher [name="aspect_ids[]"]').length).toBe(1);
|
|
||||||
|
|
||||||
Publisher.toggleAspectIds(li2);
|
|
||||||
expect($('#publisher [name="aspect_ids[]"]').length).toBe(2);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("bindServiceIcons", function() {
|
|
||||||
beforeEach( function(){
|
|
||||||
spec.loadFixture('aspects_index_services');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('gets called on initialize', function(){
|
|
||||||
spyOn(Publisher, 'bindServiceIcons');
|
|
||||||
Publisher.initialize();
|
|
||||||
expect(Publisher.bindServiceIcons).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('toggles dim only on the clicked icon', function(){
|
|
||||||
expect($(".service_icon#facebook").hasClass("dim")).toBeTruthy();
|
|
||||||
expect($(".service_icon#twitter").hasClass("dim")).toBeTruthy();
|
|
||||||
|
|
||||||
Publisher.bindServiceIcons();
|
|
||||||
$(".service_icon#facebook").click();
|
|
||||||
|
|
||||||
expect($(".service_icon#facebook").hasClass("dim")).toBeFalsy();
|
|
||||||
expect($(".service_icon#twitter").hasClass("dim")).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('binds to the services icons and toggles the hidden field', function(){
|
|
||||||
spyOn(Publisher, 'toggleServiceField');
|
|
||||||
Publisher.bindServiceIcons();
|
|
||||||
$(".service_icon#facebook").click();
|
|
||||||
|
|
||||||
expect(Publisher.toggleServiceField).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('toggleServiceField', function(){
|
|
||||||
beforeEach( function(){
|
|
||||||
spec.loadFixture('aspects_index_services');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('adds a hidden field to the form if there is not one already', function(){
|
|
||||||
expect($('#publisher [name="services[]"]').length).toBe(0);
|
|
||||||
Publisher.toggleServiceField($(".service_icon#facebook").first());
|
|
||||||
expect($('#publisher [name="services[]"]').length).toBe(1);
|
|
||||||
expect($('#publisher [name="services[]"]').attr('value')).toBe("facebook");
|
|
||||||
});
|
|
||||||
|
|
||||||
it('removes the hidden field if its already there', function() {
|
|
||||||
Publisher.toggleServiceField($(".service_icon#facebook").first());
|
|
||||||
expect($('#publisher [name="services[]"]').length).toBe(1);
|
|
||||||
|
|
||||||
Publisher.toggleServiceField($(".service_icon#facebook").first());
|
|
||||||
expect($('#publisher [name="services[]"]').length).toBe(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('does not remove a hidden field with a different value', function() {
|
|
||||||
Publisher.toggleServiceField($(".service_icon#facebook").first());
|
|
||||||
expect($('#publisher [name="services[]"]').length).toBe(1);
|
|
||||||
|
|
||||||
Publisher.toggleServiceField($(".service_icon#twitter").first());
|
|
||||||
expect($('#publisher [name="services[]"]').length).toBe(2);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("input", function(){
|
|
||||||
beforeEach(function(){
|
|
||||||
spec.loadFixture('aspects_index_prefill');
|
|
||||||
});
|
|
||||||
it("returns the status_message_fake_text textarea", function(){
|
|
||||||
expect(Publisher.input()[0].id).toBe('status_message_fake_text');
|
|
||||||
expect(Publisher.input().length).toBe(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
Loading…
Reference in a new issue