import { ADMIN_ROLES, USER_ROLES, TIERS } from '../../../constants';
import { RoleGuard } from './roleguards';

describe('RoleGuard', () => {
  it('1つの許可Roleが設定時、完全に一致するroleを持つ場合、許可される', () => {
    const guards = RoleGuard.requireds({ roles: [USER_ROLES.AUTHOR] });
    expect(guards.checkRole('author')).toBeTruthy();
  });
  it('1つの許可Roleが設定時、その許可roleを含むroleを持つ場合、許可される', () => {
    const guards = RoleGuard.requireds({ roles: [USER_ROLES.AUTHOR] });
    // 'author admin'が許可リスト(author)に含まれるので許可
    expect(guards.checkRole('author admin')).toBeTruthy();
  });
  it('author OR adminの許可Roleが設定時、その許可roleを含むroleを持つ場合、許可される', () => {
    const guards = RoleGuard.requireds({
      roles: [USER_ROLES.AUTHOR, ADMIN_ROLES.ADMIN],
    });
    // authorが許可リスト([authorまたはadmin])に含まれるので許可
    expect(guards.checkRole('author')).toBeTruthy();
    // adminが許可リスト([authorまたはadmin])に含まれるので許可
    expect(guards.checkRole('admin')).toBeTruthy();
    // adminが許可リスト([authorまたはadmin])に含まれるので許可
    expect(guards.checkRole('author admin')).toBeTruthy();
  });
  it('author OR adminの許可Roleが設定時、その許可roleを含むroleを持たない場合、拒否される', () => {
    const guards = RoleGuard.requireds({
      roles: [USER_ROLES.AUTHOR, ADMIN_ROLES.ADMIN],
    });
    // typistが許可リスト([authorまたはadmin])に含まれないので拒否
    expect(guards.checkRole('typist')).toBeFalsy();
  });
  it('author AND adminの許可Roleが設定時、その許可roleを含むroleを持つ場合、許可される', () => {
    const guards = RoleGuard.requireds({
      roles: [[USER_ROLES.AUTHOR, ADMIN_ROLES.ADMIN]],
    });
    // 'author admin'が許可リスト([authorかつadmin])に含まれるので許可
    expect(guards.checkRole('author admin')).toBeTruthy();
    // 'typist author admin'が許可リスト([authorかつadmin])に含まれるので許可
    expect(guards.checkRole('typist author admin')).toBeTruthy();
  });
  it('author AND adminの許可Roleが設定時、その許可roleに合致しないroleを持つ場合、拒否される', () => {
    const guards = RoleGuard.requireds({
      roles: [[USER_ROLES.AUTHOR, ADMIN_ROLES.ADMIN]],
    });
    // authorが許可リスト([authorかつadmin])に含まれないので拒否
    expect(guards.checkRole('author')).toBeFalsy();
    // adminが許可リスト([authorかつadmin])に含まれないので拒否
    expect(guards.checkRole('admin')).toBeFalsy();
    // typistが許可リスト([authorかつadmin])に含まれないので拒否
    expect(guards.checkRole('typist')).toBeFalsy();
  });
  it('(author AND admin) OR typistの許可Roleが設定時、その許可roleを含むroleを持つ場合、許可される', () => {
    const guards = RoleGuard.requireds({
      roles: [[USER_ROLES.AUTHOR, ADMIN_ROLES.ADMIN], USER_ROLES.TYPIST],
    });
    // typistが許可リスト(typist)に含まれないので許可
    expect(guards.checkRole('typist')).toBeTruthy();
    // 'author admin'が許可リスト([authorかつadmin])に含まれるので許可
    expect(guards.checkRole('author admin')).toBeTruthy();
    // 'typist author admin'が許可リスト([authorかつadmin],typist)に含まれるので許可
    expect(guards.checkRole('typist author admin')).toBeTruthy();
  });
  it('(author AND admin) OR typistの許可Roleが設定時、その許可roleを含むroleを持たない場合、拒否される', () => {
    const guards = RoleGuard.requireds({
      roles: [[USER_ROLES.AUTHOR, ADMIN_ROLES.ADMIN], USER_ROLES.TYPIST],
    });
    // authorが許可リスト([authorかつadmin])に含まれないので拒否
    expect(guards.checkRole('author')).toBeFalsy();
    // adminが許可リスト([authorかつadmin])に含まれないので拒否
    expect(guards.checkRole('admin')).toBeFalsy();
    // ""が許可リスト([authorかつadmin])に含まれないので拒否
    expect(guards.checkRole('')).toBeFalsy();
  });
});

describe('isRoles', () => {
  it('roleの各要素が正しい値であったとき、許可される', () => {
    const guards = RoleGuard.requireds({
      roles: [[USER_ROLES.AUTHOR, ADMIN_ROLES.ADMIN], USER_ROLES.TYPIST],
    });
    const result = guards.isRoles('admin author');
    expect(result).toBeTruthy();
  });
  it('roleの各要素に不正な値があったとき、拒否される', () => {
    const guards = RoleGuard.requireds({
      roles: [[USER_ROLES.AUTHOR, ADMIN_ROLES.ADMIN], USER_ROLES.TYPIST],
    });
    const result = guards.isRoles('admin xxx');
    expect(result).toBeFalsy();
  });

  it('roleの各要素に重複があったとき、拒否される', () => {
    const guards = RoleGuard.requireds({
      roles: [[USER_ROLES.AUTHOR, ADMIN_ROLES.ADMIN], USER_ROLES.TYPIST],
    });
    const result = guards.isRoles('admin admin');
    expect(result).toBeFalsy();
  });

  it('roleの値がないとき、拒否される', () => {
    const guards = RoleGuard.requireds({
      roles: [[USER_ROLES.AUTHOR, ADMIN_ROLES.ADMIN], USER_ROLES.TYPIST],
    });
    const result = guards.isRoles('');
    expect(result).toBeFalsy();
  });
});

describe('RoleGuard(Tier)', () => {
  it('設定したTierに指定した値が含まれる場合、許可される', () => {
    const guards = RoleGuard.requireds({
      tiers: [TIERS.TIER1, TIERS.TIER2, TIERS.TIER3],
    });
    expect(guards.checkTier(TIERS.TIER1)).toBeTruthy();
  });
  it('設定したTierに指定した値が含まれない場合、拒否される', () => {
    const guards = RoleGuard.requireds({
      tiers: [TIERS.TIER1, TIERS.TIER2, TIERS.TIER3],
    });
    expect(guards.checkTier(TIERS.TIER4)).toBeFalsy();
  });
});
