-
Notifications
You must be signed in to change notification settings - Fork 255
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
25 changed files
with
426 additions
and
372 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,78 +1,42 @@ | ||
import cac from 'cac' | ||
import { execSync, ExecSyncOptions } from 'child_process' | ||
import { asObject, asString } from 'cleaners' | ||
import fs from 'fs' | ||
import { makeConfig } from 'cleaner-config' | ||
import { asObject, asOptional, asString } from 'cleaners' | ||
import { join } from 'path' | ||
|
||
const cwd = join(__dirname, '..') | ||
const TESTER_CONFIG = 'testerConfig.json' | ||
const maestroDir = join(cwd, 'maestro') | ||
|
||
// const redANSII = '\x1b[31m' | ||
const blueANSII = '\x1b[34m' | ||
const resetANSII = '\x1b[0m' | ||
|
||
// const error = console.error.bind(console, redANSII, 'ERROR:' + resetANSII) | ||
// const warn = console.warn.bind(console, yellowANSII, 'WARN:' + resetANSII) | ||
const info = console.info.bind(console, blueANSII, 'INFO:' + resetANSII) | ||
|
||
const asTestConfig = asObject({ | ||
env: asObject(asString) | ||
}) | ||
|
||
const runMaestro = async (options: CLIOptions, env?: { [key: string]: string }): Promise<void> => { | ||
const { device, dryRun, excludeTags, includeTags, test } = options | ||
const group = test ?? maestroDir | ||
|
||
const dev = device == null ? '' : `--device ${device} ` | ||
const inc = includeTags == null ? '' : `--include-tags=${includeTags} ` | ||
const exc = excludeTags == null ? '' : `--exclude-tags=${excludeTags} ` | ||
|
||
const cmd = `maestro --no-ansi ${dev}test ${inc}${exc}${group}` | ||
if (!dryRun) { | ||
info(cmd) | ||
const execSyncOpts: ExecSyncOptions = { cwd, stdio: 'inherit', env: { ...process.env, ...env } } | ||
const result = execSync(cmd, execSyncOpts) | ||
const output = result != null ? result.toString() : 'No output result' | ||
info(output) | ||
} else { | ||
info(cmd) | ||
} | ||
} | ||
|
||
const cli = cac('Edge Maestro CLI') | ||
|
||
interface CLIOptions { | ||
test?: string | ||
device?: string | ||
includeTags?: string | ||
excludeTags?: string | ||
dryRun?: boolean | ||
} | ||
|
||
cli | ||
.command('[param]', 'runMaestro.ts') | ||
.option('--test, -t [test]', 'Run specific test or group. Must specify the full path to test or directory relative to the repo working directory') | ||
.option('--device, -d [device]', 'Run test on specificied adb device id', { default: undefined }) | ||
.option('--include-tags, --it [includeTag]', 'Comma-separated list of test tags to include', { default: undefined }) | ||
.option('--exclude-tags, --et [excludeTags]', 'Comma-separated list of test tags to exclude', { default: undefined }) | ||
.option('--dry-run, --dr', 'Print the list of tests that would be run, but do not run them', { default: false }) | ||
.action((param: string, options: CLIOptions) => { | ||
if (param != null) { | ||
console.log(`Unknown param ${param}`) | ||
process.exit(-1) | ||
} | ||
let testerConfig | ||
if (fs.existsSync(TESTER_CONFIG)) { | ||
const testerConfigJson = fs.readFileSync(TESTER_CONFIG, { encoding: 'utf8' }) | ||
testerConfig = asTestConfig(JSON.parse(testerConfigJson)) | ||
env: asOptional( | ||
asObject({ | ||
MAESTRO_APP_ID: asOptional(asString, 'co.edgesecure.app'), | ||
MAESTRO_EDGE_UTXO_USERNAME: asOptional(asString, 'user'), | ||
MAESTRO_EDGE_UTXO_PASSWORD: asOptional(asString, 'passwd'), | ||
MAESTRO_EDGE_UTXO_PIN_1: asOptional(asString, '1'), | ||
MAESTRO_EDGE_UTXO_PIN_2: asOptional(asString, '1'), | ||
MAESTRO_EDGE_UTXO_PIN_3: asOptional(asString, '1'), | ||
MAESTRO_EDGE_UTXO_PIN_4: asOptional(asString, '1'), | ||
MAESTRO_EDGE_IP2FA_MEXICO_USERNAME: asOptional(asString, 'user'), | ||
MAESTRO_EDGE_IP2FA_MEXICO_PASSWORD: asOptional(asString, 'passwd') | ||
}), | ||
{ | ||
MAESTRO_APP_ID: 'co.edgesecure.app', | ||
MAESTRO_EDGE_UTXO_USERNAME: 'user', | ||
MAESTRO_EDGE_UTXO_PASSWORD: 'passwd', | ||
MAESTRO_EDGE_UTXO_PIN_1: '1', | ||
MAESTRO_EDGE_UTXO_PIN_2: '1', | ||
MAESTRO_EDGE_UTXO_PIN_3: '1', | ||
MAESTRO_EDGE_UTXO_PIN_4: '1', | ||
MAESTRO_EDGE_IP2FA_MEXICO_USERNAME: 'user', | ||
MAESTRO_EDGE_IP2FA_MEXICO_PASSWORD: 'passwd' | ||
} | ||
) | ||
}).withRest | ||
|
||
const cwd = join(__dirname, '..') | ||
|
||
runMaestro(options, testerConfig?.env).catch(e => { | ||
console.error(e) | ||
process.exit(-1) | ||
}) | ||
}) | ||
const { env } = makeConfig(asTestConfig, TESTER_CONFIG) | ||
|
||
cli.help() | ||
cli.parse() | ||
const execSyncOpts: ExecSyncOptions = { cwd, stdio: 'inherit', env: { ...process.env, ...env } } | ||
const args = process.argv.slice(2).join(' ') | ||
const cmd = `maestro ${args}` | ||
execSync(cmd, execSyncOpts) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,72 @@ | ||
import * as React from 'react' | ||
import { ImageStyle, StyleProp, TextStyle, ViewStyle } from 'react-native' | ||
import { ImageStyle, StyleProp, StyleSheet, TextStyle, ViewStyle } from 'react-native' | ||
|
||
import { ThemeProps, useTheme } from '../services/ThemeContext' | ||
import { cacheStyles, getTheme, Theme, useTheme } from '../services/ThemeContext' | ||
|
||
interface StyleProps { | ||
style?: StyleProp<any> | ||
} | ||
type ValidStyles = ImageStyle | TextStyle | ViewStyle | ValidStyles[] | ||
|
||
type ValidStyles = ImageStyle | TextStyle | ViewStyle | ||
|
||
type Styler<Props> = ValidStyles | ((theme: Theme) => ValidStyles | ((props: Props) => ValidStyles | ValidStyles[])) | ||
|
||
/** | ||
* Creates a styled component using a `styler` parameter. The `styler` can be the | ||
* styles itself, a function with the current theme and component props as | ||
* curried arguments (e.g. `theme => props => styles` or `theme => styles`). | ||
* The styles are cached when no `props` parameter is required by the `styler`. | ||
* | ||
* **Example Usage** | ||
* | ||
* ``` | ||
* const Colorful = styled(Text)({ fontWeight: 'Red' }) | ||
* const Themed = styled(Text)(theme => ({ color: theme.color })) | ||
* const Dynamic = styled(Text)(theme => props => ({ color: props.color ?? theme.color })) | ||
* const DynamicSansTheme = styled(Text)(_theme => props => ({ color: props.color })) | ||
* ``` | ||
*/ | ||
export function styled<BaseProps extends StyleProps>(Component: React.ComponentType<BaseProps>) { | ||
function makeStyledComponent<Props extends object>(getStyles: (props: Omit<BaseProps, 'style'> & Props & ThemeProps) => ValidStyles) { | ||
const StyledComponent: React.ComponentType<Omit<BaseProps, 'style'> & Props> = props => { | ||
const theme = useTheme() | ||
const styles = getStyles({ ...props, theme }) | ||
const allProps: BaseProps = { ...props, style: styles } as any | ||
return <Component {...allProps} /> | ||
function makeStyledComponent<Props extends object>(styler: Styler<Props>): React.ComponentType<Omit<BaseProps, 'style'> & Props> { | ||
function addName<P extends Omit<BaseProps, 'style'> & Props>(StyledComponent: React.ComponentType<P>) { | ||
StyledComponent.displayName = Component.displayName != null ? `StyledComponent(${Component.displayName})` : `StyledComponent` | ||
|
||
return StyledComponent | ||
} | ||
|
||
if (typeof styler === 'function') { | ||
const rv = styler(getTheme()) | ||
if (typeof rv === 'function') { | ||
const stylerNarrowed = styler as (theme: Theme) => (props: Props) => ValidStyles | ValidStyles[] | ||
return addName(function StyledComponent(props) { | ||
const theme = useTheme() | ||
const style = stylerNarrowed(theme)(props) | ||
|
||
const allProps: Omit<BaseProps, 'style'> & BaseProps['style'] = { ...props, style: style } | ||
return <Component {...allProps} /> | ||
}) | ||
} else { | ||
const stylerNarrowed = styler as (theme: Theme) => ValidStyles | ||
const getStyles = cacheStyles((theme: Theme) => ({ | ||
style: stylerNarrowed(theme) | ||
})) | ||
|
||
return addName(function StyledComponent(props) { | ||
const theme = useTheme() | ||
const stylesheet = getStyles(theme) | ||
|
||
const allProps: Omit<BaseProps, 'style'> & BaseProps['style'] = { ...props, style: stylesheet.style } | ||
return <Component {...allProps} /> | ||
}) | ||
} | ||
} else { | ||
const stylesheet = StyleSheet.create({ style: styler }) | ||
|
||
return addName(function StyledComponent(props) { | ||
const allProps: Omit<BaseProps, 'style'> & BaseProps['style'] = { ...props, style: stylesheet.style } | ||
return <Component {...allProps} /> | ||
}) | ||
} | ||
StyledComponent.displayName = Component.displayName != null ? `StyledComponent(${Component.displayName})` : `StyledComponent` | ||
return StyledComponent | ||
} | ||
return makeStyledComponent | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.