Lawrence  Lesch

Lawrence Lesch

1654068840

Marko-jest: Jest Marko Transformer, Import .marko Files in Jest Tests

Marko Jest  

[DEPRECATED] Jest Marko transformer and rendering test utility.

DEPRECATED ⚠

This module is deprecated and no longer maintained, in favour of the official @marko/jest 🖖

What is this?

Transformer and rendering test library for Marko 4 component with Jest & JSDOM.

  • Renders Marko component on JSDOM
  • Supports rendering and client-side behaviour testing
  • Snapshot testing
  • TypeScript support

Requirements

  • Jest: 23.x
  • Marko: ^4.9.0

Setup

Add marko-jest to your dev dependencies. You could do it by yarn add marko-jest --dev or npm install marko-jest --save-dev.

Register marko preprocessor/transformer on your Jest config. This allows Jest to process and compile Marko file. Add the following lines to the Jest transform section:

// package.json or jest config
{
  ...

  "jest": {
    "transform": {
      "^.+\\.marko$": "<rootDir>/node_modules/marko-jest/preprocessor.js"
    },
    ...
  },

  ...
}

Quick Start

These are a quick steps to test a Marko component with marko-jest:

Require marko-jest module and use the init function to initiate the Marko component you want to test. This is the way to 'require' Marko component on test files.

The init function will return render function which you can use to render the initiated Marko component.

// __tests__/component.spec.js
import { init } from 'marko-jest';
// or const { init } = require('marko-jest');

// init() requires full path to Marko component
const componentPath = path.resolve(__dirname, '../index.marko');
const { render } = init(componentPath);

describe('test-button', () => {
  ...
});

The render function returns RenderResult object which allows you to get the component instance. Use the component instance to access its properties (e.g el, els, or state) or methods (e.g getEl(), update(), rerender()) for testing.

// __tests__/component.spec.js
import { init, cleanup } from 'marko-jest';

const componentPath = path.resolve(__dirname, '../index.marko');
const { render } = init(componentPath);

describe('test-button', () => {
  let renderResult;

  afterEach(cleanup);

  describe('on rendering', () => {
    const input = { label: 'Click here' };

    beforeEach(async () => {
      renderResult = await render(input);
    });

    it('should render a link given default input', () => {
      const button = renderResult.component.el.querySelector('a');
      expect(button).toBeDefined();
    });
  });
});

Component Rendering Test

One way to test a component is to test its generated HTML. You can access it from the RenderResult object returned by the render function.

You can use the following methods/property from the RenderResult object:

  • Property component: component instance. You can access the output HTML element using Marko component instance's properties (such as el or els), or methods (getEl(key) or getEls(key)).
  • Property container: the test container element, which is a div element. Behind the scene, marko-jest render function automatically creates a test container and renders the component inside it.
  • Method getNodes: return the list of rendered HTML elements. Usually useful for snapshot testing (see next section).

Once you get the HTML element, you can use any native HTML methods to assert if a certain element or class is existed.

Examples:

// container
it('should render icon DOWN', () => {
  const iconEl = return renderResult.container.querySelector('.btn__icon');
  expect(iconEl.innerHTML).toContain('#svg-icon-chevron-down');
});

// component instance with property el
it('should render a link given default input', () => {
  const ctaLink = rendereResult.component.el.querySelector('main-cta');
  expect(ctaLink.textContent).toBe('Shop Now');
});

// component instance with getEl() if you have key attribute inside Marko template
it('should render a link given default input', () => {
  const button = component.getEl('main-cta');
  expect(button).toBeDefined();
});

// component instance with getEls()
it('should render benefit links', () => {
  const benefitLinks = component.getEls('benefits');
  expect(benefitLinks.lenth).toBeGreaterThan(2);
});

Accessing Non-Element Nodes

Marko's getEl() and getEls() returns HTML elements only, which means it does not return any non-element nodes such as text and comment nodes. If you want to access element & non-elements (e.g for snapshot testing), you can use RenderResult getNodes() which will return array of all Nodes, including HTML elements, text, and comment nodes.

it('should render text node', () => {
  const nodes = renderResult.getNodes();

  expect(nodes[0].nodeType).toEqual(Node.TEXT_NODE);
});

A use case for this is you have a component which can render a text node without any HTML element as container

// span-or-text-component.marko
<span body-only-if(!input.showSpan)>
  ${input.text}
</span>
// test-span-or-text-component.spec.js
import { init, cleanup } from 'marko-jest';
const { render } = init(path.resolve(__dirname, './resources/body-only-item/index.marko'));

describe('span-or-text component', () => {
  let renderResult;

  afterEach(cleanup);

  it('should render component as a span element', async () => {
    renderResult = await render({ showSpan: true, text: 'test' });
    const nodes = renderResult.getNodes();

    expect(nodes[0].nodeName).toEqual('SPAN');
    expect(nodes[0].nodeType).toEqual(Node.ELEMENT_NODE);
  });

  it('should render component as a text node', async () => {
    renderResult = await render({ showSpan: false, text: 'test' });
    const nodes = renderResult.getNodes();

    expect(nodes[0].nodeName).toEqual('#text');
    expect(nodes[0].nodeType).toEqual(Node.TEXT_NODE);
  });
});

Snapshot testing

You can utilize Jest snapshot testing to test component rendering. The RenderResult getNodes() will return array of HTML elements which we can use for Jest snapshot feature.

Example:

// __tests__/component.spec.js
import * as path from 'path';
import { init, cleanup } from 'marko-jest';

const componentPath = path.resolve(__dirname, '../index.marko');
const { render } = init(componentPath);

describe('test-button', () => {
  afterEach(cleanup);

  it('should render correctly given default input', async () => {
    const input = { label: 'Click here' };
    const renderResult = await render(input);

    expect(renderResult.getNodes()).toMatchSnapshot();
  });
});

Behaviour Testing

You can test component behaviour (e.g click handler) by triggering event though the HTML element.

Example on testing a toggle button:

// index.marko
class {
  onCreate() {
    this.state = {
      clicked: false
    };
  }

  toggleButton() {
    this.state.clicked = !this.state.clicked;
  }
}

<button class="btn" on-click('toggleButton')>
  <span if(state.clicked)>DONE</span>
  <span else>Click me</span>
</button>

You can access the button element and trigger the click:

// __tests__/index.spec.js
import * as path from 'path';
import { init, cleanup } from 'marko-jest';

const componentPath = path.resolve(__dirname, '../index.marko');
const { render } = init(componentPath);

describe('test-simple-button', () => {
  let component;

  afterEach(cleanup);

  describe('on rendering', () => {
    let mainButton;

    beforeEach(async () => {
      const renderResult = await render({ });

      component = renderResult.component;
      mainButton = component.getEl('rootButton');
    });

    it('should render a button', () => {
      expect(mainButton).toBeTruthy();
    });

    it('should render default label', () => {
      const buttonLabel = mainButton.textContent;
      expect(buttonLabel).toEqual('Click me');
    });

    describe('when clicked', () => {
      beforeEach(() => {
        mainButton.click();
        component.update();
      });

      it('should change the button label', () => {
        const buttonLabel = mainButton.textContent;
        expect(buttonLabel).toEqual('DONE');
      });
    });
  });
});

You can also combine it with snapshot testing:

import * as path from 'path';
import { init, cleanup } from 'marko-jest';

const componentPath = path.resolve(__dirname, '../index.marko');
const { render } = init(componentPath);

describe('test-simple-button', () => {
  let renderResult;
  let component;

  afterEach(cleanup);

  describe('on rendering', () => {
    beforeEach(async () => {
      renderResult = await render({ });
      component = renderResult.component;
    });

    it('should render correctly', () => {
      expect(renderResult.getNodes()).toMatchSnapshot();
    });

    describe('when clicked', () => {
      beforeEach(() => {
        component.getEl('rootButton').click();
        component.update();
      });

      it('should update the element', () => {
        expect(renderResult.getNodes()).toMatchSnapshot();
      });
    });
  });
});

TypeScript Support

marko-jest module provides TypeScript type definition. Make sure you also install type definition for Marko by adding module @types/marko to your project.

Shallow Rendering

marko-jest can do shallow rendering on external component. If you use external Marko component module/library (such as ebayui-core), you can exclude those components from being rendered deeply by adding the module name to Jest globals config taglibExcludePackages. marko-jest will use Marko's taglibFinder.excludePackage() to prevent any components from those modules to be rendered.

For example, if you want to do shallow rendering on all components from @ebay/ebayui-core module, add the module name to Jest globals config:

// package.json
{
  ...

  "jest": {
    "transform": {
      ...
    },
    ...
    "globals": {
      "marko-jest": {
        "taglibExcludePackages": [
          "@ebay/ebayui-core",
          "marko-material"
        ]
      }
    }
  },

  ...
}

Now Marko Jest will render your Marko component:

// cta-component.marko
<section>
  <ebay-button priority="primary" on-click('toggleButton')>
    PAY
  </ebay-button>
</section>

As:

<section>
  <ebay-button priority="primary">PAY</ebay-button>
<section>

Instead of

<section>
  <button type="button" class="btn btn--primary">PAY</button>
<section>

One of the advantages of shallow rendering is to isolate your unit test so you can focus on testing your component instead of the external ones. On the example above, if the ebay-button implementation has changed (e.g css class name or new attribute added), your snapshot test will not failed.

Current Limitation of marko-jest shallow rendering

  • The shallow rendering will affect ALL test suites, you cannot turn it on or off during runtime.
  • You can only do shallow rendering on external modules. Unfortunately, you cannot do shallow rendering on component from the same project. The only workaround so far is to separate your UI component as external module (npm package) and consume it on your project.

marko-jest APIs

marko-jest API provides 2 high level functions: init and cleanup.

init(fullPathToMarkoComponent: string): InitResult

This is a way to 'require' Marko component on test file. It requires full path to Marko component.

At the moment, you can't easily require Marko component on Node.js with JSDOM. By default, when a Marko component is required on Node.js, you can only do server-side-only component. This means you can render the component as HTML but without any browser-side features such as render to virtual DOM, DOM event handling, or browser-side lifecycle.

init function will 'trick' Marko to require a component on Node.js as if it's done on browser. Therefore, the required component will have all browser-side features, including component rendering.

The init function will return an object InitResult which has:

  • property componentClass: Component, the Class of require/init-ed Marko Component. Quite useful if you want to spy on Marko component lifecycle method.
  • function render(input: any): Promise<RenderResult>: Asynchronously render the component using the given input. This will return a promise which will be resolved with an instance of RenderResult.

The RenderResult is the result of component rendering which has:

  • property component: Component: the rendered component instance. Use this instance to access any Marko component properties or methods.
  • property container: HTMLElement: the test container element, which is a div element. Behind the scene, marko-jest render function automatically creates a test container and renders the component inside it.
  • method getNodes(): HTMLElement[]: return the list of any rendered HTML elements. This method is better than Marko's getEl() and getEls() which does not return any non-element nodes such as text and comment nodes. If you want to access element & non-elements (e.g for snapshot testing), you can use getNodes() which will return array of all Nodes, including HTML elements, text, and comment nodes.

cleanup(): void

Remove all test containers created by the render function. Totally recommended to call cleanup on Jest afterEach.

For more info about marko-jest API, you can check the TypeScript type definition here

Known Issues

  • Failed rendering Marko component with custom transformer
  • Limited support of shallow rendering, see Shallow Rendering above or #1

Roadmap

Planned new features and improvements:

  • Better support of shallow and deep rendering.

Contributing

Contributing guidelines is still WIP but you're welcome to contribute by creating issues or Pull Request.

Author: Abiyasa
Source Code: https://github.com/abiyasa/marko-jest 
License: MIT license

#javascript #jest #tests 

What is GEEK

Buddha Community

Marko-jest: Jest Marko Transformer, Import .marko Files in Jest Tests

Como Exportar Uma Função De C++ Para React Native

Hoje, continuo compartilhando minha experiência com o Módulo Nativo e C++.

Como veremos muitas bibliotecas C/C++ escrevendo para plataformas móveis, precisamos implementá-las em nosso aplicativo iOS ou React Native. É por isso que quero escrever um artigo sobre como exportar uma função de C++ para React Native, que é fácil de entender e economiza tempo para iniciantes. Vou começar com um novo aplicativo nativo de reação

1. Crie um novo aplicativo nativo de reação, abra seu terminal e execute

npx react-native init NativeModules

2. Abra o Xcode e navegue até NativeModules/ios/NativeModule.xcworkspace

3. Trabalhando no lado C++

Crie um novo arquivo C++ e nomeie-oCpp_to_RN.cpp

Quando criamos um novo arquivo C++, o Xcode criará um arquivo de cabeçalho Cpp_to_RN.hpp para nós

Primeiro, abra o arquivo “ Cpp_to_RN.hpp e crie uma classe que inclua uma função sem o corpo.

#ifndef Cpp_to_RN_hpp
#define Cpp_to_RN_hpp#include <stdio.h>
#include <string>class Cpp_to_RN {
public:
    std::string sayHello();
};#endif /* Cpp_to_RN_hpp */

Em seguida, abra o Cpp_to_RN.cpparquivo e escreva uma função simples “ sayHello()

#include "Cpp_to_RN.hpp"
std::string Cpp_to_RN::sayHello(){
    return "Hello from CPP";
}

4. Trabalhando no arquivo C++ de encapsulamento.

Para encapsular os arquivos C++ e exportá-los para o lado IOS (swift)

uma. Crie um arquivo Objective C e nomeie-oCpp_to_RN.m

Renomeie o Cpp_to_RN.m para Cpp_to_RN.mm

b. Abra o WrapCpp_to_RN.mm arquivo e escreva o conteúdo do corpo que envolverá a função sayHellodo arquivo C++.

#import <Foundation/Foundation.h>
#import "WrapCpp_to_RN.h"
#import "Cpp_to_RN.hpp"@implementation WrapCpp_to_RN- (NSString *) sayHello {
  Cpp_to_RN fromCPP;
    std::string helloWorldMessage = fromCPP.sayHello();
    return [NSString
            stringWithCString:helloWorldMessage.c_str()
            encoding:NSUTF8StringEncoding];
}
@end

c. Crie um arquivo de cabeçalho e nomeie-oWrapCpp_to_RN.h

Exporte a wrapSayHellofunção para o arquivo Swift

#import <Foundation/Foundation.h>
@interface WrapCpp_to_RN : NSObject
- (NSString *) wrapSayHello;
@end

5. Trabalhando no lado iOS (Swift)

Para exportar a função C++ para React Native

uma. Crie um arquivo Swift e nomeie-oSendCpp_to_RN.swift

Observação: o Xcode nos pedirá para criar um NativeModules-Bridging-Header.harquivo para nós.

Crie uma classe SendCpp_to_RNe declare-a comoNSObject

#import <Foundation/Foundation.h>
@interface WrapCpp_to_RN : NSObject
- (NSString *) wrapSayHello;
@end

Escreva uma função requiresMainQueueSetup()para evitar avisos quando executamos o aplicativo

#import <Foundation/Foundation.h>
@interface WrapCpp_to_RN : NSObject
- (NSString *) wrapSayHello;
@end

Escreva uma função para envolver o WrapCpp_to_RN()fromWrapCpp_to_RN.mm

import Foundation@objc(SendCpp_to_RN)
class SendCpp_to_RN : NSObject {
    
  @objc static func requiresMainQueueSetup() -> Bool {
        return false
    }
  
  @objc func fromCpp(_ successCallback: RCTResponseSenderBlock) -> Void {
    successCallback([NSNull(), WrapCpp_to_RN().wrapSayHello() as Any])
    }}

b. Exporte uma função wrap no arquivo Swift para React Native

Crie um arquivo Objective C para exportar a classe Swift e sua função usandoCallback

#import <React/RCTBridgeModule.h>
#import <Foundation/Foundation.h>
#import "UIKit/UIKit.h"
@interface RCT_EXTERN_MODULE(SendCpp_to_RN, NSObject)RCT_EXTERN_METHOD(fromCpp:(RCTResponseSenderBlock)successCallback)@end

c. Conecte o Swift ao React Native, abra o NativeModules-Bridging-Header.h arquivo

#import <React/RCTBridgeModule.h>#import <React/RCTViewManager.h>#import "WrapCpp_to_RN.h"

6. Trabalhando no lado React Native

Chame a classe Swift e suas funções

import React from 'react';
import {StyleSheet, Text, View, NativeModules, Button} from 'react-native';const App = () => {
  const onPress = () => {
    const {SendCpp_to_RN} = NativeModules;
    SendCpp_to_RN.fromCpp((_err, res) => console.log(res));
  };
  return (
    <View style={styles.container}>
      <Text> Practice !</Text>
      <Button title="C++ to React Native" color="#841584" onPress={onPress} />
    </View>
  );
};
const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
});
export default App;

E pronto, basta executar o aplicativo

react-native run-ios

Ou apenas clique no botão “executar” no Xcode e veja o que fizemos.

Espero que meu artigo seja útil para você, obrigado pelo tempo de leitura.

 Fonte: https://betterprogramming.pub/native-modules-export-c-function-to-react-native-for-beginners-77e89934b210

#cpp #cplusplus #react 

坂本  篤司

坂本 篤司

1656981060

関数をC++からReactNativeにエクスポートする方法

今日も、ネイティブモジュールとC++での経験を共有し続けています。

多くのC/C ++ライブラリがモバイルプラットフォーム用に作成されているので、それらをiOSまたはReactNativeアプリケーションに実装する必要があります。そのため、関数をC++からReactNativeにエクスポートする方法についての記事を書きたいと思います。これは、理解しやすく、初心者の時間を節約できます。新しいreactネイティブアプリケーションから始めます

1.新しいreactネイティブアプリを作成し、ターミナルを開いて実行します

npx react-native init NativeModules

2. Xcodeを開き、NativeModules / ios/NativeModule.xcworkspaceに移動します

3.C++側での作業

新しいC++ファイルを作成し、名前を付けますCpp_to_RN.cpp

新しいC++ファイルを作成すると、XcodeはヘッダーファイルCpp_to_RN.hpp を作成します

まず、「Cpp_to_RN.hppファイルを開き、本体のない関数を含むクラスを作成します。

#ifndef Cpp_to_RN_hpp
#define Cpp_to_RN_hpp#include <stdio.h>
#include <string>class Cpp_to_RN {
public:
    std::string sayHello();
};#endif /* Cpp_to_RN_hpp */

次に、ファイルを開いてCpp_to_RN.cpp、単純な関数「sayHello()」を記述します。

#include "Cpp_to_RN.hpp"
std::string Cpp_to_RN::sayHello(){
    return "Hello from CPP";
}

4.C++ファイルのラッピングに取り組んでいます。

C ++ファイルをラップしてIOS(swift)側にエクスポートするには

a。ObjectiveCファイルを作成して名前を付けますCpp_to_RN.m

名前をに変更Cpp_to_RN.m します Cpp_to_RN.mm

b。ファイルを開き、C++ファイルからWrapCpp_to_RN.mm 関数をラップする本文のコンテンツを記述します。sayHello

#import <Foundation/Foundation.h>
#import "WrapCpp_to_RN.h"
#import "Cpp_to_RN.hpp"@implementation WrapCpp_to_RN- (NSString *) sayHello {
  Cpp_to_RN fromCPP;
    std::string helloWorldMessage = fromCPP.sayHello();
    return [NSString
            stringWithCString:helloWorldMessage.c_str()
            encoding:NSUTF8StringEncoding];
}
@end

c。ヘッダーファイルを作成し、名前を付けますWrapCpp_to_RN.h

wrapSayHello関数をSwiftファイルにエクスポートします

#import <Foundation/Foundation.h>
@interface WrapCpp_to_RN : NSObject
- (NSString *) wrapSayHello;
@end

5. iOS(Swift)側での作業

C++関数をReactNativeにエクスポートするには

a。Swiftファイルを作成し、名前を付けますSendCpp_to_RN.swift

注:Xcodeは、NativeModules-Bridging-Header.hファイルを作成するように要求します。

クラスSendCpp_to_RNを作成し、次のように宣言しますNSObject

#import <Foundation/Foundation.h>
@interface WrapCpp_to_RN : NSObject
- (NSString *) wrapSayHello;
@end

requiresMainQueueSetup()アプリケーション実行時の警告を防ぐ関数を作成する

#import <Foundation/Foundation.h>
@interface WrapCpp_to_RN : NSObject
- (NSString *) wrapSayHello;
@end

WrapCpp_to_RN()fromをラップする関数を記述しますWrapCpp_to_RN.mm

import Foundation@objc(SendCpp_to_RN)
class SendCpp_to_RN : NSObject {
    
  @objc static func requiresMainQueueSetup() -> Bool {
        return false
    }
  
  @objc func fromCpp(_ successCallback: RCTResponseSenderBlock) -> Void {
    successCallback([NSNull(), WrapCpp_to_RN().wrapSayHello() as Any])
    }}

b。Swiftファイルのラップ関数をReactNativeにエクスポートします

を使用してSwiftクラスとその関数をエクスポートするObjectiveCファイルを作成しますCallback

#import <React/RCTBridgeModule.h>
#import <Foundation/Foundation.h>
#import "UIKit/UIKit.h"
@interface RCT_EXTERN_MODULE(SendCpp_to_RN, NSObject)RCT_EXTERN_METHOD(fromCpp:(RCTResponseSenderBlock)successCallback)@end

c。SwiftをReactNativeに接続し、NativeModules-Bridging-Header.h ファイルを開きます

#import <React/RCTBridgeModule.h>#import <React/RCTViewManager.h>#import "WrapCpp_to_RN.h"

6.ReactNative側での作業

Swiftクラスとその関数を呼び出す

import React from 'react';
import {StyleSheet, Text, View, NativeModules, Button} from 'react-native';const App = () => {
  const onPress = () => {
    const {SendCpp_to_RN} = NativeModules;
    SendCpp_to_RN.fromCpp((_err, res) => console.log(res));
  };
  return (
    <View style={styles.container}>
      <Text> Practice !</Text>
      <Button title="C++ to React Native" color="#841584" onPress={onPress} />
    </View>
  );
};
const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
});
export default App;

これで完了です。アプリケーションを実行するだけです。

react-native run-ios

または、Xcodeの「実行」ボタンをクリックして、実行内容を確認してください。

私の記事がお役に立てば幸いです。お読みいただきありがとうございます。

 ソース:https ://betterprogramming.pub/native-modules-export-c-function-to-react-native-for-beginners-77e89934b210

#cpp #cplusplus #react 

Rupert  Beatty

Rupert Beatty

1675797780

LLDebugtool: A Debugging Tool for Developers & Testers

LLDebugtool

A debugging tool for developers and testers that can help you analyze and manipulate data in non-xcode situations.

Introduction

LLDebugTool is a debugging tool for developers and testers that can help you analyze and manipulate data in non-xcode situations.

LLDebugToolSwift is the extension of LLDebugTool, it provide swift interface for LLDebugTool, LLDebugToolSwift will release with LLDebugTool at same time.

If your project is a Objective-C project, you can use LLDebugTool, if your project is a Swift project or contains swift files, you can use LLDebugToolSwift.

Choose LLDebugTool for your next project, or migrate over your existing projects—you'll be happy you did! 🎊🎊🎊

Gif

Preview

What's new in 1.3.8.1

Remove auto check version.

  • Too many visits to the website cocoadocs.org cause cocoadocs.org to disable the access to LLDebugTool, so this function is removed.

What can you do with LLDebugTool?

Always check the network request or view log information for certain events without having to run under XCode. This is useful in solving the testers' problems.

Easier filtering and filtering of useful information.

Easier analysis of occasional problems.

Easier analysis of the cause of the crash.

Easier sharing, previewing, or removing sandbox files, which can be very useful in the development stage.

Easier observe app's memory, CPU, FPS and other information.

Take screenshots, tag and share.

More intuitive view of view structure and dynamic modify properties.

Determine UI elements and colors in your App more accurately.

Easy access to and comparison of point information.

Easy access to element borders and frames.

Quick entry for html.

Mock location at anytime.

Adding LLDebugTool to your project

CocoaPods

CocoaPods is the recommended way to add LLDebugTool to your project.

Objective - C

  1. Add a pod entry for LLDebugTool to your Podfile pod 'LLDebugTool' , '~> 1.0'.
  2. If only you want to use it only in Debug mode, Add a pod entry for LLDebugTool to your Podfile pod 'LLDebugTool' , '~> 1.0' ,:configurations => ['Debug'], Details also see Wiki/Use in Debug environment. If you want to specify the version, use as pod 'LLDebugTool' , '1.3.8.1' ,:configurations => ['Debug'].
  3. The recommended approach is to use multiple targets and only add pod 'LLDebugTool', '~> 1.0' to Debug Target. This has the advantage of not contamiling the code in the Product environment and can be integrated into the App in the Archive Debug environment (if :configurations => ['Debug'], it can only run through XCode. It is not possible to Archive as an App).
  4. Install the pod(s) by running pod install. If you can't search LLDebugTool or you can't find the newest release version, running pod repo update before pod install.
  5. Include LLDebugTool wherever you need it with #import "LLDebug.h" or you can write #import "LLDebug.h" in your .pch in your .pch file.

Swift

  1. Add a pod entry for LLDebugToolSwift to your Podfile pod 'LLDebugToolSwift' , '~> 1.0'.
  2. If only you want to use it only in Debug mode, Add a pod entry for LLDebugToolSwift to your Podfile pod 'LLDebugToolSwift' , '~> 1.0' ,:configurations => ['Debug'], Details also see Wiki/Use in Debug environment. If you want to specify the version, use as pod 'LLDebugToolSwift' , '1.3.8.1' ,:configurations => ['Debug'].
  3. The recommended approach is to use multiple targets and only add pod 'LLDebugToolSwift', '~> 1.0' to Debug Target. This has the advantage of not contamiling the code in the Product environment and can be integrated into the App in the Archive Debug environment (if :configurations => ['Debug'], it can only run through XCode. It is not possible to Archive as an App).
  4. Must be added in the Podfile use_frameworks!.
  5. Install the pod(s) by running pod install. If you can't search LLDebugToolSwift or you can't find the newest release version, running pod repo update before pod install.
  6. Include LLDebugTool wherever you need it with import "LLDebugToolSwift.

Carthage

Carthage is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.

Objective - C

To integrate LLDebugTool into your Xcode project using Carthage, specify it in your Cartfile:

github "LLDebugTool"

Run carthage to build the framework and drag the built LLDebugTool.framework into your Xcode project.

Swift

To integrate LLDebugToolSwift into your Xcode project using Carthage, specify it in your Cartfile:

github "LLDebugToolSwift"

Run carthage to build the framework and drag the built LLDebugToolSwift.framework into your Xcode project.

Source files

Alternatively you can directly add the source folder named LLDebugTool. to your project.

Objective - C

  1. Download the latest code version or add the repository as a git submodule to your git-tracked project.
  2. Open your project in Xcode, then drag and drop the source folder named LLDebugTool. When you are prompted to "Choose options for adding these files", be sure to check the "Copy items if needed".
  3. Integrated FMDB to your project,FMDB is an Objective-C wrapper around SQLite.
  4. Integrated Masonry to your project, Masonry is an Objective-C constraint library. There are no specific version requirements, but it is recommended that you use the latest version.
  5. Include LLDebugTool wherever you need it with #import "LLDebug.h" or you can write #import "LLDebug.h" in your .pch in your .pch file.

Swift

  1. Download the LLDebugTool latest code version or add the repository as a git submodule to your git-tracked project.
  2. Download the LLDebugToolSwift latest code version or add the repository as a git submodule to your git-tracked project.
  3. Open your project in Xcode, then drag and drop the source folder named LLDebugTool and LLDebugToolSwift. When you are prompted to "Choose options for adding these files", be sure to check the "Copy items if needed".
  4. Integrated FMDB to your project,FMDB is an Objective-C wrapper around SQLite.
  5. Integrated Masonry to your project, Masonry is an Objective-C constraint library. There are no specific version requirements, but it is recommended that you use the latest version.
  6. Include LLDebugTool wherever you need it with import LLDebugToolSwift".

Usage

Get Started

You need to start LLDebugTool at "application:(UIApplication * )application didFinishLaunchingWithOptions:(NSDictionary * )launchOptions", Otherwise you will lose some information.

If you want to configure some parameters, must configure before "startWorking". More config details see LLConfig.h.

  • Quick Start

In Objective-C

#import "AppDelegate.h"
#import "LLDebug.h"

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // The default color configuration is green background and white text color. 

    // Start working.
    [[LLDebugTool sharedTool] startWorking];
    
    // Write your project code here.
    return YES;
}

In Swift

import LLDebugToolSwift

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // ####################### Start LLDebugTool #######################//
        // Use this line to start working.
        LLDebugTool.shared().startWorking()
        
        // Write your project code here.
        
        return true
    }
  • Start With Custom Config

In Objective-C

#import "AppDelegate.h"
#import "LLDebug.h"

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    // Start working with config.
    [[LLDebugTool sharedTool] startWorkingWithConfigBlock:^(LLConfig * _Nonnull config) {

        //####################### Color Style #######################//
        // Uncomment one of the following lines to change the color configuration.
        // config.colorStyle = LLConfigColorStyleSystem;
        // [config configBackgroundColor:[UIColor orangeColor] primaryColor:[UIColor whiteColor] statusBarStyle:UIStatusBarStyleDefault];

        //####################### User Identity #######################//
        // Use this line to tag user. More config please see "LLConfig.h".
        config.userIdentity = @"Miss L";

        //####################### Window Style #######################//
        // Uncomment one of the following lines to change the window style.
        // config.entryWindowStyle = LLConfigEntryWindowStyleNetBar;

    }];

    return YES;
}

In Swift

import LLDebugToolSwift

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        
        // Start working with config.
        LLDebugTool.shared().startWorking { (config) in
            //####################### Color Style #######################//
            // Uncomment one of the following lines to change the color configuration.
            // config.colorStyle = .system
            // config.configBackgroundColor(.orange, textColor: .white, statusBarStyle: .default)
        
            //####################### User Identity #######################//
            // Use this line to tag user. More config please see "LLConfig.h".
            config.userIdentity = "Miss L";
        
            //####################### Window Style #######################//
            // Uncomment one of the following lines to change the window style.
            // config.windowStyle = .netBar
        
            //####################### Features #######################//
            // Uncomment this line to change the available features.
            // config.availables = .noneAppInfo
        }
        
        return true
    }

Network Request

You don't need to do anything, just call the "startWorking" will monitoring most of network requests, including the use of NSURLSession, NSURLConnection and AFNetworking. If you find that you can't be monitored in some cases, please open an issue and tell me.

Log

Print and save a log. More log macros details see LLDebugToolMacros.h.

  • Save Log

In Objective-C

#import "LLDebug.h"

- (void)testNormalLog {
    // Insert an LLog where you want to print.
    LLog(@"Message you want to save or print.");
}

In Swift

import LLDebugToolSwift

    func testNormalLog() {
        // Insert an LLog where you want to print.
        LLog.log(message: "Message you want to save or print.")
    }
  • Save Log with event and level

In Objective-C

#import "LLDebug.h"

- (void)testEventErrorLog {
    // Insert an LLog_Error_Event where you want to print an event and level log.
    LLog_Error_Event(@"The event that you want to mark. such as bugA, taskB or processC.",@"Message you want to save or print.");
}

In Swift

import LLDebugToolSwift

    func testEventErrorLog() {
        // Insert an LLog_Error_Event where you want to print an event and level log.
        LLog.errorLog(message: "Message you want to save or print.", event: "The event that you want to mark. such as bugA, taskB or processC.")
    }

Crash

You don't need to do anything, just call the "startWorking" to intercept the crash, store crash information, cause and stack informations, and also store the network requests and log informations at the this time.

AppInfo

LLDebugTool monitors the app's CPU, memory, and FPS. At the same time, you can also quickly check the various information of the app.

Sandbox

LLDebugTool provides a quick way to view and manipulate sandbox, you can easily delete the files/folders inside the sandbox, or you can share files/folders by airdrop elsewhere. As long as apple supports this file format, you can preview the files directly in LLDebugTool.

Screenshots

LLDebugTool provides a screenshot and allows for simple painting and marking that can be easily recorded during testing or while the UI designers debugs the App.

Hierarchy

LLDebugTool provides a view structure tool for viewing or modify elements' properties and information in non-debug mode.

Magnifier

LLDebugTool provides a magnify tool for magnifying local uis and viewing color values at specified pixel.

Ruler

LLDebugTool provides a convenient tools to display touch point information.

Widget Border

LLDebugTool provides a function to display element border, convenient to see the view's frame.

HTML

LLDebugTool can debug HTML pages through WKWebView, UIWebView or your customized ViewController in your app at any time.

Location

LLDebugTool provides a function to mock location at anytime.

More Usage

  • You can get more help by looking at the Wiki.
  • You can download and run the LLDebugToolDemo or LLDebugToolSwiftDemo to find more use with LLDebugTool. The demo is build under MacOS 10.15.1, XCode 11.2.1, iOS 13.2.2, CocoaPods 1.8.4. If there is any version compatibility problem, please let me know.

Requirements

LLDebugTool works on iOS 8+ and requires ARC to build. It depends on the following Apple frameworks, which should already be included with most Xcode templates:

UIKit

Foundation

SystemConfiguration

Photos

QuickLook

CoreTelephony

CoreLocation

MapKit

AVKit

Architecture

LLDebug.h

Public header file. You can refer it to the pch file.

DebugTool

LLDebugTool Used to start and stop LLDebugTool, you need to look at it.

LLConfig Used for the custom color , size , identification and other information. If you want to configure anything, you need to focus on this file.

LLDebugToolMacros.h Quick macro definition file.

Components

  • Network Used to monitoring network request.
  • Log Used to quick print and save log.
  • Crash Used to collect crash information when an App crashes.
  • AppInfo Use to monitoring app's properties.
  • Sandbox Used to view and operate sandbox files.
  • Screenshot Used to process and display screenshots.
  • Hierarchy Used to process and present the view structure.
  • Magnifier Used for magnifying glass function.
  • Ruler Used to ruler function.
  • Widget Border User to widget border function.
  • Function Used to show functions.
  • Html Used to dynamic test web view.
  • Location Used to mock location.
  • Setting Used to dynamically set configs.

Communication

  • If you need help, open an issue.
  • If you'd like to ask a general question, open an issue.
  • If you found a bug, and can provide steps to reliably reproduce it, open an issue.
  • If you have a feature request, open an issue.
  • If you find anything wrong or anything dislike, open an issue.
  • If you have some good ideas or some requests, send mail(llworkinggroup1992@gmail.com) to me.
  • If you want to contribute, submit a pull request.

Contact

Change-log

A brief summary of each LLDebugTool release can be found in the CHANGELOG.

点击查看中文简介

Download Details:

Author: HDB-Li
Source Code: https://github.com/HDB-Li/LLDebugTool 
License: View license

#swift #ios #cpu #monitoring #objective-c #xcode 

Léon  Peltier

Léon Peltier

1656979200

Comment Exporter Une Fonction De C++ Vers React Native

Aujourd'hui, je continue à partager mon expérience avec le module natif et C++.

Comme nous verrons beaucoup de bibliothèques C/C++ écrire pour les plates-formes mobiles, nous devons les implémenter dans notre application iOS ou React Native. C'est pourquoi je souhaite écrire un article sur la façon d'exporter une fonction de C++ vers React Native, ce qui est facile à comprendre et fait gagner du temps aux débutants. Je vais commencer avec une nouvelle application native réactive

1. Créez une nouvelle application native React, ouvrez votre terminal et exécutez

npx react-native init NativeModules

2. Ouvrez Xcode et accédez à NativeModules/ios/NativeModule.xcworkspace

3. Travailler du côté C++

Créez un nouveau fichier C++ et nommez-leCpp_to_RN.cpp

Lorsque nous créons un nouveau fichier C++, Xcode créera un fichier d'en-tête Cpp_to_RN.hpp pour nous

Tout d'abord, ouvrez le fichier " Cpp_to_RN.hpp" et créez une classe qui inclut une fonction sans le corps.

#ifndef Cpp_to_RN_hpp
#define Cpp_to_RN_hpp#include <stdio.h>
#include <string>class Cpp_to_RN {
public:
    std::string sayHello();
};#endif /* Cpp_to_RN_hpp */

Ouvrez ensuite le Cpp_to_RN.cppfichier et écrivez une fonction simple " sayHello()"

#include "Cpp_to_RN.hpp"
std::string Cpp_to_RN::sayHello(){
    return "Hello from CPP";
}

4. Travail sur l'encapsulation du fichier C++.

Pour envelopper les fichiers C++ et les exporter vers le côté IOS (swift)

un. Créez un fichier Objective C et nommez-leCpp_to_RN.m

Renommez le Cpp_to_RN.m en Cpp_to_RN.mm

b. Ouvrez le WrapCpp_to_RN.mm fichier et écrivez le contenu du corps qui encapsulera la fonction sayHelloà partir du fichier C++.

#import <Foundation/Foundation.h>
#import "WrapCpp_to_RN.h"
#import "Cpp_to_RN.hpp"@implementation WrapCpp_to_RN- (NSString *) sayHello {
  Cpp_to_RN fromCPP;
    std::string helloWorldMessage = fromCPP.sayHello();
    return [NSString
            stringWithCString:helloWorldMessage.c_str()
            encoding:NSUTF8StringEncoding];
}
@end

c. Créez un fichier d'en-tête et nommez-leWrapCpp_to_RN.h

Exporter la wrapSayHellofonction vers le fichier Swift

#import <Foundation/Foundation.h>
@interface WrapCpp_to_RN : NSObject
- (NSString *) wrapSayHello;
@end

5. Travailler du côté iOS (Swift)

Pour exporter la fonction C++ vers React Native

un. Créez un fichier Swift et nommez-leSendCpp_to_RN.swift

Remarque : Xcode nous demandera de créer un NativeModules-Bridging-Header.hfichier pour nous.

Créez une classe SendCpp_to_RNet déclarez-la commeNSObject

#import <Foundation/Foundation.h>
@interface WrapCpp_to_RN : NSObject
- (NSString *) wrapSayHello;
@end

Écrire une fonction requiresMainQueueSetup()pour empêcher l'avertissement lorsque nous exécutons l'application

#import <Foundation/Foundation.h>
@interface WrapCpp_to_RN : NSObject
- (NSString *) wrapSayHello;
@end

Ecrire une fonction pour envelopper le WrapCpp_to_RN()fromWrapCpp_to_RN.mm

import Foundation@objc(SendCpp_to_RN)
class SendCpp_to_RN : NSObject {
    
  @objc static func requiresMainQueueSetup() -> Bool {
        return false
    }
  
  @objc func fromCpp(_ successCallback: RCTResponseSenderBlock) -> Void {
    successCallback([NSNull(), WrapCpp_to_RN().wrapSayHello() as Any])
    }}

b. Exporter une fonction wrap dans un fichier Swift vers React Native

Créez un fichier Objective C pour exporter la classe Swift et sa fonction à l'aide deCallback

#import <React/RCTBridgeModule.h>
#import <Foundation/Foundation.h>
#import "UIKit/UIKit.h"
@interface RCT_EXTERN_MODULE(SendCpp_to_RN, NSObject)RCT_EXTERN_METHOD(fromCpp:(RCTResponseSenderBlock)successCallback)@end

c. Connectez Swift à React Native, ouvrez le NativeModules-Bridging-Header.h fichier

#import <React/RCTBridgeModule.h>#import <React/RCTViewManager.h>#import "WrapCpp_to_RN.h"

6. Travailler du côté React Native

Appelez la classe Swift et ses fonctions

import React from 'react';
import {StyleSheet, Text, View, NativeModules, Button} from 'react-native';const App = () => {
  const onPress = () => {
    const {SendCpp_to_RN} = NativeModules;
    SendCpp_to_RN.fromCpp((_err, res) => console.log(res));
  };
  return (
    <View style={styles.container}>
      <Text> Practice !</Text>
      <Button title="C++ to React Native" color="#841584" onPress={onPress} />
    </View>
  );
};
const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
});
export default App;

Et nous avons terminé, il suffit de lancer l'application

react-native run-ios

Ou cliquez simplement sur le bouton "exécuter" sur Xcode et voyez ce que nous avons fait.

J'espère que mon article vous sera utile, merci pour le temps de lecture.

 Source : https://betterprogramming.pub/native-modules-export-c-function-to-react-native-for-beginners-77e89934b210

#cpp #cplusplus #react 

黎 飞

黎 飞

1656984600

如何将函数从 C++ 导出到 React Native

今天,我继续分享我在 Native Module 和 C++ 方面的经验。

由于我们将看到很多为移动平台编写的 C/C++ 库,因此我们需要将它们实现到我们的 iOS 或 React Native 应用程序中。这就是为什么我想写一篇关于如何将一个函数从 C++ 导出到 React Native 的文章,它易于理解并且为初学者节省了时间。我将从一个新的 react native 应用程序开始

1.新建一个react native app,打开你的终端运行

npx react-native init NativeModules

2. 打开 Xcode 并导航到 NativeModules/ios/NativeModule.xcworkspace

3. 在 C++ 端工作

创建一个新的 C++ 文件并命名Cpp_to_RN.cpp

当我们创建一个新的 C++ 文件时,Xcode 会Cpp_to_RN.hpp 为我们创建一个头文件

首先,打开“ Cpp_to_RN.hpp文件,并创建一个包含没有主体的函数的类。

#ifndef Cpp_to_RN_hpp
#define Cpp_to_RN_hpp#include <stdio.h>
#include <string>class Cpp_to_RN {
public:
    std::string sayHello();
};#endif /* Cpp_to_RN_hpp */

然后打开Cpp_to_RN.cpp文件,写一个简单的函数“ sayHello()

#include "Cpp_to_RN.hpp"
std::string Cpp_to_RN::sayHello(){
    return "Hello from CPP";
}

4. 处理包装 C++ 文件。

包装 C++ 文件并将它们导出到 IOS (swift) 端

一个。创建一个Objective C文件并命名Cpp_to_RN.m

重命名Cpp_to_RN.m Cpp_to_RN.mm

湾。打开WrapCpp_to_RN.mm 文件并编写将包装sayHelloC++ 文件中的函数的正文内容。

#import <Foundation/Foundation.h>
#import "WrapCpp_to_RN.h"
#import "Cpp_to_RN.hpp"@implementation WrapCpp_to_RN- (NSString *) sayHello {
  Cpp_to_RN fromCPP;
    std::string helloWorldMessage = fromCPP.sayHello();
    return [NSString
            stringWithCString:helloWorldMessage.c_str()
            encoding:NSUTF8StringEncoding];
}
@end

C。创建头文件并命名WrapCpp_to_RN.h

将函数导出wrapSayHello到 Swift 文件

#import <Foundation/Foundation.h>
@interface WrapCpp_to_RN : NSObject
- (NSString *) wrapSayHello;
@end

5. 在 iOS (Swift) 端工作

将 C++ 函数导出到 React Native

一个。创建一个 Swift 文件并命名SendCpp_to_RN.swift

注意:Xcode 会要求我们为我们创建一个NativeModules-Bridging-Header.h文件。

创建一个类SendCpp_to_RN并将其声明为NSObject

#import <Foundation/Foundation.h>
@interface WrapCpp_to_RN : NSObject
- (NSString *) wrapSayHello;
@end

编写一个函数requiresMainQueueSetup()来防止我们运行应用程序时出现警告

#import <Foundation/Foundation.h>
@interface WrapCpp_to_RN : NSObject
- (NSString *) wrapSayHello;
@end

编写一个函数来包装WrapCpp_to_RN()fromWrapCpp_to_RN.mm

import Foundation@objc(SendCpp_to_RN)
class SendCpp_to_RN : NSObject {
    
  @objc static func requiresMainQueueSetup() -> Bool {
        return false
    }
  
  @objc func fromCpp(_ successCallback: RCTResponseSenderBlock) -> Void {
    successCallback([NSNull(), WrapCpp_to_RN().wrapSayHello() as Any])
    }}

湾。将 Swift 文件中的包装函数导出到 React Native

创建一个 Objective C 文件以导出 Swift 类及其函数,使用Callback

#import <React/RCTBridgeModule.h>
#import <Foundation/Foundation.h>
#import "UIKit/UIKit.h"
@interface RCT_EXTERN_MODULE(SendCpp_to_RN, NSObject)RCT_EXTERN_METHOD(fromCpp:(RCTResponseSenderBlock)successCallback)@end

C。将 Swift 连接到 React Native,打开NativeModules-Bridging-Header.h 文件

#import <React/RCTBridgeModule.h>#import <React/RCTViewManager.h>#import "WrapCpp_to_RN.h"

6. 在 React Native 方面工作

调用 Swift 类及其函数

import React from 'react';
import {StyleSheet, Text, View, NativeModules, Button} from 'react-native';const App = () => {
  const onPress = () => {
    const {SendCpp_to_RN} = NativeModules;
    SendCpp_to_RN.fromCpp((_err, res) => console.log(res));
  };
  return (
    <View style={styles.container}>
      <Text> Practice !</Text>
      <Button title="C++ to React Native" color="#841584" onPress={onPress} />
    </View>
  );
};
const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
});
export default App;

我们完成了,只需运行应用程序

react-native run-ios

或者只需单击 Xcode 上的“运行”按钮,看看我们做了什么。

希望我的文章对您有所帮助,感谢您的阅读时间。

 来源:https ://betterprogramming.pub/native-modules-export-c-function-to-react-native-for-beginners-77e89934b210

#cpp #cplusplus #react