mirror of
				https://github.com/Redocly/redoc.git
				synced 2025-11-04 09:47:31 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			194 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			194 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
'use strict';
 | 
						|
import { Component  } from '@angular/core';
 | 
						|
import {
 | 
						|
  inject,
 | 
						|
  TestBed
 | 
						|
} from '@angular/core/testing';
 | 
						|
 | 
						|
import { OperationsList } from '../components/OperationsList/operations-list';
 | 
						|
import { MenuService, MenuItem } from './menu.service';
 | 
						|
import { Hash } from './hash.service';
 | 
						|
import { LazyTasksService } from '../shared/components/LazyFor/lazy-for';
 | 
						|
import { ScrollService  } from './scroll.service';
 | 
						|
import { SchemaHelper } from './schema-helper.service';
 | 
						|
import { SpecManager } from '../utils/spec-manager';
 | 
						|
 | 
						|
describe('Menu service', () => {
 | 
						|
  beforeEach(() => {
 | 
						|
    TestBed.configureTestingModule({ declarations: [ TestAppComponent, OperationsList ] });
 | 
						|
  });
 | 
						|
 | 
						|
  let menu:MenuService, hashService, scroll, tasks;
 | 
						|
  let specMgr;
 | 
						|
 | 
						|
  beforeEach(inject([SpecManager, Hash, ScrollService, LazyTasksService],
 | 
						|
  ( _specMgr, _hash, _scroll, _tasks) => {
 | 
						|
    hashService = _hash;
 | 
						|
    spyOn(hashService, 'update').and.stub();
 | 
						|
    scroll = _scroll;
 | 
						|
    tasks = _tasks;
 | 
						|
    specMgr = _specMgr;
 | 
						|
    SchemaHelper.setSpecManager(specMgr);
 | 
						|
  }));
 | 
						|
 | 
						|
  beforeEach(done => {
 | 
						|
    specMgr.load('/tests/schemas/extended-petstore.yml').then(done, done.fail);
 | 
						|
  });
 | 
						|
 | 
						|
  beforeEach(() => {
 | 
						|
    menu = TestBed.get(MenuService);
 | 
						|
    let fixture = TestBed.createComponent(TestAppComponent);
 | 
						|
    fixture.detectChanges();
 | 
						|
  });
 | 
						|
 | 
						|
  it('should scroll to operation when location hash is present [jp]', (done) => {
 | 
						|
    let hash = '#tag/pet/paths/~1pet~1findByStatus/get';
 | 
						|
    spyOn(menu, 'scrollToActive').and.callThrough();
 | 
						|
    spyOn(window, 'scrollTo').and.stub();
 | 
						|
    hashService.value.subscribe((hash) => {
 | 
						|
      if (!hash) return;
 | 
						|
      expect(menu.scrollToActive).toHaveBeenCalled();
 | 
						|
      let scrollY = (<jasmine.Spy>window.scrollTo).calls.argsFor(0)[1];
 | 
						|
      expect(scrollY).toBeGreaterThan(0);
 | 
						|
      (<jasmine.Spy>window.scrollTo).and.callThrough();
 | 
						|
      done();
 | 
						|
    });
 | 
						|
    hashService.value.next(hash);
 | 
						|
  });
 | 
						|
  //
 | 
						|
  it('should scroll to operation when location hash is present [operation]', (done) => {
 | 
						|
    let hash = '#operation/getPetById';
 | 
						|
    spyOn(menu, 'scrollToActive').and.callThrough();
 | 
						|
    spyOn(window, 'scrollTo').and.stub();
 | 
						|
    hashService.value.subscribe((hash) => {
 | 
						|
      if (!hash) return;
 | 
						|
      expect(menu.scrollToActive).toHaveBeenCalled();
 | 
						|
      let scrollY = (<jasmine.Spy>window.scrollTo).calls.argsFor(0)[1];
 | 
						|
      expect(scrollY).toBeGreaterThan(0);
 | 
						|
      done();
 | 
						|
    });
 | 
						|
    hashService.value.next(hash);
 | 
						|
  });
 | 
						|
 | 
						|
  it('should select next/prev menu item when scrolled down/up', () => {
 | 
						|
    // enable all items
 | 
						|
    menu.items.forEach(item => item.ready = true);
 | 
						|
 | 
						|
    scroll.$scrollParent = document.querySelector('#parent');
 | 
						|
    menu.activeIdx.should.be.equal(-1);
 | 
						|
 | 
						|
    let nextElTop = menu.getEl(1).getBoundingClientRect().top;
 | 
						|
    scroll.$scrollParent.scrollTop = nextElTop + 1;
 | 
						|
 | 
						|
    //simulate scroll down
 | 
						|
    spyOn(scroll, 'scrollY').and.returnValue(nextElTop + 10);
 | 
						|
    menu.onScroll(true);
 | 
						|
    menu.activeIdx.should.be.equal(1);
 | 
						|
 | 
						|
    scroll.scrollY.and.returnValue(nextElTop - 2);
 | 
						|
    scroll.$scrollParent.scrollTop = nextElTop - 1;
 | 
						|
    menu.onScroll(false);
 | 
						|
    menu.activeIdx.should.be.equal(0);
 | 
						|
  });
 | 
						|
 | 
						|
  describe('buildMenu method', () => {
 | 
						|
    let suitSchema = {
 | 
						|
      tags: [
 | 
						|
        {name: 'tag1', description: 'info1', 'x-traitTag': true},
 | 
						|
        {name: 'tag2', description: 'info2'},
 | 
						|
        {name: 'tag4', description: 'info2', 'x-displayName': 'Tag Four'}
 | 
						|
      ],
 | 
						|
      paths: {
 | 
						|
        test: {
 | 
						|
          put: {
 | 
						|
            tags: ['tag1', 'tag3'],
 | 
						|
            summary: 'test put'
 | 
						|
          },
 | 
						|
          get: {
 | 
						|
            tags: ['tag1', 'tag2'],
 | 
						|
            summary: 'test get'
 | 
						|
          },
 | 
						|
          delete: {
 | 
						|
            tags: ['tag4'],
 | 
						|
            summary: 'test delete'
 | 
						|
          },
 | 
						|
          // no tags
 | 
						|
          post: {
 | 
						|
            summary: 'test post'
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    };
 | 
						|
 | 
						|
    let items:MenuItem[];
 | 
						|
    beforeEach(() => {
 | 
						|
      menu.items = null;
 | 
						|
      specMgr._schema = suitSchema;
 | 
						|
      menu.buildMenu();
 | 
						|
      items = menu.items;
 | 
						|
    });
 | 
						|
 | 
						|
    it('should return instance of Array', () => {
 | 
						|
      items.should.be.instanceof(Array);
 | 
						|
    });
 | 
						|
 | 
						|
    it('should return Array with correct number of items', () => {
 | 
						|
      // 3 - defined tags, 1 - tag3 and 1 operation item for operation without tag
 | 
						|
      items.length.should.be.equal(3 + 1 + 1);
 | 
						|
    });
 | 
						|
 | 
						|
    it('should append not defined tags to the end of list', () => {
 | 
						|
      let item = items[3];
 | 
						|
      item.name.should.be.equal('tag3');
 | 
						|
      item.items.length.should.be.equal(1);
 | 
						|
      item.items[0].name.should.be.equal('test put');
 | 
						|
    });
 | 
						|
 | 
						|
    it('should append operation items without tags to the end of list', () => {
 | 
						|
      let operationItem = items[4];
 | 
						|
      operationItem.name.should.be.equal('test post');
 | 
						|
      operationItem.metadata.type.should.be.equal('operation');
 | 
						|
      should.not.exist(operationItem.items);
 | 
						|
    });
 | 
						|
 | 
						|
    it('should map x-traitTag to empty operation list', () => {
 | 
						|
      let item = items[0];
 | 
						|
      should.not.exist(item.items);
 | 
						|
    });
 | 
						|
 | 
						|
    it('operations for tag should contain valid pointer and name', () => {
 | 
						|
      for (let item of items) {
 | 
						|
        item.should.be.an.Object();
 | 
						|
        if (item.items) {
 | 
						|
          for (let subItem of item.items) {
 | 
						|
            subItem.should.have.properties(['metadata']);
 | 
						|
            let pointer = subItem.metadata.pointer;
 | 
						|
            let methSchema = specMgr.byPointer(pointer);
 | 
						|
            should.exist(methSchema);
 | 
						|
            if (methSchema.summary) {
 | 
						|
              methSchema.summary.should.be.equal(subItem.name);
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    });
 | 
						|
 | 
						|
    it('should use x-displayName to set custom names', () => {
 | 
						|
      let info = items[2];
 | 
						|
      info.id.should.be.equal('tag/tag4');
 | 
						|
      info.name.should.be.equal('Tag Four');
 | 
						|
    });
 | 
						|
  });
 | 
						|
});
 | 
						|
 | 
						|
@Component({
 | 
						|
  selector: 'test-app',
 | 
						|
  template:
 | 
						|
      `<div id='parent' style='height: 500px; overflow:auto'>
 | 
						|
        <api-info></api-info>
 | 
						|
        <operations-list></operations-list>
 | 
						|
      </div>`
 | 
						|
})
 | 
						|
class TestAppComponent {
 | 
						|
}
 |