ts-mockito#verify TypeScript Examples

The following examples show how to use ts-mockito#verify. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: internal.spec.ts    From kin-node with MIT License 6 votes vote down vote up
test('getServiceConfig', async () => {
    const env = newTestEnv(1);
    const [client, txClientV4] = [env.client, env.txClientV4];

    setGetServiceConfigResp(txClientV4);

    const resp = await client.getServiceConfig();
    expect(Buffer.from(resp.getSubsidizerAccount()!.getValue_asU8())).toEqual(subsidizer);
    expect(Buffer.from(resp.getToken()!.getValue_asU8())).toEqual(token);
    expect(Buffer.from(resp.getTokenProgram()!.getValue_asU8())).toEqual(TOKEN_PROGRAM_ID.toBuffer());

    await client.getServiceConfig();

    // Verify that only one request was submitted
    verify(txClientV4.getServiceConfig(anything(), anything(), anything())).times(1);
});
Example #2
Source File: web3-provider.connector.test.ts    From limit-order-protocol-utils with MIT License 5 votes vote down vote up
describe('Web3ProviderConnector', () => {
    let web3Provider: Web3;
    let web3ProviderConnector: Web3ProviderConnector;

    const typedData = {
        primaryType: 'Order',
        types: {
            EIP712Domain: EIP712_DOMAIN,
            Order: ORDER_STRUCTURE,
        },
        domain: {
            name: PROTOCOL_NAME,
            version: PROTOCOL_VERSION,
            chainId: 1,
            verifyingContract: '',
        },
        message: {},
    };

    beforeEach(() => {
        web3Provider = mock<Web3>();
        web3ProviderConnector = new Web3ProviderConnector(
            instance(web3Provider)
        );
    });

    it('signTypedData() must call eth_signTypedData_v4 rpc method', async () => {
        const walletAddress = '0xasd';

        const extendedWeb3 = {
            signTypedDataV4: jest.fn(),
        };

        when(web3Provider.extend(anything())).thenReturn(extendedWeb3);

        await web3ProviderConnector.signTypedData(walletAddress, typedData, '');

        expect(extendedWeb3.signTypedDataV4).toHaveBeenCalledWith(
            walletAddress,
            JSON.stringify(typedData)
        );
    });

    it('contractEncodeABI() changed address from null to undefined for contract instance', async () => {
        const eth = mock<Eth>();
        class ContractMock {
            methods = {
                foo: () => ({encodeABI: () => ''}),
            };
        }

        /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
        when(eth.Contract).thenReturn(ContractMock as any);
        when(web3Provider.eth).thenReturn(instance(eth));

        web3ProviderConnector.contractEncodeABI(
            LIMIT_ORDER_PROTOCOL_ABI,
            null,
            'foo',
            []
        );

        verify(eth.Contract).once();
    });
});
Example #3
Source File: internal.spec.ts    From kin-node with MIT License 5 votes vote down vote up
test('createAccount no service subsidizer', async () => {
    const account = PrivateKey.random();
    const tokenAccount = await Token.getAssociatedTokenAddress(ASSOCIATED_TOKEN_PROGRAM_ID, TOKEN_PROGRAM_ID, new PublicKey(token).solanaKey(), account.publicKey().solanaKey());

    const appSubsidizer = PrivateKey.random();
    const env = newTestEnv();
    const [client, accountClientV4, txClientV4] = [env.client, env.accountClientV4, env.txClientV4];

    setGetServiceConfigRespNoSubsidizer(txClientV4);
    setGetRecentBlockhashResp(txClientV4);

    when(accountClientV4.createAccount(anything(), anything(), anything()))
        .thenCall((req: accountpbv4.CreateAccountRequest, md: grpc.Metadata, callback) => {
            const err = validateHeaders(md);
            if (err != undefined) {
                callback(err, undefined);
                return;
            }

            const resp = new accountpbv4.CreateAccountResponse();

            // This should only be reached if an app subsidizer was passed in
            const tx = SolanaTransaction.from(req.getTransaction()!.getValue_asU8());
            expect(tx.signatures).toHaveLength(2);
            expect(tx.signatures[0].publicKey.toBuffer()).toEqual(appSubsidizer.publicKey().buffer);
            expect(appSubsidizer.kp.verify(tx.serializeMessage(), tx.signatures[0].signature!)).toBeTruthy();

            expect(tx.signatures[1].publicKey.toBuffer()).toEqual(account.publicKey().buffer);
            expect(account.kp.verify(tx.serializeMessage(), tx.signatures[1].signature!)).toBeTruthy();

            expect(tx.instructions).toHaveLength(2);

            const createAssocInstruction = TokenInstruction.decodeCreateAssociatedAccount(tx.instructions[0]);
            expect(createAssocInstruction.subsidizer.toBuffer()).toEqual(appSubsidizer.publicKey().buffer);
            expect(createAssocInstruction.address).toEqual(tokenAccount);
            expect(createAssocInstruction.owner.toBuffer()).toEqual(account.publicKey().buffer);
            expect(createAssocInstruction.mint.toBuffer()).toEqual(token);

            const setAuthInstruction = TokenInstruction.decodeSetAuthority(tx.instructions[1]);
            expect(setAuthInstruction.account).toEqual(tokenAccount);
            expect(setAuthInstruction.currentAuthority.toBuffer()).toEqual(account.publicKey().buffer);
            expect(setAuthInstruction.newAuthority!.toBuffer()).toEqual(appSubsidizer.publicKey().buffer);
            expect(setAuthInstruction.authorityType).toEqual('CloseAccount');

            resp.setResult(accountpbv4.CreateAccountResponse.Result.OK);
            callback(undefined, resp);
        });

    // Don't pass in subsidizer
    try {
        await client.createAccount(account);
        fail();
    } catch (err) {
        expect(err).toBeInstanceOf(NoSubsidizerError);
    }

    // Pass in subsidizer
    await client.createAccount(account, undefined, appSubsidizer);
});
Example #4
Source File: modal-header.component.spec.ts    From canopy with Apache License 2.0 5 votes vote down vote up
describe('LgModalHeaderComponent', () => {
  let component: LgModalHeaderComponent;
  let fixture: ComponentFixture<LgModalHeaderComponent>;
  let modalServiceMock: LgModalService;

  beforeEach(async () => {
    modalServiceMock = mock(LgModalService);

    await TestBed.configureTestingModule({
      declarations: [ LgModalHeaderComponent ],
      providers: [ { provide: LgModalService, useValue: instance(modalServiceMock) } ],
    }).compileComponents();
  });

  beforeEach(() => {
    fixture = TestBed.createComponent(LgModalHeaderComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });

  it('should have a class', () => {
    expect(fixture.nativeElement.getAttribute('class')).toContain('lg-modal-header');
  });

  it('should have an id', () => {
    component.id = 'test-2';
    fixture.detectChanges();

    expect(fixture.nativeElement.getAttribute('id')).toContain('test-2');
  });

  it('should close the modal on #close', () => {
    component.modalId = 'test';
    component.close();

    verify(modalServiceMock.close('test')).once();

    expect().nothing();
  });
});
Example #5
Source File: modal-trigger.directive.spec.ts    From canopy with Apache License 2.0 5 votes vote down vote up
describe('LgModalTriggerComponent', () => {
  let fixture: ComponentFixture<TestTriggerComponent>;
  let triggerDebugElement: DebugElement;
  let triggerInstance: LgModalTriggerDirective;
  let modalServiceMock: LgModalService;
  let focusSpy: jasmine.Spy;
  const isOpen$ = new BehaviorSubject(true);

  beforeEach(
    waitForAsync(() => {
      modalServiceMock = mock(LgModalService);

      TestBed.configureTestingModule({
        declarations: [ LgModalTriggerDirective, TestTriggerComponent ],
        providers: [ { provide: LgModalService, useValue: instance(modalServiceMock) } ],
      }).compileComponents();

      when(modalServiceMock.isOpen$(anything())).thenReturn(isOpen$);

      fixture = TestBed.createComponent(TestTriggerComponent);

      triggerDebugElement = fixture.debugElement.query(
        By.directive(LgModalTriggerDirective),
      );

      triggerInstance = triggerDebugElement.injector.get<LgModalTriggerDirective>(
        LgModalTriggerDirective,
      );

      focusSpy = spyOn(triggerDebugElement.nativeElement, 'focus');

      fixture.detectChanges();
    }),
  );

  it('should open the modal on click of the trigger element', () => {
    const clickedSpy = spyOn(triggerInstance.clicked, 'emit');

    triggerDebugElement.nativeElement.click();

    expect(triggerInstance['allowFocusOnModalTrigger']).toBeTrue();
    verify(modalServiceMock.open('test')).once();

    expect(clickedSpy).toHaveBeenCalledTimes(1);
  });

  it('should set the focus on the trigger when the modal is closed', () => {
    triggerInstance['allowFocusOnModalTrigger'] = true;
    isOpen$.next(false);

    expect(focusSpy).toHaveBeenCalledTimes(1);
  });

  it('shouldn\'t set the focus on the trigger when the modal is open', () => {
    triggerInstance['allowFocusOnModalTrigger'] = true;
    isOpen$.next(true);

    expect(focusSpy).toHaveBeenCalledTimes(0);
  });

  it('shouldn\'t set the focus on the trigger if the modal has just been initialised', () => {
    triggerInstance['allowFocusOnModalTrigger'] = false;
    isOpen$.next(false);

    expect(focusSpy).toHaveBeenCalledTimes(0);
  });
});
Example #6
Source File: internal.spec.ts    From kin-node with MIT License 5 votes vote down vote up
test('createAccount', async () => {
    const account = PrivateKey.random();
    const tokenAccount = await Token.getAssociatedTokenAddress(ASSOCIATED_TOKEN_PROGRAM_ID, TOKEN_PROGRAM_ID, new PublicKey(token).solanaKey(), account.publicKey().solanaKey());

    const env = newTestEnv();
    const [client, accountClientV4, txClientV4] = [env.client, env.accountClientV4, env.txClientV4];

    setGetServiceConfigResp(txClientV4);
    setGetRecentBlockhashResp(txClientV4);

    let created = false;
    when(accountClientV4.createAccount(anything(), anything(), anything()))
        .thenCall((req: accountpbv4.CreateAccountRequest, md: grpc.Metadata, callback) => {
            const err = validateHeaders(md);
            if (err != undefined) {
                callback(err, undefined);
                return;
            }

            const resp = new accountpbv4.CreateAccountResponse();
            if (created) {
                resp.setResult(accountpbv4.CreateAccountResponse.Result.EXISTS);
            } else {
                const tx = SolanaTransaction.from(req.getTransaction()!.getValue_asU8());
                expect(tx.signatures).toHaveLength(2);
                expect(tx.signatures[0].publicKey.toBuffer()).toEqual(subsidizer);
                expect(tx.signatures[0].signature).toBeNull();

                expect(tx.signatures[1].publicKey.toBuffer()).toEqual(account.publicKey().buffer);
                expect(account.kp.verify(tx.serializeMessage(), tx.signatures[1].signature!)).toBeTruthy();

                expect(tx.instructions).toHaveLength(2);

                const createAssocInstruction = TokenInstruction.decodeCreateAssociatedAccount(tx.instructions[0]);
                expect(createAssocInstruction.subsidizer.toBuffer()).toEqual(subsidizer);
                expect(createAssocInstruction.address).toEqual(tokenAccount);
                expect(createAssocInstruction.owner.toBuffer()).toEqual(account.publicKey().buffer);
                expect(createAssocInstruction.mint.toBuffer()).toEqual(token);

                const setAuthInstruction = TokenInstruction.decodeSetAuthority(tx.instructions[1]);
                expect(setAuthInstruction.account).toEqual(tokenAccount);
                expect(setAuthInstruction.currentAuthority.toBuffer()).toEqual(account.publicKey().buffer);
                expect(setAuthInstruction.newAuthority!.toBuffer()).toEqual(subsidizer);
                expect(setAuthInstruction.authorityType).toEqual('CloseAccount');

                resp.setResult(accountpbv4.CreateAccountResponse.Result.OK);
                created = true;
            }
            callback(undefined, resp);
        });

    await client.createAccount(account);
    expect(created).toBeTruthy();

    try {
        await client.createAccount(account);
        fail();
    } catch (err) {
        expect(err).toBeInstanceOf(AccountExists);
    }
});
Example #7
Source File: roles.guard.spec.ts    From nestjs-rest-sample with GNU General Public License v3.0 5 votes vote down vote up
describe('RolesGuard(ts-mockito)', () => {
  let guard: RolesGuard;
  const reflecter = mock(Reflector);
  beforeEach(() => {
    guard = new RolesGuard(instance(reflecter));
  });

  afterEach(() => {
    reset();
  });

  it('should skip(return true) if the `HasRoles` decorator is not set', async () => {
    const context = mock<ExecutionContext>();
    when(context.getHandler()).thenReturn({} as any);

    const contextInstacne = instance(context);
    when(
      reflecter.get<RoleType[]>(HAS_ROLES_KEY, contextInstacne.getHandler()),
    ).thenReturn([] as RoleType[]);
    const result = await guard.canActivate(contextInstacne);

    expect(result).toBeTruthy();
    verify(
      reflecter.get<RoleType[]>(HAS_ROLES_KEY, contextInstacne.getHandler()),
    ).once();
  });

  it('should return true if the `HasRoles` decorator is set', async () => {
    const context = mock<ExecutionContext>();

    when(context.getHandler()).thenReturn({} as any);

    const arguHost = mock<HttpArgumentsHost>();
    when(arguHost.getRequest()).thenReturn({
      user: { roles: [RoleType.USER] },
    } as any);

    when(context.switchToHttp()).thenReturn(instance(arguHost));
    const contextInstacne = instance(context);

    when(
      reflecter.get<RoleType[]>(HAS_ROLES_KEY, contextInstacne.getHandler()),
    ).thenReturn([RoleType.USER] as RoleType[]);

    const result = await guard.canActivate(contextInstacne);
    console.log(result);
    expect(result).toBeTruthy();
    verify(
      reflecter.get<RoleType[]>(HAS_ROLES_KEY, contextInstacne.getHandler()),
    ).once();
  });

  it('should return false if the `HasRoles` decorator is set but role is not allowed', async () => {
    const context = mock<ExecutionContext>();

    when(context.getHandler()).thenReturn({} as any);

    // logged in as USER
    const arguHost = mock<HttpArgumentsHost>();
    when(arguHost.getRequest()).thenReturn({
      user: { roles: [RoleType.USER] },
    } as any);

    when(context.switchToHttp()).thenReturn(instance(arguHost));
    const contextInstacne = instance(context);

    // but requires ADMIN
    when(
      reflecter.get<RoleType[]>(HAS_ROLES_KEY, contextInstacne.getHandler()),
    ).thenReturn([RoleType.ADMIN] as RoleType[]);

    const result = await guard.canActivate(contextInstacne);
    console.log(result);
    expect(result).toBeFalsy();
    verify(
      reflecter.get<RoleType[]>(HAS_ROLES_KEY, contextInstacne.getHandler()),
    ).once();
  });
});
Example #8
Source File: swagger-provider.spec.ts    From adonis5-swagger with MIT License 4 votes vote down vote up
describe('Swagger provider', () => {
	async function createAdonisApp(mockedServices: Partial<ContainerBindings>) {
		const app = await new AdonisApplication([], []).loadApp()
		for (const [alias, mockedService] of Object.entries(mockedServices)) {
			app.iocContainer.bind(alias, () => mockedService)
		}

		return app
	}

	describe('Swagger enabled', () => {
		let testUrl = 'testUrl'
		let configMock: ConfigContract
		let routerMock: RouterContract
		let routerForMiddlewareMock: RouteContract
		let app: AdonisApplication

		beforeAll(async () => {
			configMock = mock(Config)
			when(configMock.get('swagger.uiEnabled', true)).thenReturn(true)
			when(configMock.get('swagger.specEnabled', true)).thenReturn(true)
			when(configMock.get('swagger.uiUrl', 'docs')).thenReturn('docs')
			when(configMock.get('swagger.specUrl')).thenReturn(testUrl)
			when(configMock.get('swagger.middleware', [])).thenReturn([])
			when(configMock.get('swagger.options', {})).thenReturn({})

			routerMock = mock(Router)
			routerForMiddlewareMock = mock(Route)
			const routeForMiddlewareInstance = instance(routerForMiddlewareMock)
			when(routerMock.get(`docs/:fileName?`, anything())).thenReturn(routeForMiddlewareInstance)
			when(routerMock.get(testUrl, anything())).thenReturn(routeForMiddlewareInstance)

			app = await createAdonisApp({
				'Adonis/Core/Config': instance(configMock),
				'Adonis/Core/Route': instance(routerMock),
			})
		})

		it('should instantiate provider with enabled swagger', async () => {
			const swaggerProvider = new SwaggerProvider(app.application)
			await swaggerProvider.register()
			await swaggerProvider.boot()

			verify(configMock.get('swagger.uiEnabled', true)).once()
			verify(configMock.get('swagger.specEnabled', true)).once()
			verify(configMock.get('swagger.uiUrl', 'docs')).once()
			verify(configMock.get('swagger.specUrl')).once()

			verify(routerMock.get(testUrl, anything())).once()
			verify(routerForMiddlewareMock.middleware(anything())).twice()
		})

		afterAll(async () => {
			await app.stopApp()
		})
	})

	describe('Swagger disabled', () => {
		let testUrl = 'testUrl'
		let configMock: ConfigContract
		let routerMock: RouterContract
		let adonisApp: AdonisApplication

		beforeAll(async () => {
			configMock = mock(Config)
			when(configMock.get('swagger.uiEnabled')).thenReturn(false)
			when(configMock.get('swagger.specEnabled')).thenReturn(false)

			routerMock = mock(Router)
			when(routerMock.get(testUrl, anything())).thenReturn({} as any)

			adonisApp = await createAdonisApp({
				'Adonis/Core/Config': instance(configMock),
				'Adonis/Core/Route': instance(routerMock),
			})
		})

		it('should not init swagger module, swagger was disabled', async () => {
			const swaggerProvider = new SwaggerProvider(adonisApp.application)
			await swaggerProvider.register()
			await swaggerProvider.boot()

			verify(configMock.get('swagger.specEnabled')).never()
			verify(configMock.get('swagger.uiEnabled')).never()
			verify(configMock.get('swagger.uiUrl', 'docs')).never()
			verify(configMock.get('swagger.specUrl')).never()

			verify(routerMock.get(testUrl, anything())).never()
		})

		afterAll(async () => {
			await adonisApp.stopApp()
		})
	})
})
Example #9
Source File: private-key-provider.connector.test.ts    From limit-order-protocol-utils with MIT License 4 votes vote down vote up
describe('PrivateKeyProviderConnector', () => {
    let web3Provider: Web3;
    let privateKeyProviderConnector: PrivateKeyProviderConnector;

    const testPrivateKey =
        'd8d1f95deb28949ea0ecc4e9a0decf89e98422c2d76ab6e5f736792a388c56c7';
    const limitOrder: LimitOrder = {
        salt: '1469462901577',
        getMakerAmount:
            '0xf4a215c30000000000000000000000000000000000000000000000',
        getTakerAmount:
            '0x296637bf0000000000000000000000000000000000000000000000',
        makerAsset: '0x111111111117dc0aa78b770fa6a738034120c302',
        takerAsset: '0xe9e7cea3dedca5984780bafc599bd69add087d56',
        maker: '0xa07c1d51497fb6e66aa2329cecb86fca0a957fdb',
        receiver: '0x0000000000000000000000000000000000000000',
        allowedSender: '0x0000000000000000000000000000000000000000',
        makingAmount: '1000000000000000000000',
        takingAmount: '90000000000000000000',
        makerAssetData:
            '0x23b872dd000000000000000000000000fb3c7eb936caa12b5a884d612393969a557d43070000',
        takerAssetData:
            '0x23b872dd00000000000000000000000000000000000000000000000000000000000000000000',
        interaction: '0x',
        permit: '0x',
        predicate: '0x',
    };
    const typedData: EIP712TypedData = {
        primaryType: 'Order',
        types: {
            EIP712Domain: EIP712_DOMAIN,
            Order: ORDER_STRUCTURE,
        },
        domain: {
            name: PROTOCOL_NAME,
            version: PROTOCOL_VERSION,
            chainId: 1,
            verifyingContract: '',
        },
        message: limitOrder,
    };

    beforeEach(() => {
        web3Provider = mock<Web3>();
        privateKeyProviderConnector = new PrivateKeyProviderConnector(
            testPrivateKey,
            instance(web3Provider)
        );
    });

    it('signTypedData() must sign typed data by private key', async () => {
        const walletAddress = '0xa07c1d51497fb6e66aa2329cecb86fca0a957fdb';

        const signature = await privateKeyProviderConnector.signTypedData(
            walletAddress,
            typedData
        );

        expect(signature).toMatchSnapshot();
    });

    it('contractEncodeABI() changed address from null to undefined for contract instance', async () => {
        const eth = mock<Eth>();
        class ContractMock {
            methods = {
                foo: () => ({encodeABI: () => ''}),
            };
        }

        /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
        when(eth.Contract).thenReturn(ContractMock as any);
        when(web3Provider.eth).thenReturn(instance(eth));

        privateKeyProviderConnector.contractEncodeABI(
            LIMIT_ORDER_PROTOCOL_ABI,
            null,
            'foo',
            []
        );

        verify(eth.Contract).once();
    });
});
Example #10
Source File: internal.spec.ts    From kin-node with MIT License 4 votes vote down vote up
test('internal retry Kin 4', async () => {
    let env = newTestEnv();
    const [accountClientV4, airdropClientV4] = [env.accountClientV4, env.airdropClientV4];
    let [client, txClientV4] = [env.client, env.txClientV4];

    const account = PrivateKey.random();
    when(accountClientV4.createAccount(anything(), anything(), anything()))
        .thenCall((_, __, callback) => {
            const err: grpc.ServiceError = {
                name: "",
                message: "",
                code: grpc.status.INTERNAL,
            };
            callback(err, new accountpbv4.CreateAccountRequest());
        });
    when(accountClientV4.getAccountInfo(anything(), anything(), anything()))
        .thenCall((_, __, callback) => {
            const err: grpc.ServiceError = {
                name: "",
                message: "",
                code: grpc.status.INTERNAL,
            };
            callback(err, new accountpbv4.GetAccountInfoResponse());
        });
    when(airdropClientV4.requestAirdrop(anything(), anything(), anything()))
        .thenCall((_, __, callback) => {
            const err: grpc.ServiceError = {
                name: "",
                message: "",
                code: grpc.status.INTERNAL,
            };
            callback(err, new airdroppbv4.RequestAirdropResponse());
        });
    when(txClientV4.getTransaction(anything(), anything(), anything()))
        .thenCall((_, __, callback) => {
            const err: grpc.ServiceError = {
                name: "",
                message: "",
                code: grpc.status.INTERNAL,
            };
            callback(err, new transactionpbv4.GetTransactionResponse());
        });
    when(txClientV4.submitTransaction(anything(), anything(), anything()))
        .thenCall((_, __, callback) => {
            const err: grpc.ServiceError = {
                name: "",
                message: "",
                code: grpc.status.INTERNAL,
            };
            callback(err, new transactionpbv4.SubmitTransactionResponse());
        });

    setGetServiceConfigResp(txClientV4);
    setGetMinBalanceResp(txClientV4);
    setGetRecentBlockhashResp(txClientV4);

    try {
        await client.createAccount(account);
        fail();
    } catch (err) {
        expect(err).toBeDefined();
    }
    verify(accountClientV4.createAccount(anything(), anything(), anything())).times(3);

    try {
        await client.getAccountInfo(new PublicKey(Buffer.alloc(32)));
        fail();
    } catch (err) {
        expect(err).toBeDefined();
    }
    verify(accountClientV4.createAccount(anything(), anything(), anything())).times(3);

    try {
        await client.getTransaction(Buffer.alloc(32));
        fail();
    } catch (err) {
        expect(err).toBeDefined();
    }
    verify(txClientV4.getTransaction(anything(), anything(), anything())).times(3);

    const transaction = new SolanaTransaction({
        feePayer: PrivateKey.random().publicKey().solanaKey(),
        recentBlockhash: new PublicKey(recentBlockhash).toBase58(),
    }).add(
        Token.createTransferInstruction(
            TOKEN_PROGRAM_ID,
            PrivateKey.random().publicKey().solanaKey(),
            PrivateKey.random().publicKey().solanaKey(),
            PrivateKey.random().publicKey().solanaKey(),
            [],
            100,
        )
    );
    try {
        await client.submitTransaction(transaction);
        fail();
    } catch (err) {
        expect(err).toBeDefined();
    }
    verify(txClientV4.submitTransaction(anything(), anything(), anything())).times(3);

    try {
        await client.requestAirdrop(account.publicKey(), new BigNumber(10));
        fail();
    } catch (err) {
        expect(err).toBeDefined();
    }
    verify(airdropClientV4.requestAirdrop(anything(), anything(), anything())).times(3);

    env = newTestEnv();
    client = env.client;
    txClientV4 = env.txClientV4;

    when(txClientV4.getServiceConfig(anything(), anything(), anything()))
        .thenCall((_, __, callback) => {
            const err: grpc.ServiceError = {
                name: "",
                message: "",
                code: grpc.status.INTERNAL,
            };
            callback(err, new transactionpbv4.SubmitTransactionResponse());
        });

    when(txClientV4.getRecentBlockhash(anything(), anything(), anything()))
        .thenCall((_, __, callback) => {
            const err: grpc.ServiceError = {
                name: "",
                message: "",
                code: grpc.status.INTERNAL,
            };
            callback(err, new transactionpbv4.GetRecentBlockhashResponse());
        });

    when(txClientV4.getMinimumBalanceForRentExemption(anything(), anything(), anything()))
        .thenCall((_, __, callback) => {
            const err: grpc.ServiceError = {
                name: "",
                message: "",
                code: grpc.status.INTERNAL,
            };
            callback(err, new transactionpbv4.GetMinimumBalanceForRentExemptionResponse());
        });

    try {
        await client.getServiceConfig();
        fail();
    } catch (err) {
        expect(err).toBeDefined();
    }
    verify(txClientV4.getServiceConfig(anything(), anything(), anything())).times(3);

    try {
        await client.getRecentBlockhash();
        fail();
    } catch (err) {
        expect(err).toBeDefined();
    }
    verify(txClientV4.getRecentBlockhash(anything(), anything(), anything())).times(3);

    try {
        await client.getMinimumBalanceForRentExemption();
        fail();
    } catch (err) {
        expect(err).toBeDefined();
    }
    verify(txClientV4.getMinimumBalanceForRentExemption(anything(), anything(), anything())).times(3);
});
Example #11
Source File: post.controller.spec.ts    From nestjs-rest-sample with GNU General Public License v3.0 4 votes vote down vote up
describe('Post Controller', () => {
  describe('Replace PostService in provider(useClass: PostServiceStub)', () => {
    let controller: PostController;

    beforeEach(async () => {
      const module: TestingModule = await Test.createTestingModule({
        providers: [
          {
            provide: PostService,
            useClass: PostServiceStub,
          },
        ],
        controllers: [PostController],
      }).compile();

      controller = await module.resolve<PostController>(PostController);
    });

    it('should be defined', () => {
      expect(controller).toBeDefined();
    });

    it('GET on /posts should return all posts', async () => {
      const posts = await lastValueFrom(controller.getAllPosts());
      expect(posts.length).toBe(3);
    });

    it('GET on /posts/:id should return one post ', (done) => {
      controller.getPostById('1').subscribe((data) => {
        expect(data._id).toEqual('1');
        done();
      });
    });

    it('POST on /posts should save post', async () => {
      const post: CreatePostDto = {
        title: 'test title',
        content: 'test content',
      };
      const saved = await lastValueFrom(
        controller.createPost(
          post,
          createMock<Response>({
            location: jest.fn().mockReturnValue({
              status: jest.fn().mockReturnValue({
                send: jest.fn().mockReturnValue({
                  headers: { location: '/posts/post_id' },
                  status: 201,
                }),
              }),
            }),
          }),
        ),
      );
      // console.log(saved);
      expect(saved.status).toBe(201);
    });

    it('PUT on /posts/:id should update the existing post', (done) => {
      const post: UpdatePostDto = {
        title: 'test title',
        content: 'test content',
      };
      controller
        .updatePost(
          '1',
          post,
          createMock<Response>({
            status: jest.fn().mockReturnValue({
              send: jest.fn().mockReturnValue({
                status: 204,
              }),
            }),
          }),
        )
        .subscribe((data) => {
          expect(data.status).toBe(204);
          done();
        });
    });

    it('DELETE on /posts/:id should delete post', (done) => {
      controller
        .deletePostById(
          '1',
          createMock<Response>({
            status: jest.fn().mockReturnValue({
              send: jest.fn().mockReturnValue({
                status: 204,
              }),
            }),
          }),
        )
        .subscribe((data) => {
          expect(data).toBeTruthy();
          done();
        });
    });

    it('POST on /posts/:id/comments', async () => {
      const result = await lastValueFrom(
        controller.createCommentForPost(
          'testpost',
          { content: 'testcomment' },
          createMock<Response>({
            location: jest.fn().mockReturnValue({
              status: jest.fn().mockReturnValue({
                send: jest.fn().mockReturnValue({
                  headers: { location: '/posts/post_id/comments/comment_id' },
                  status: 201,
                }),
              }),
            }),
          }),
        ),
      );

      expect(result.status).toBe(201);
    });

    it('GET on /posts/:id/comments', async () => {
      const result = await lastValueFrom(
        controller.getAllCommentsOfPost('testpost'),
      );

      expect(result.length).toBe(1);
    });
  });

  describe('Replace PostService in provider(useValue: fake object)', () => {
    let controller: PostController;

    beforeEach(async () => {
      const module: TestingModule = await Test.createTestingModule({
        providers: [
          {
            provide: PostService,
            useValue: {
              findAll: (_keyword?: string, _skip?: number, _limit?: number) =>
                of<any[]>([
                  {
                    _id: 'testid',
                    title: 'test title',
                    content: 'test content',
                  },
                ]),
            },
          },
        ],
        controllers: [PostController],
      }).compile();

      controller = await module.resolve<PostController>(PostController);
    });

    it('should get all posts(useValue: fake object)', async () => {
      const result = await lastValueFrom(controller.getAllPosts());
      expect(result[0]._id).toEqual('testid');
    });
  });

  describe('Replace PostService in provider(useValue: jest mocked object)', () => {
    let controller: PostController;
    let postService: PostService;

    beforeEach(async () => {
      const module: TestingModule = await Test.createTestingModule({
        providers: [
          {
            provide: PostService,
            useValue: {
              constructor: jest.fn(),
              findAll: jest
                .fn()
                .mockImplementation(
                  (_keyword?: string, _skip?: number, _limit?: number) =>
                    of<any[]>([
                      {
                        _id: 'testid',
                        title: 'test title',
                        content: 'test content',
                      },
                    ]),
                ),
            },
          },
        ],
        controllers: [PostController],
      }).compile();

      controller = await module.resolve<PostController>(PostController);
      postService = module.get<PostService>(PostService);
    });

    it('should get all posts(useValue: jest mocking)', async () => {
      const result = await lastValueFrom(controller.getAllPosts('test', 10, 0));
      expect(result[0]._id).toEqual('testid');
      expect(postService.findAll).toBeCalled();
      expect(postService.findAll).lastCalledWith('test', 0, 10);
    });
  });

  describe('Mocking PostService using ts-mockito', () => {
    let controller: PostController;
    const mockedPostService: PostService = mock(PostService);

    beforeEach(async () => {
      controller = new PostController(instance(mockedPostService));
    });

    it('should get all posts(ts-mockito)', async () => {
      when(
        mockedPostService.findAll(anyString(), anyNumber(), anyNumber()),
      ).thenReturn(
        of([
          { _id: 'testid', title: 'test title', content: 'content' },
        ]) as Observable<Post[]>,
      );
      const result = await lastValueFrom(controller.getAllPosts('', 10, 0));
      expect(result.length).toEqual(1);
      expect(result[0].title).toBe('test title');
      verify(
        mockedPostService.findAll(anyString(), anyNumber(), anyNumber()),
      ).once();
    });
  });
});
Example #12
Source File: c-copy.test.ts    From bindable with MIT License 4 votes vote down vote up
describe('c-copy component', () => {
    let component;
    let mockedNotification: CToastsService;

    describe('Unit', () => {
        afterEach(() => {
            jest.useRealTimers();
        });

        beforeEach(() => {
            jest.useFakeTimers();
            jest.clearAllMocks();

            mockedNotification = mock(CToastsService);
            component = new CCopy(instance(mockedNotification));
        });

        describe('#copy', () => {
            test('without action callback', async () => {
                await component.copy('test');

                verify(mockedNotification.success(anything())).once();
            });

            test('with action callback', async () => {
                component.action = jest.fn(async () => 'Success');

                expect(component.action).toBeDefined();

                await component.copy('***');

                expect(component.action).toHaveBeenCalled();

                verify(mockedNotification.success(anything())).once();
            });
        });
    });

    describe('Integration', () => {
        afterEach(() => {
            component.dispose();
        });

        beforeEach(() => {
            jest.clearAllMocks();
        });

        it('testing link enabled', async done => {
            component = StageComponent.withResources()
                .inView('<c-copy link.bind="customLink"></c-copy>')
                .boundTo({
                    customLink: true,
                });

            try {
                await bootStrapEnvironment(component);
                expect(component.viewModel.link).toBe(true);
                done();
            } catch (e) {
                done.fail(e);
            }
        });

        it('testing link to be false if invalid type', async done => {
            component = StageComponent.withResources()
                .inView('<c-copy link.bind="customLink"></c-copy>')
                .boundTo({
                    customLink: 1,
                });

            try {
                await bootStrapEnvironment(component);
                expect(component.viewModel.link).toBe(false);
                done();
            } catch (e) {
                done.fail(e);
            }
        });

        it('testing wrap enabled', async done => {
            component = StageComponent.withResources()
                .inView('<c-copy wrap.bind="customWrap"></c-copy>')
                .boundTo({
                    customWrap: true,
                });

            try {
                await bootStrapEnvironment(component);
                expect(component.viewModel.wrap).toBe(true);
                done();
            } catch (e) {
                done.fail(e);
            }
        });

        it('testing wrap to be false if invalid type', async done => {
            component = StageComponent.withResources()
                .inView('<c-copy wrap.bind="customWrap"></c-copy>')
                .boundTo({
                    customWrap: 1,
                });

            try {
                await bootStrapEnvironment(component);
                expect(component.viewModel.wrap).toBe(false);
                done();
            } catch (e) {
                done.fail(e);
            }
        });

        it('tests if copy text link works', async done => {
            const queryStr = 'c-button';
            component = StageComponent.withResources()
                .inView('<c-copy link.bind="customLink"></c-copy>')
                .boundTo({
                    customLink: true,
                });

            try {
                await bootStrapEnvironment(component);
                (document.querySelector(queryStr) as any).click();
                expect(copyToClipboard).toHaveBeenCalledTimes(1);
                expect(component.viewModel.link).toBe(true);
                done();
            } catch (e) {
                done.fail(e);
            }
        });

        describe('CSS Classes', () => {
            it('css class: container', async done => {
                component = StageComponent.withResources().inView('<c-copy></c-copy>');

                try {
                    await bootStrapEnvironment(component);
                    expect(component.viewModel.styles.container).not.toBe(undefined);
                    done();
                } catch (e) {
                    done.fail(e);
                }
            });

            it('css class: content', async done => {
                component = StageComponent.withResources().inView('<c-copy></c-copy>');

                try {
                    await bootStrapEnvironment(component);
                    expect(component.viewModel.styles.container).not.toBe(undefined);
                    done();
                } catch (e) {
                    done.fail(e);
                }
            });
        });
    });
});
Example #13
Source File: ModelManager.test.ts    From aem-spa-page-model-manager with Apache License 2.0 4 votes vote down vote up
describe('ModelManager ->', () => {
    const PAGE_MODEL_LOAD_EVENT_OPTIONS = {
        detail: {
            model: PAGE_MODEL
        }
    };

    function expectPageModelLoadedEventFired() {
        expect(PathUtils.dispatchGlobalCustomEvent).toHaveBeenCalled();
        expect(PathUtils.dispatchGlobalCustomEvent).toHaveBeenCalledWith(EventType.PAGE_MODEL_LOADED, PAGE_MODEL_LOAD_EVENT_OPTIONS);
    }

    function assertAsyncModelFetched() {
        expectPageModelLoadedEventFired();

        return ModelManager.getData().then((data) => {
            assert.deepEqual(data, PAGE_MODEL, 'data should be correct');
        });
    }

    function mockTheFetch(path: any, data: any) {
        REQUEST_MAP[path] = data;
    }

    let pathName = '';
    let metaProps: { [key: string]: string } = {};
    const isRouteExcludedSpy = isRouteExcluded as jest.MockedFunction<(route: string) => boolean>;

    beforeEach(() => {
        metaProps = {};
        metaProps[MetaProperty.PAGE_MODEL_ROOT_URL] = PAGE_MODEL_URL;
        pathName = PAGE_PATH;

        when(ModelClientMock.fetch(anyString())).thenReturn(Promise.resolve(PAGE_MODEL));
        when(ModelClientMock.fetch(PAGE_MODEL_URL)).thenReturn(Promise.resolve(PAGE_MODEL));
        when(ModelClientMock.fetch(CHILD_MODEL_URL)).thenReturn(Promise.resolve(content_test_page_root_child0000_child0010));
        when(ModelClientMock.fetch(NON_EXISTING_MODEL_URL))
            .thenReturn(Promise.reject({ response: { status: 404, statusText: 'Could not find page' } }));
        when(ModelClientMock.fetch(ERROR_MODEL_URL)).thenReturn(Promise.reject('Some Error without json'));

        when(ModelClientMock.fetch(ERROR_MODEL_URL_404)).thenReturn(Promise.resolve(ERROR_PAGE_MODEL_404));
        when(ModelClientMock.fetch(ERROR_MODEL_URL_500)).thenReturn(Promise.resolve(ERROR_PAGE_MODEL_500));

        modelClient = instance(ModelClientMock);
        jest.spyOn(PathUtils, 'getMetaPropertyValue').mockImplementation((val) => metaProps[val]);
        jest.spyOn(PathUtils, 'dispatchGlobalCustomEvent');
        jest.spyOn(PathUtils, 'getCurrentPathname').mockImplementation(() => pathName);
        isRouteExcludedSpy.mockImplementation(() => false);
        mockTheFetch(PAGE_MODEL_URL, PAGE_MODEL);
    });

    afterEach(() => {
        reset(ModelClientMock);
        pathName = '';
    });

    describe('initialize ->', () => {
        describe('Initialization without config object ->', () => {
            it('should NOT fetch remote data on initialization when the model is provided', () => {
                return ModelManager.initialize({ model: PAGE_MODEL }).then((data) => {
                    expectPageModelLoadedEventFired();
                    expect(data).toEqual(PAGE_MODEL);
                    assert.deepEqual(data, PAGE_MODEL, 'data should be correct');
                });
            });

            it('should fetch remote data on initialization - root path as meta property', () => {
                metaProps[MetaProperty.PAGE_MODEL_ROOT_URL] = PAGE_MODEL_URL;

                return ModelManager.initialize().then((data) => {
                    expectPageModelLoadedEventFired();
                    assert.deepEqual(data, PAGE_MODEL, 'data should be correct');
                });
            });

            it('should fetch remote data on initialization - root path as currentPathname', () => {
                pathName = PAGE_MODEL_URL;

                return ModelManager.initialize().then((data) => {
                    expectPageModelLoadedEventFired();
                    assert.deepEqual(data, PAGE_MODEL, 'data should be correct');
                });
            });

            it('should fetch remote data on initialization - root path as a parameter', () => {
                return ModelManager.initialize(PAGE_PATH).then((data) => {
                    expectPageModelLoadedEventFired();
                    assert.deepEqual(data, PAGE_MODEL, 'data should be correct');
                });
            });
        });

        it('should fetch remote data on initialization', () => {
            return ModelManager.initialize({ path: PAGE_PATH, modelClient: modelClient }).then((data) => {
                verify(modelClient.fetch(anyString()));
                assert.deepEqual(data, PAGE_MODEL, 'data should be correct');
            });
        });

        it('should fail when initialized on non-browser with invlid config', () => {
            pathName = '';

            // disable console.error within the test
            jest.spyOn(console, 'error').mockImplementation();

            //simulate non browser for the test
            const windowSpy = jest.spyOn(global, 'window', 'get');

            windowSpy.mockImplementation();

            try {
                ModelManager.initialize();
            } catch (err) {
                assert.strictEqual(err.name, 'Error');
            }
            windowSpy.mockRestore();
        });

        it('should throw error when initialized without model url', () => {
            metaProps = {};
            pathName = '';
            try {
                ModelManager.initialize();
            } catch (err) {
                assert.strictEqual(err.name, 'Error');
            }
        });

        it('should throw error when initialized with invalid model url', () => {
            try {
                ModelManager.initialize({ path: '?abc' });
            } catch (err) {
                assert.strictEqual(err.name, 'Error');
            }
        });

        it('should not make concurrent server calls on duplicate request', () => {
            return ModelManager.initialize({ path: PAGE_PATH, model: PAGE_MODEL, modelClient: modelClient }).then(() => {
                expectPageModelLoadedEventFired();
                pathName = '/content/test/duplicate/request';

                when(ModelClientMock.fetch(pathName)).thenReturn(new Promise((resolve) => {
                    setTimeout(() => resolve(PAGE_MODEL), 200);
                }));

                const promises: any[] = [];

                promises.push(ModelManager._fetchData(pathName));
                promises.push(ModelManager._fetchData(pathName));
                promises.push(ModelManager._fetchData(pathName));

                return Promise.all(promises).then(() => {
                    for (let i = 0; i < promises.length - 1; ++i) {
                        expect(promises[i]).toEqual(promises[i + 1]);
                    }
                });
            });
        });

        describe('when the request is for an asynchronous subpage -- ', () => {
            beforeEach(() => {
                pathName = '/content/test/pageNotInModel';
                metaProps[MetaProperty.PAGE_MODEL_ROOT_URL] = '/content/test';
            });

            it('should fetch data twice on initialization', () => {
                return ModelManager.initialize({ path: PAGE_PATH, modelClient: modelClient }).then((data) => {
                    expectPageModelLoadedEventFired();
                    verify(ModelClientMock.fetch(anyString())).times(2);
                    assert.deepEqual(data, PAGE_MODEL, 'data should be correct');
                });
            });

            it('should fetch data once on initialization when sub page route path is excluded', () => {
                isRouteExcludedSpy.mockReturnValue(true);
                return ModelManager.initialize({ path: PAGE_PATH, modelClient: modelClient }).then((data) => {
                    expectPageModelLoadedEventFired();
                    verify(ModelClientMock.fetch(anyString())).times(1);
                    assert.deepEqual(data, PAGE_MODEL, 'data should be correct');
                });
            });
         });

        it('should not fetch data on initialization', () => {
            return ModelManager.initialize({ path: PAGE_PATH, model: PAGE_MODEL, modelClient: modelClient }).then((data) => {
                expectPageModelLoadedEventFired();
                // verify(ModelClientMock.fetch(anyString())).never();
                assert.deepEqual(data, PAGE_MODEL, 'data should be correct');
            });
        });

        it('should not fetch data', () => {
            return ModelManager.initialize({ path: PAGE_PATH, model: PAGE_MODEL, modelClient: modelClient }).then(() => {
                expectPageModelLoadedEventFired();

                return ModelManager.getData(CHILD_PATH).then((data) => {
                    verify(ModelClientMock.fetch(CHILD_MODEL_URL)).never();
                    assert.deepEqual(data, content_test_page_root_child0000_child0010, 'data should be correct');
                });
            });
        });

        it('should fetch all the data', () => {
            return ModelManager.initialize({ path: PAGE_PATH, model: PAGE_MODEL, modelClient: modelClient }).then(() => {
                expectPageModelLoadedEventFired();

                return ModelManager.getData().then((data) => {
                    verify(ModelClientMock.fetch(CHILD_MODEL_URL)).never();
                    assert.deepEqual(data, PAGE_MODEL, 'data should be correct');
                });
            });
        });

        it('should fetch data if forced', () => {
            return ModelManager.initialize({ path: PAGE_PATH, model: PAGE_MODEL, modelClient: modelClient }).then(() => {
                expectPageModelLoadedEventFired();

                return ModelManager.getData({ path: CHILD_PATH, forceReload: true }).then((data) => {
                    verify(ModelClientMock.fetch(anyString())).times(1);
                    assert.deepEqual(data, content_test_page_root_child0000_child0010, 'data should be correct');
                });
            });
        });
    });

    describe('initializeAsync ->', () => {
        describe('Initialization without config object ->', () => {
            it('should fetch remote data on initialization - root path as meta property', () => {
                metaProps[MetaProperty.PAGE_MODEL_ROOT_URL] = PAGE_MODEL_URL;
                ModelManager.initializeAsync();
                assertAsyncModelFetched();
            });

            it('should fetch remote data on initialization - root path as currentPathname', () => {
                pathName = PAGE_MODEL_URL;
                ModelManager.initializeAsync();
                assertAsyncModelFetched();
            });

            it('should initialize model store when no root path is provided', () => {
                metaProps = {};
                pathName = '';
                ModelManager.initializeAsync();

                return ModelManager.getData({ path: PAGE_MODEL_URL }).then((data) => {
                    assert.deepEqual(data, PAGE_MODEL, 'data should be correct');
                });
            });
        });

        it('should fetch standalone item data', () => {
            metaProps = {};
            pathName = '';
            ModelManager.initializeAsync();

            return ModelManager.getData({ path: CHILD_PATH }).then((data) => {
                assert.deepEqual(data, content_test_page_root_child0000_child0010, 'data should be correct');
            });
        });
        it('should throw error when fetching data without initialization', () => {
            ModelManager.getData({ path: PAGE_MODEL_URL }).then((data) => {
                assert.deepEqual(data, PAGE_MODEL, 'data should be correct');
            });
        });

        it('should NOT fetch remote data on initialization when the model is provided', () => {
            ModelManager.initializeAsync({ model: PAGE_MODEL });
            assertAsyncModelFetched();
        });

        it('should fetch remote data on initialization - root path as a parameter', () => {
            ModelManager.initializeAsync(PAGE_PATH);
            assertAsyncModelFetched();
        });

        it('should fetch remote data on initialization', () => {
            ModelManager.initializeAsync({ path: PAGE_PATH, modelClient: modelClient });
            verify(modelClient.fetch(anyString()));
            assertAsyncModelFetched();
        });

        it('should load a 404 error page.', async () => {

            const configuration:ModelManagerConfiguration = {
                path: PAGE_PATH,
                modelClient: modelClient,
                errorPageRoot: ERROR_PAGE_ROOT
            };
            const data:Model = await ModelManager.initialize(configuration);
            verify(modelClient.fetch(anyString()));
            assert.deepEqual(data, PAGE_MODEL, 'data should be correct');

            const nonExistingData = await ModelManager._fetchData(NON_EXISTING_PATH);
            assert.deepEqual(nonExistingData, ERROR_PAGE_MODEL_404, 'data should be correct');

        });

        it('should load a 500 error page.', async () => {

            const configuration:ModelManagerConfiguration = {
                path: PAGE_PATH,
                modelClient: modelClient,
                errorPageRoot: ERROR_PAGE_ROOT
            };
            const data:Model = await ModelManager.initialize(configuration);
            verify(modelClient.fetch(anyString()));
            assert.deepEqual(data, PAGE_MODEL, 'data should be correct');

            const nonExistingData = await ModelManager._fetchData(PAGE_WITH_ERROR_PATH);
            assert.deepEqual(nonExistingData, ERROR_PAGE_MODEL_500, 'data should be correct');

        });
    });
});
Example #14
Source File: modal.service.spec.ts    From canopy with Apache License 2.0 4 votes vote down vote up
describe('LgModalService', () => {
  const id = 'test-1';
  let service: LgModalService;
  let serviceSpy: LgModalService;
  let subscription: Subscription;

  beforeEach(
    waitForAsync(() => {
      service = TestBed.inject(LgModalService);
    }),
  );

  beforeEach(() => {
    serviceSpy = spy(service);
    service.add(id);
  });

  afterEach(() => {
    subscription?.unsubscribe();
  });

  it('should be created', () => {
    expect(service).toBeTruthy();
  });

  it('should push true to the state of the specific modal when calling the #open fn', (done: DoneFn) => {
    service.open(id);

    subscription = service['states'].get(id).subscribe(data => {
      expect(data).toBeTrue();
      done();
    });
  });

  it('should push false to the state of the specific modal when calling the #close fn', (done: DoneFn) => {
    service.close(id);

    subscription = service['states'].get(id).subscribe(data => {
      expect(data).toBeFalse();
      done();
    });
  });

  describe('isOpen$', () => {
    it('should return the state observable for the specific modal', (done: DoneFn) => {
      service['states'].get(id).next(true);

      subscription = service.isOpen$(id).subscribe(data => {
        expect(data).toBeTrue();
        done();
      });
    });

    it('should call #add when the modal doesn\'t exist', (done: DoneFn) => {
      subscription = service.isOpen$('test-2').subscribe(data => {
        verify(serviceSpy.add('test-2')).once();

        expect(data).toBeFalse();
        done();
      });
    });
  });

  it('should add a new item to the map when calling #add', () => {
    expect(service['states'].has(id)).toBeTrue();
    expect(service['states'].has('test-2')).toBeFalse();

    service.add('test-2');

    expect(service['states'].has(id)).toBeTrue();
    expect(service['states'].has('test-2')).toBeTrue();
  });

  it('should call #close and remove an item from the map when calling #remove', () => {
    expect(service['states'].has(id)).toBeTrue();

    service.remove(id);

    verify(serviceSpy.close(id)).once();

    expect(service['states'].has(id)).toBeFalse();
  });
});
Example #15
Source File: modal.component.spec.ts    From canopy with Apache License 2.0 4 votes vote down vote up
describe('LgModalComponent', () => {
  let component: LgModalComponent;
  let cdrMock: ChangeDetectorRef;
  let fixture: MockedComponentFixture<LgModalComponent>;
  let modalServiceMock: LgModalService;
  const id = 'test-1';
  const isModalOpen$ = new BehaviorSubject<boolean>(false);

  beforeEach(
    waitForAsync(() => {
      cdrMock = mock(ChangeDetectorRef);
      modalServiceMock = mock(LgModalService);

      TestBed.configureTestingModule({
        declarations: [
          LgModalComponent,
          MockComponents(LgModalHeaderComponent, LgModalBodyComponent),
        ],
        imports: [ MockModule(LgCardModule), MockModule(LgFocusModule) ],
        providers: [
          { provide: LgModalService, useValue: instance(modalServiceMock) },
          { provide: ChangeDetectorRef, useValue: instance(cdrMock) },
        ],
      }).compileComponents();

      when(modalServiceMock.isOpen$(anything())).thenReturn(isModalOpen$);
    }),
  );

  beforeEach(() => {
    fixture = MockRender(`
      <lg-modal [id]="id">
        <lg-modal-header></lg-modal-header>
        <lg-modal-body></lg-modal-body>
      </lg-modal>
    `);

    component = fixture.debugElement.children[0].componentInstance;
    component.id = id;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });

  describe('on init', () => {
    it('should update isOpen', () => {
      isModalOpen$.next(true);

      expect(component.isOpen).toBe(true);
    });

    it('should add the overflow style to the body and emit an open event if the modal is open', () => {
      const openEmitterSpy = spy(component.open);

      isModalOpen$.next(true);

      verify(openEmitterSpy.emit()).once();

      fixture.detectChanges();
      const bodyEl: HTMLBodyElement = document.querySelector('body');

      expect(bodyEl.style.overflow).toEqual('hidden');
    });

    it('should remove the overflow style on the body and emit a closed event if the modal is close', () => {
      const closedEmitterSpy = spy(component.closed);

      isModalOpen$.next(false);

      verify(closedEmitterSpy.emit()).once();

      fixture.detectChanges();
      const bodyEl: HTMLBodyElement = document.querySelector('body');

      expect(bodyEl.style.overflow).toEqual('');
    });

    it('should detect changes', () => {
      const cdrDetectChangesSpy = spyOn(component['cdr'], 'detectChanges');

      isModalOpen$.next(true);

      expect(cdrDetectChangesSpy).toHaveBeenCalledTimes(1);
    });
  });

  it('should update the modal header and body id on #ngAfterContentInit', () => {
    component.ngAfterContentInit();

    expect(component.modalHeaderComponent.id).toEqual('lg-modal-header-test-1');
    expect(component.modalBodyComponent.id).toEqual('lg-modal-body-test-1');
  });

  describe('on keydown', () => {
    const escEvent = new KeyboardEvent('keydown', {
      key: keyName.KEY_ESCAPE,
    });

    it('should close the modal when escape key is pressed and the modal is open', () => {
      component.isOpen = true;
      component.onKeydown(escEvent);

      verify(modalServiceMock.close(id)).once();

      expect().nothing();
    });

    it('shouldn\'t close the modal when any other key is pressed', () => {
      component.isOpen = true;
      const event = new KeyboardEvent('keydown', {
        key: keyName.KEY_UP,
      });

      component.onKeydown(event);

      verify(modalServiceMock.close(id)).never();

      expect().nothing();
    });

    it('shouldn\'t close the modal when the modal is already closed', () => {
      component.isOpen = false;
      component.onKeydown(escEvent);

      verify(modalServiceMock.close(id)).never();

      expect().nothing();
    });
  });

  describe('clicking on the modal panel', () => {
    it('should stop the propagation of the event', () => {
      const event = new Event('click');

      spyOn(event, 'stopPropagation').and.callThrough();
      component.onModalClick(event);

      expect(event.stopPropagation).toHaveBeenCalledTimes(1);
    });
  });
});
Example #16
Source File: radio-button.component.spec.ts    From canopy with Apache License 2.0 4 votes vote down vote up
describe('LgRadioButtonComponent', () => {
  let component: LgRadioButtonComponent;
  let testComponent: TestRadioButtonComponent;
  let fixture: ComponentFixture<LgRadioButtonComponent>;
  let testFixture: ComponentFixture<TestRadioButtonComponent>;
  let errorStateMatcherMock: LgErrorStateMatcher;
  let radioGroupMock: LgRadioGroupComponent;
  let hintDebugElement: DebugElement;
  let inputDebugElement: DebugElement;

  beforeEach(
    waitForAsync(() => {
      errorStateMatcherMock = mock(LgErrorStateMatcher);
      radioGroupMock = mock(LgRadioGroupComponent);
      when(radioGroupMock.name).thenReturn('color');
      when(radioGroupMock.variant).thenReturn('segment');

      TestBed.configureTestingModule({
        imports: [ FormsModule, ReactiveFormsModule ],
        declarations: [
          LgRadioButtonComponent,
          LgRadioGroupComponent,
          TestRadioButtonComponent,
          MockComponents(LgHintComponent),
        ],
        providers: [
          {
            provide: LgRadioGroupComponent,
            useFactory: () => instance(radioGroupMock),
          },
          {
            provide: LgErrorStateMatcher,
            useFactory: () => instance(errorStateMatcherMock),
          },
        ],
      }).compileComponents();

      fixture = TestBed.createComponent(LgRadioButtonComponent);
      component = fixture.componentInstance;

      fixture.detectChanges();

      testFixture = TestBed.createComponent(TestRadioButtonComponent);
      testComponent = testFixture.componentInstance;

      testFixture.detectChanges();

      inputDebugElement = testFixture.debugElement.queryAll(By.css('input'))[1];
      hintDebugElement = testFixture.debugElement.query(By.directive(LgHintComponent));
    }),
  );

  it('sets its name from the radio group name', () => {
    expect(component.name).toBe('color');
  });

  describe('the variant', () => {
    it('should be set based on the radio group variant', () => {
      expect(component.variant).toBe('segment');
    });

    it('should set the correct class modifier', () => {
      expect(fixture.debugElement.nativeElement.getAttribute('class')).toContain(
        'lg-radio-button--segment',
      );

      when(radioGroupMock.variant).thenReturn('radio');
      fixture = TestBed.createComponent(LgRadioButtonComponent);
      component = fixture.componentInstance;

      expect(fixture.debugElement.nativeElement.getAttribute('class')).not.toContain(
        'lg-radio-button--segment',
      );
    });
  });

  // https://github.com/NagRock/ts-mockito/issues/120
  xit('sets the radio group value when checked', () => {
    component.value = 'red';
    const radio = fixture.debugElement.query(By.css('input'));

    radio.triggerEventHandler('click', null);
    fixture.detectChanges();
    verify(radioGroupMock.value).called();

    expect().nothing();
  });

  it('sets the disabled property when the radio group is disabled', () => {
    when(radioGroupMock.disabled).thenReturn(true);
    fixture.detectChanges();

    expect(component.disabled).toBe(true);
  });

  // https://github.com/NagRock/ts-mockito/issues/120
  xit('marks the radioGroup as touched if the radio is checked', () => {
    const radio = fixture.debugElement.query(By.css('input'));

    radio.triggerEventHandler('click', null);
    fixture.detectChanges();
    verify(radioGroupMock.onTouched()).once();

    expect().nothing();
  });

  it('sets the aria-invalid attribute to false when the input is valid', () => {
    when(errorStateMatcherMock.isControlInvalid(anything(), anything())).thenReturn(
      false,
    );

    fixture.detectChanges();
    const radio = fixture.debugElement.query(By.css('input'));

    expect(radio.nativeElement.getAttribute('aria-invalid')).toBe('false');
  });

  it('adds the error class and set aria-invalid to true if the form field is invalid', () => {
    when(errorStateMatcherMock.isControlInvalid(anything(), anything())).thenReturn(true);
    fixture.detectChanges();

    expect(fixture.debugElement.nativeElement.className).toContain(
      'lg-radio-button--error',
    );

    const radio = fixture.debugElement.query(By.css('input'));

    expect(radio.nativeElement.getAttribute('aria-invalid')).toBe('true');
  });

  it('links the hint to the input with the correct aria attributes', () => {
    expect(testComponent).not.toBe(null);
    expect(hintDebugElement.nativeElement.getAttribute('id').length).not.toEqual(0);

    expect(inputDebugElement.nativeElement.getAttribute('aria-describedBy')).toContain(
      hintDebugElement.nativeElement.getAttribute('id'),
    );
  });

  it('should emit an event when #onBlur is called', () => {
    const blurEmitterSpy = spy(component.blur);

    component.onBlur(new Event(''));
    verify(blurEmitterSpy.emit(anything())).once();
  });
});
Example #17
Source File: feature-toggle.guard.spec.ts    From canopy with Apache License 2.0 4 votes vote down vote up
describe('FeatureToggleGuard', () => {
  let configServiceMock: LgFeatureToggleService;
  let guard: FeatureToggleGuard;
  const routerMock = mock(Router);
  const enabledConfig = { parent: true };
  const disabledConfig = { parent: false };
  const enabledConfig2 = { parent: true, child: true };
  const disabledConfig2 = { parent: false, child: false };
  const routeSnapshot: Partial<ActivatedRouteSnapshot> = {
    data: { featureToggle: 'parent' },
    children: [
      {
        data: { featureToggle: 'child' },
      } as any,
    ],
  };

  const checkGuardConfigs = (
    guardType: GuardTypes,
    config,
    marbleValue: boolean,
    onceVerify: boolean = false,
  ) => {
    /* eslint-disable @typescript-eslint/no-unused-expressions, no-unused-expressions */
    onceVerify
      ? when(configServiceMock.toggles$).thenReturn(config)
      : when(configServiceMock.toggles$).thenReturn(of(config));
    /* eslint-enable */

    switch (guardType) {
      case GuardTypes.CAN_ACTIVATE:

        expect(guard.canActivate(routeSnapshot as ActivatedRouteSnapshot)).toBeObservable(
          cold('(a|)', { a: marbleValue }),
        );

        break;

      case GuardTypes.CAN_ACTIVATE_CHILD:

        expect(
          guard.canActivateChild(routeSnapshot as ActivatedRouteSnapshot),
        ).toBeObservable(cold('(a|)', { a: marbleValue }));

        break;

      case GuardTypes.CAN_LOAD:

        expect(guard.canLoad(routeSnapshot as Route)).toBeObservable(
          cold('(a|)', { a: marbleValue }),
        );

        break;
    }

    return verify(
      routerMock.navigate(deepEqual([ '/' ]), deepEqual({ queryParamsHandling: 'merge' })),
    );
  };

  beforeEach(() => {
    configServiceMock = mock(LgFeatureToggleService);

    TestBed.configureTestingModule({
      providers: [
        FeatureToggleGuard,
        {
          provide: LgFeatureToggleService,
          useFactory: () => instance(configServiceMock),
        },
        { provide: Router, useFactory: () => instance(routerMock) },
      ],
    });

    guard = TestBed.inject(FeatureToggleGuard);
  });

  describe('can activate', () => {
    it('should be true when the parent is enabled', () => {
      checkGuardConfigs(GuardTypes.CAN_ACTIVATE, enabledConfig, true).never();
      reset(routerMock);
    });

    it('should be true when the parent and child is enabled', () => {
      checkGuardConfigs(GuardTypes.CAN_ACTIVATE, enabledConfig2, true).never();
      reset(routerMock);
    });

    it('should be false when the parent is disabled', () => {
      checkGuardConfigs(GuardTypes.CAN_ACTIVATE_CHILD, disabledConfig, false).once();
      reset(routerMock);
    });

    it('should be false when the parent is enabled but not child', () => {
      checkGuardConfigs(GuardTypes.CAN_ACTIVATE, disabledConfig2, false).once();
      reset(routerMock);
    });
  });

  describe('can activate child', () => {
    it('should be true when the parent is enabled', () => {
      checkGuardConfigs(GuardTypes.CAN_ACTIVATE_CHILD, of(enabledConfig), true).never();
      reset(routerMock);
    });

    it('should be true when the parent and child is enabled', () => {
      checkGuardConfigs(GuardTypes.CAN_ACTIVATE_CHILD, of(enabledConfig2), true).never();
      reset(routerMock);
    });

    it('should be false when the parent is disabled', () => {
      checkGuardConfigs(
        GuardTypes.CAN_ACTIVATE_CHILD,
        of(disabledConfig),
        false,
        true,
      ).once();

      reset(routerMock);
    });

    it('should be false when the parent is enabled but not child', () => {
      checkGuardConfigs(
        GuardTypes.CAN_ACTIVATE_CHILD,
        of(disabledConfig2),
        false,
        true,
      ).once();

      reset(routerMock);
    });
  });

  describe('can load', () => {
    it('should be true when the parent is enabled', () => {
      checkGuardConfigs(GuardTypes.CAN_LOAD, of(enabledConfig), true).never();
      reset(routerMock);
    });

    it('should be true when the parent and child is enabled', () => {
      checkGuardConfigs(GuardTypes.CAN_LOAD, of(enabledConfig2), true).never();
      reset(routerMock);
    });

    it('should be false when the parent is disabled', () => {
      checkGuardConfigs(GuardTypes.CAN_LOAD, of(disabledConfig), false, true).once();
      reset(routerMock);
    });

    it('should be false when the parent is enabled but not child', () => {
      checkGuardConfigs(GuardTypes.CAN_LOAD, of(disabledConfig2), false, true).once();
      reset(routerMock);
    });
  });
});
Example #18
Source File: accordion-panel-heading.component.spec.ts    From canopy with Apache License 2.0 4 votes vote down vote up
describe('LgAccordionPanelHeadingComponent', () => {
  let component: LgAccordionPanelHeadingComponent;
  let fixture: ComponentFixture<LgAccordionPanelHeadingComponent>;
  let triggerElement;

  beforeEach(
    waitForAsync(() => {
      TestBed.configureTestingModule({
        declarations: [
          LgAccordionPanelHeadingComponent,
          MockComponents(LgHeadingComponent, LgIconComponent),
        ],
      }).compileComponents();
    }),
  );

  beforeEach(() => {
    fixture = TestBed.createComponent(LgAccordionPanelHeadingComponent);
    component = fixture.componentInstance;
    component.headingLevel = 2;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });

  describe('#toggle', () => {
    beforeEach(() => {
      triggerElement = fixture.debugElement.query(
        By.css('.lg-accordion__heading-toggle'),
      );
    });

    describe('when the accordion item is toggled open', () => {
      it('should set \'isActive\' to false', () => {
        component.isActive = true;
        component.toggle();

        expect(component.isActive).toBe(false);
      });

      it('should set the \'active\' class', () => {
        expect(
          triggerElement.nativeElement.classList.contains(
            'lg-accordion__heading-toggle--active',
          ),
        ).toBe(false);

        triggerElement.nativeElement.click();
        fixture.detectChanges();

        expect(
          triggerElement.nativeElement.classList.contains(
            'lg-accordion__heading-toggle--active',
          ),
        ).toBe(true);
      });

      it('should set the `aria-expanded` attribute to true', () => {
        expect(triggerElement.attributes['aria-expanded']).toBe('false');

        triggerElement.nativeElement.click();
        fixture.detectChanges();

        expect(triggerElement.attributes['aria-expanded']).toBe('true');
      });
    });

    describe('when the accordion item is toggled close', () => {
      it('should set \'isActive\' to true', () => {
        component.isActive = false;
        component.toggle();

        expect(component.isActive).toBe(true);
      });

      it('should remove the `active` class', () => {
        triggerElement.nativeElement.click();
        fixture.detectChanges();

        expect(
          triggerElement.nativeElement.classList.contains(
            'lg-accordion__heading-toggle--active',
          ),
        ).toBe(true);

        triggerElement.nativeElement.click();
        fixture.detectChanges();

        expect(
          triggerElement.nativeElement.classList.contains(
            'lg-accordion__heading-toggle--active',
          ),
        ).toBe(false);
      });

      it('should set the `aria-expanded` attribute to false', () => {
        triggerElement.nativeElement.click();
        fixture.detectChanges();

        expect(triggerElement.attributes['aria-expanded']).toBe('true');

        triggerElement.nativeElement.click();
        fixture.detectChanges();

        expect(triggerElement.attributes['aria-expanded']).toBe('false');
      });
    });

    it('should emit an event with the value of \'isActive\'', () => {
      const componentEventSpy = spy(component.toggleActive);

      component.toggle();

      verify(componentEventSpy.emit(true)).once();

      expect().nothing();
    });
  });
});
Example #19
Source File: userStorage.spec.ts    From space-sdk with MIT License 4 votes vote down vote up
describe('UserStorage', () => {
  describe('createFolder()', () => {
    it('should throw error if user is not authenticated', async () => {
      const storage = new UserStorage({ identity: mockIdentity, token: '', endpoint: '' });
      await expect(storage.createFolder({ bucket: '', path: '' })).to.eventually.be.rejectedWith(UnauthenticatedError);
    });

    it('should push empty .keep file to bucket at specified path', async () => {
      const createFolderRequest = { bucket: 'personal', path: 'topLevel' };
      const { storage, mockBuckets } = initStubbedStorage();

      await storage.createFolder(createFolderRequest);

      verify(
        mockBuckets.pushPath(
          'myBucketKey',
          '.keep',
          deepEqual({
            path: '/topLevel/.keep',
            content: Buffer.from(''),
          }),
        ),
      ).called();
    });
  });

  describe('listDirectory()', () => {
    it('should throw error if user is not authenticated', async () => {
      const storage = new UserStorage({ identity: mockIdentity, token: '', endpoint: '' });
      await expect(storage.listDirectory({ bucket: 'bucket', path: '' })).to.eventually.be.rejectedWith(
        UnauthenticatedError,
      );
    });

    it('should return list of items', async () => {
      const listDirectoryRequest = { bucket: 'personal', path: 'topLevel' };

      const mainItem = mock<PathItem>();

      const childItem = {
        name: 'folder',
        path: '/ipfs/Qm123/folder',
        cid: 'Qm...',
        isDir: true,
        size: 10,
      };

      const updatedAt = (new Date().getMilliseconds()) * 1000000;

      const { storage, mockBuckets } = initStubbedStorage();
      when(mockBuckets.listPath('myBucketKey', `/${listDirectoryRequest.path}`, 0)).thenResolve({
        item: {
          ...mainItem,
          items: [
            {
              ...childItem,
              metadata: {
                updatedAt,
                roles: new Map(),
              },
              items: [],
              count: 1,
            },
          ],
        },
      });

      const mockMembers = new Map<string, PathAccessRole>();
      const pubkey = 'bbaareieswor4fnmzdwmv6fwij2rxyyjmpc2izognkiqnfxlvnzzsvs7y5y';
      mockMembers.set(pubkey, PathAccessRole.PATH_ACCESS_ROLE_WRITER);
      when(mockBuckets.pullPathAccessRoles(anyString(), anyString())).thenResolve(mockMembers);

      const result = await storage.listDirectory(listDirectoryRequest);

      const expectedDate = dayjs(new Date(Math.round(updatedAt / 1000000))).format();

      expect(result).to.not.equal(undefined);
      expect(result.items[0]).to.not.equal(undefined);
      expect(result.items[0].name).to.equal(childItem.name);
      expect(result.items[0].bucket).to.not.be.empty;
      expect(result.items[0].dbId).to.not.be.empty;
      expect(result.items[0].ipfsHash).to.equal(childItem.cid);
      expect(result.items[0].isDir).to.equal(childItem.isDir);
      expect(result.items[0].sizeInBytes).to.equal(childItem.size);
      expect(result.items[0].created).to.equal(expectedDate);
      expect(result.items[0].updated).to.equal(expectedDate);
      expect(result.items[0].fileExtension).to.equal('');
      expect(result.items[0].isLocallyAvailable).to.equal(false);
      expect(result.items[0].backupCount).to.equal(1);
      expect(result.items[0].members).to.deep.equal([{
        publicKey: Buffer.from(tryParsePublicKey(pubkey).pubKey).toString('hex'),
        role: PathAccessRole.PATH_ACCESS_ROLE_WRITER,
        address: GetAddressFromPublicKey(pubkey),
      }]);
      expect(result.items[0].isBackupInProgress).to.equal(false);
      expect(result.items[0].isRestoreInProgress).to.equal(false);
      expect(result.items[0].uuid).to.equal('generated-uuid');
    });
  });

  describe('openFile()', () => {
    // it('should throw error if user is not authenticated', async () => {
    //   const storage = new UserStorage({ identity: mockIdentity, token: '' });
    //   await expect(storage.openFile({ bucket: 'bucket', path: '' })).to.eventually.be.rejectedWith(
    //     UnauthenticatedError,
    //   );
    // });

    it('should throw if file is not found', async () => {
      const { storage, mockBuckets } = initStubbedStorage();
      when(mockBuckets.pullPath('myBucketKey', '/file.txt', anything())).thenThrow(
        new Error('Error: no link named "file.txt" under QmVQWu2C3ZgdoAmBsffFASrgynAfgvYX8CCK4o9SxRvC4p'),
      );

      await expect(storage.openFile({ bucket: 'personal', path: '/file.txt' })).to.eventually.be.rejectedWith(
        DirEntryNotFoundError,
      );
    });

    it('should return a valid stream of files data', async () => {
      const { storage, mockBuckets } = initStubbedStorage();
      const actualFileContent = "file.txt's file content";

      when(mockBuckets.pullPath('myBucketKey', '/file.txt', anything())).thenReturn(
        // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
        // @ts-ignore
        newEncryptedDataWriter(actualFileContent, decodeFileEncryptionKey(encryptionKey)),
      );

      const result = await storage.openFile({ bucket: 'personal', path: '/file.txt' });
      const filesData = await result.consumeStream();

      expect(new TextDecoder('utf8').decode(filesData)).to.equal(actualFileContent);
      expect(result.mimeType).to.equal('generic/type');
    });
  });

  describe('openFileByUuid', () => {
    // it('should throw if uuid is not found', async () => {
    //  // fix this when mocking metadatastore works
    // });

    it('should return a valid stream of files data', async () => {
      const { storage, mockBuckets } = initStubbedStorage();
      const fileUuid = v4();
      const actualFileContent = "file.txt's file content";
      when(mockBuckets.existing('mockThreadId')).thenReturn(Promise.resolve([
        {
          ...mock<Root>(),
          name: 'myBucket',
          key: 'myBucketKey',
        },
      ]));
      when(mockBuckets.listPath('myBucketKey', anyString())).thenResolve({
        item: {
          ...mock<PathItem>(),
          name: 'file.txt',
          path: '/ipfs/Qm123/file.txt',
          metadata: {
            updatedAt: (new Date().getMilliseconds()) * 1000000,
            roles: new Map(),
          },
          items: [],
        },
      });

      when(mockBuckets.pullPath('myBucketKey', anyString(), anything())).thenReturn(
        // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
        // @ts-ignore
        newEncryptedDataWriter(actualFileContent, decodeFileEncryptionKey(encryptionKey)),
      );

      const mockMembers = new Map<string, PathAccessRole>();
      mockMembers.set('dummykey', PathAccessRole.PATH_ACCESS_ROLE_WRITER);
      when(mockBuckets.pullPathAccessRoles('myBucketKey', '/ipfs/Qm123/file.txt')).thenResolve(mockMembers);

      const result = await storage.openFileByUuid({ uuid: fileUuid });
      const filesData = await result.consumeStream();

      expect(new TextDecoder('utf8').decode(filesData)).to.equal(actualFileContent);
      expect(result.mimeType).to.equal('generic/type');
      expect(result.entry.bucket).to.not.be.empty;
      expect(result.entry.dbId).to.not.be.empty;
    });
  });

  describe('addItems()', () => {
    it('should publish data, error and done events correctly', async () => {
      const { storage, mockBuckets } = initStubbedStorage();
      const uploadError = new Error('update is non-fast-forward');
      when(mockBuckets.pushPath('myBucketKey', anyString(), anything(), anything())).thenResolve({
        ...mock<PushPathResult>(),
      });

      const childItem = {
        name: 'entryName',
        path: '/ipfs/Qm123/entryName',
        cid: 'Qm...',
        isDir: false,
        size: 10,
      };

      when(mockBuckets.listPath('myBucketKey', anyString())).thenResolve({
        item: {
          ...mock<PathItem>(),
          name: 'entryName',
          path: '/ipfs/Qm123/entryName',
          cid: 'Qm...',
          isDir: false,
          size: 10,
          metadata: {
            updatedAt: (new Date().getMilliseconds()) * 1000000,
            roles: new Map<string, PathAccessRole>(),
          },
          count: 0,
          items: [],
        },
      });

      // fail upload of b.txt
      when(mockBuckets.pushPath('myBucketKey', '/b.txt', anything(), anything())).thenReject(uploadError);
      const callbackData = {
        data: [] as AddItemsEventData[],
        error: [] as AddItemsEventData[],
        done: [] as AddItemsEventData[],
      };

      // upload files
      const uploadResponse = await storage.addItems({
        bucket: 'personal',
        files: [
          {
            path: '/top/a.txt',
            data: 'a content',
            mimeType: 'text/plain',
          },
          {
            path: 'b.txt',
            data: 'b content',
            mimeType: 'text/plain',
          },
        ],
      });

      // listen for status events
      uploadResponse.on('data', (it) => callbackData.data.push(it));
      uploadResponse.on('error', (err) => callbackData.error.push(err));
      await new Promise((resolve) => {
        uploadResponse.once('done', (it) => {
          callbackData.done.push(it);
          resolve();
        });
      });

      // verify callback data
      expect(callbackData.data).to.containSubset([
        { path: '/top/a.txt', status: 'success' },
        { path: '/top', status: 'success' },
      ]);
      expect(callbackData.error).to.containSubset([{ path: '/b.txt', status: 'error', error: uploadError }]);
      expect(callbackData.done).to.containSubset([
        {
          bucket: 'personal',
          files: [
            { path: '/top', status: 'success' },
            { path: '/top/a.txt', status: 'success' },
            { path: '/b.txt', status: 'error', error: uploadError },
          ],
        },
      ]);
    });
  });

  describe('shareViaPublicKey()', () => {
    let storage: UserStorage;
    let mockBuckets: Buckets;

    beforeEach(() => {
      const stub = initStubbedStorage();
      storage = stub.storage;
      mockBuckets = stub.mockBuckets;
    });

    it('should throw if public keys are empty', async () => {
      await expect(
        storage.shareViaPublicKey({
          publicKeys: [],
          paths: [
            {
              bucket: 'personal',
              path: '/randomPath',
              uuid: v4(),
            },
          ],
        }),
      ).to.eventually.be.rejected;
    });

    it('should throw if public keys are not valid', async () => {
      await expect(
        storage.shareViaPublicKey({
          publicKeys: [{
            id: '[email protected]',
            pk: 'invalid-pk-provided',
          }],
          paths: [
            {
              bucket: 'personal',
              path: '/randomPath',
              uuid: v4(),
            },
          ],
        }),
      ).to.eventually.be.rejectedWith('Unsupported encoding: i');
    });
  });
});