Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1f19b2528a | ||
|
|
1f11c39773 | ||
|
|
b6ccb5927a | ||
|
|
1d465ee318 | ||
|
|
3ab48b1cf5 | ||
|
|
de4ac978bd | ||
|
|
8df5faf4ef | ||
|
|
99a2035fdb | ||
|
|
a0d61728ea | ||
|
|
312bf6102c | ||
|
|
f4885b6f1c | ||
|
|
ca63a0979e | ||
|
|
1f266c3353 | ||
|
|
c7b2a70312 | ||
|
|
255133af4d | ||
|
|
db74531cd4 | ||
|
|
f36d8bfc78 | ||
|
|
3b31ace726 |
21
CHANGELOG.md
21
CHANGELOG.md
@@ -1,5 +1,26 @@
|
||||
# Changelog
|
||||
|
||||
## 0.7.2 (2020-09-06)
|
||||
|
||||
* update onesync documentation and do not recommend it as it breaks other apps | [commit](https://github.com/undergroundwires/privacy.sexy/commit/f36d8bfc7848bb65ac0c641e318a689bf3816ccf)
|
||||
* add reversibility for biometric disabling and do not recommend it | [commit](https://github.com/undergroundwires/privacy.sexy/commit/db74531cd4139615c6d595959217d3651f099019)
|
||||
* fix bad highlighting of selected nodes when using keyboard navigation | [commit](https://github.com/undergroundwires/privacy.sexy/commit/255133af4dfae40171406648a3e2920f16d71cb3)
|
||||
* add reversibility to removing bloatware | [commit](https://github.com/undergroundwires/privacy.sexy/commit/c7b2a703128470a05f12c9c6e8002444def37ef8)
|
||||
* fix indeterminate state being lost | [commit](https://github.com/undergroundwires/privacy.sexy/commit/1f266c33535f72b69c65985bf2eff27cd2c5a104)
|
||||
* fix wording in default text in text area | [commit](https://github.com/undergroundwires/privacy.sexy/commit/ca63a0979ef55d07d09d9443e5cea9aa888870a5)
|
||||
* add best practice suggestion to come back | [commit](https://github.com/undergroundwires/privacy.sexy/commit/f4885b6f1c82752f2143934e336d6d1b1af03015)
|
||||
|
||||
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.7.1...0.7.2)
|
||||
|
||||
## 0.7.1 (2020-09-04)
|
||||
|
||||
* fix some browsers (including firefox) downloading the script as a text file | [commit](https://github.com/undergroundwires/privacy.sexy/commit/8c17929151f9c4fa5f48564492bbf400ced95eea)
|
||||
* rename screenshot image file | [commit](https://github.com/undergroundwires/privacy.sexy/commit/b8682a852a14ed6cf49986695d9510b840ac9d3d)
|
||||
* fix new/changed script higlighting not working on production builds | [commit](https://github.com/undergroundwires/privacy.sexy/commit/8c38dd73d8c7b77d8d341c0389f4d7229f9b97fd)
|
||||
* refactor unused imports | [commit](https://github.com/undergroundwires/privacy.sexy/commit/6badfef9daace0c5de3fd33652a82bfe22261b11)
|
||||
|
||||
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.7.0...0.7.1)
|
||||
|
||||
## 0.7.0 (2020-09-02)
|
||||
|
||||
* [search] better (multilined) message when there are no results | [commit](https://github.com/undergroundwires/privacy.sexy/commit/ec15af01dd020b364c2174fe562fd66227c2320c)
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
## Get started
|
||||
|
||||
- Online version: [https://privacy.sexy](https://privacy.sexy)
|
||||
- or download latest desktop version for [Windows](https://github.com/undergroundwires/privacy.sexy/releases/download/0.7.0/privacy.sexy-Setup-0.7.0.exe), [Linux](https://github.com/undergroundwires/privacy.sexy/releases/download/0.7.0/privacy.sexy-0.7.0.AppImage), [macOS](https://github.com/undergroundwires/privacy.sexy/releases/download/0.7.0/privacy.sexy-0.7.0.dmg)
|
||||
- or download latest desktop version for [Windows](https://github.com/undergroundwires/privacy.sexy/releases/download/0.7.2/privacy.sexy-Setup-0.7.2.exe), [Linux](https://github.com/undergroundwires/privacy.sexy/releases/download/0.7.2/privacy.sexy-0.7.2.AppImage), [macOS](https://github.com/undergroundwires/privacy.sexy/releases/download/0.7.2/privacy.sexy-0.7.2.dmg)
|
||||
- 💡 Come back regularly to apply latest version for stronger privacy and security.
|
||||
|
||||
[](https://privacy.sexy)
|
||||
|
||||
@@ -48,8 +49,8 @@
|
||||
- Development: `npm run serve` to compile & hot-reload for development.
|
||||
- Production: `npm run build` to prepare files for distribution.
|
||||
- Or run using Docker:
|
||||
1. Build: `docker build -t undergroundwires/privacy.sexy:0.7.0 .`
|
||||
2. Run: `docker run -it -p 8080:80 --rm --name privacy.sexy-0.7.0 undergroundwires/privacy.sexy:0.7.0`
|
||||
1. Build: `docker build -t undergroundwires/privacy.sexy:0.7.2 .`
|
||||
2. Run: `docker run -it -p 8080:80 --rm --name privacy.sexy-0.7.2 undergroundwires/privacy.sexy:0.7.2`
|
||||
|
||||
## Architecture
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "privacy.sexy",
|
||||
"version": "0.7.0",
|
||||
"version": "0.7.2",
|
||||
"author": "undergroundwires",
|
||||
"description": "Enforce privacy & security best-practices on Windows, because privacy is sexy 🍑🍆",
|
||||
"private": true,
|
||||
|
||||
@@ -52,7 +52,7 @@ function parseCategoryChild(
|
||||
children.subScripts.push(script);
|
||||
} else {
|
||||
throw new Error(`Child element is neither a category or a script.
|
||||
Parent: ${parent.category}, element: ${categoryOrScript}`);
|
||||
Parent: ${parent.category}, element: ${JSON.stringify(categoryOrScript)}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -41,6 +41,9 @@ function mayBeUniqueLine(codeLine: string): boolean {
|
||||
if (trimmed === ')' || trimmed === '(') { // "(" and ")" are used often in batch code
|
||||
return false;
|
||||
}
|
||||
if (codeLine.startsWith(':: ') || codeLine.startsWith('REM ')) { // Is comment?
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ declare module 'liquor-tree' {
|
||||
// https://github.com/amsik/liquor-tree/blob/master/src/lib/Node.js
|
||||
export interface ILiquorTreeNodeState {
|
||||
checked: boolean;
|
||||
indeterminate: boolean;
|
||||
}
|
||||
|
||||
export interface ILiquorTreeNode {
|
||||
|
||||
@@ -5,9 +5,10 @@ export class LiquorTreeOptions implements ILiquorTreeOptions {
|
||||
public readonly checkbox = true;
|
||||
public readonly checkOnSelect = true;
|
||||
/* For checkbox mode only. Children will have the same checked state as their parent.
|
||||
⚠️ Setting this false, does not update indeterminate state of nodes.
|
||||
This is false as it's handled manually to be able to batch select for performance + highlighting */
|
||||
public readonly autoCheckChildren = false;
|
||||
public readonly parentSelect = false;
|
||||
public readonly parentSelect = true;
|
||||
public readonly keyboardNavigation = true;
|
||||
public readonly filter = { // Wrap this in an arrow function as setting filter directly does not work JS APIs
|
||||
emptyText: this.liquorTreeFilter.emptyText,
|
||||
|
||||
@@ -1,14 +1,37 @@
|
||||
import { ILiquorTreeNode } from 'liquor-tree';
|
||||
import { ILiquorTreeNode, ILiquorTreeNodeState } from 'liquor-tree';
|
||||
import { NodeType } from './../../Node/INode';
|
||||
|
||||
export function getNewCheckedState(
|
||||
oldNode: ILiquorTreeNode,
|
||||
export function getNewState(
|
||||
node: ILiquorTreeNode,
|
||||
selectedNodeIds: ReadonlyArray<string>): ILiquorTreeNodeState {
|
||||
const checked = getNewCheckedState(node, selectedNodeIds);
|
||||
const indeterminate = !checked && getNewIndeterminateState(node, selectedNodeIds);
|
||||
return {
|
||||
checked, indeterminate,
|
||||
};
|
||||
}
|
||||
|
||||
function getNewIndeterminateState(
|
||||
node: ILiquorTreeNode,
|
||||
selectedNodeIds: ReadonlyArray<string>): boolean {
|
||||
switch (oldNode.data.type) {
|
||||
switch (node.data.type) {
|
||||
case NodeType.Script:
|
||||
return selectedNodeIds.some((id) => id === oldNode.id);
|
||||
return false;
|
||||
case NodeType.Category:
|
||||
return parseAllSubScriptIds(oldNode).every((id) => selectedNodeIds.includes(id));
|
||||
return parseAllSubScriptIds(node).some((id) => selectedNodeIds.includes(id));
|
||||
default:
|
||||
throw new Error('Unknown node type');
|
||||
}
|
||||
}
|
||||
|
||||
function getNewCheckedState(
|
||||
node: ILiquorTreeNode,
|
||||
selectedNodeIds: ReadonlyArray<string>): boolean {
|
||||
switch (node.data.type) {
|
||||
case NodeType.Script:
|
||||
return selectedNodeIds.some((id) => id === node.id);
|
||||
case NodeType.Category:
|
||||
return parseAllSubScriptIds(node).every((id) => selectedNodeIds.includes(id));
|
||||
default:
|
||||
throw new Error('Unknown node type');
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ export function toNewLiquorTreeNode(node: INode): ILiquorTreeNewNode {
|
||||
text: node.text,
|
||||
state: {
|
||||
checked: false,
|
||||
indeterminate: false,
|
||||
},
|
||||
children: convertChildren(node.children, toNewLiquorTreeNode),
|
||||
data: {
|
||||
|
||||
@@ -18,14 +18,15 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
|
||||
import LiquorTree, { ILiquorTreeNewNode, ILiquorTreeExistingNode, ILiquorTree } from 'liquor-tree';
|
||||
import LiquorTree from 'liquor-tree';
|
||||
import Node from './Node/Node.vue';
|
||||
import { INode } from './Node/INode';
|
||||
import { convertExistingToNode, toNewLiquorTreeNode } from './LiquorTree/NodeWrapper/NodeTranslator';
|
||||
import { INodeSelectedEvent } from './/INodeSelectedEvent';
|
||||
import { getNewCheckedState } from './LiquorTree/NodeWrapper/NodeStateUpdater';
|
||||
import { getNewState } from './LiquorTree/NodeWrapper/NodeStateUpdater';
|
||||
import { LiquorTreeOptions } from './LiquorTree/LiquorTreeOptions';
|
||||
import { FilterPredicate, NodePredicateFilter } from './LiquorTree/NodeWrapper/NodePredicateFilter';
|
||||
import { ILiquorTreeNewNode, ILiquorTreeExistingNode, ILiquorTree, ILiquorTreeNode, ILiquorTreeNodeState } from 'liquor-tree';
|
||||
|
||||
/** Wrapper for Liquor Tree, reveals only abstracted INode for communication */
|
||||
@Component({
|
||||
@@ -49,7 +50,7 @@
|
||||
const initialNodes = this.initialNodes.map((node) => toNewLiquorTreeNode(node));
|
||||
if (this.selectedNodeIds) {
|
||||
recurseDown(initialNodes,
|
||||
(node) => node.state.checked = getNewCheckedState(node, this.selectedNodeIds));
|
||||
(node) => node.state = updateState(node.state, node, this.selectedNodeIds));
|
||||
}
|
||||
this.initialLiquourTreeNodes = initialNodes;
|
||||
} else {
|
||||
@@ -82,11 +83,11 @@
|
||||
@Watch('selectedNodeIds')
|
||||
public setSelectedStatusAsync(selectedNodeIds: ReadonlyArray<string>) {
|
||||
if (!selectedNodeIds) {
|
||||
throw new Error('Selected nodes are undefined');
|
||||
throw new Error('SelectedrecurseDown nodes are undefined');
|
||||
}
|
||||
this.getLiquorTreeApi().recurseDown((node) => {
|
||||
node.states.checked = getNewCheckedState(node, selectedNodeIds);
|
||||
});
|
||||
this.getLiquorTreeApi().recurseDown(
|
||||
(node) => node.states = updateState(node.states, node, selectedNodeIds),
|
||||
);
|
||||
}
|
||||
|
||||
private getLiquorTreeApi(): ILiquorTree {
|
||||
@@ -97,6 +98,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
function updateState(
|
||||
old: ILiquorTreeNodeState,
|
||||
node: ILiquorTreeNode,
|
||||
selectedNodeIds: ReadonlyArray<string>): ILiquorTreeNodeState {
|
||||
return {...old, ...getNewState(node, selectedNodeIds)};
|
||||
}
|
||||
|
||||
function recurseDown(
|
||||
nodes: ReadonlyArray<ILiquorTreeNewNode>,
|
||||
handler: (node: ILiquorTreeNewNode) => void) {
|
||||
|
||||
@@ -18,7 +18,8 @@ const NothingChosenCode =
|
||||
.appendCommentLine('-- 🤔 How to use')
|
||||
.appendCommentLine(' 📙 Start by exploring different categories and choosing different tweaks.')
|
||||
.appendCommentLine(' 📙 You can select "Recommended" on the top to select "safer" tweaks. Always double check!')
|
||||
.appendCommentLine(' 📙 After you choose any tweak, you can download & copy to execute your script.')
|
||||
.appendCommentLine(' 📙 After you choose any tweak, you can download or copy to execute your script.')
|
||||
.appendCommentLine(' 📙 Come back regularly to apply latest version for stronger privacy and security.')
|
||||
.appendLine()
|
||||
.appendCommentLine('-- 🧐 Why privacy.sexy')
|
||||
.appendCommentLine(' ✔️ Rich tweak pool to harden security & privacy of the OS and other softwares on it.')
|
||||
|
||||
@@ -2,42 +2,40 @@
|
||||
@import "@/presentation/styles/colors.scss";
|
||||
|
||||
.tree {
|
||||
background-color: $slate;
|
||||
}
|
||||
|
||||
.tree-node > .tree-content > .tree-anchor > span {
|
||||
color: $white !important;
|
||||
text-transform: uppercase;
|
||||
color: $light-gray;
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
.tree-node {
|
||||
white-space: normal !important;
|
||||
}
|
||||
|
||||
.tree-arrow.has-child {
|
||||
&.rtl:after, &:after {
|
||||
border-color: $white !important;
|
||||
background: $slate;
|
||||
&-node {
|
||||
white-space: normal !important;
|
||||
> .tree-content {
|
||||
> .tree-anchor > span {
|
||||
color: $white;
|
||||
text-transform: uppercase;
|
||||
font-size: 1.5em;
|
||||
}
|
||||
&:hover {
|
||||
background: $dark-gray !important;
|
||||
}
|
||||
}
|
||||
&.selected { // When using keyboard navigation it higlights current item and its child items
|
||||
background: $gray;
|
||||
.tree-text {
|
||||
color: $black !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
&-checkbox {
|
||||
&.checked {
|
||||
background: $accent !important;
|
||||
}
|
||||
&.indeterminate {
|
||||
border-color: $gray !important;
|
||||
}
|
||||
background: $dark-slate !important;
|
||||
}
|
||||
&-arrow {
|
||||
&.has-child {
|
||||
&.rtl:after, &:after {
|
||||
border-color: $white !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tree-node.selected > .tree-content {
|
||||
> .tree-anchor > span {
|
||||
font-weight: bolder;
|
||||
}
|
||||
}
|
||||
|
||||
.tree-content:hover {
|
||||
background: $dark-gray !important;
|
||||
}
|
||||
|
||||
.tree-checkbox {
|
||||
&.checked {
|
||||
background: $accent !important;
|
||||
}
|
||||
&.indeterminate {
|
||||
border-color: $gray !important;
|
||||
}
|
||||
background: $dark-slate !important;
|
||||
}
|
||||
@@ -2,97 +2,189 @@ import 'mocha';
|
||||
import { expect } from 'chai';
|
||||
import { ILiquorTreeNode } from 'liquor-tree';
|
||||
import { NodeType } from '@/presentation/Scripts/ScriptsTree/SelectableTree/Node/INode';
|
||||
import { getNewCheckedState } from '@/presentation/Scripts/ScriptsTree/SelectableTree/LiquorTree/NodeWrapper/NodeStateUpdater';
|
||||
import { getNewState } from '@/presentation/Scripts/ScriptsTree/SelectableTree/LiquorTree/NodeWrapper/NodeStateUpdater';
|
||||
|
||||
describe('getNewCheckedState', () => {
|
||||
describe('script node', () => {
|
||||
it('state is true when selected', () => {
|
||||
// arrange
|
||||
const node = getScriptNode();
|
||||
const selectedScriptNodeIds = [ 'a', 'b', node.id, 'c' ];
|
||||
// act
|
||||
const actual = getNewCheckedState(node, selectedScriptNodeIds);
|
||||
// assert
|
||||
expect(actual).to.equal(true);
|
||||
describe('getNewState', () => {
|
||||
describe('checked', () => {
|
||||
describe('script node', () => {
|
||||
it('true when selected', () => {
|
||||
// arrange
|
||||
const node = getScriptNode();
|
||||
const selectedScriptNodeIds = [ 'a', 'b', node.id, 'c' ];
|
||||
// act
|
||||
const state = getNewState(node, selectedScriptNodeIds);
|
||||
// assert
|
||||
expect(state.checked).to.equal(true);
|
||||
});
|
||||
it('false when unselected', () => {
|
||||
// arrange
|
||||
const node = getScriptNode();
|
||||
const selectedScriptNodeIds = [ 'a', 'b', 'c' ];
|
||||
// act
|
||||
const state = getNewState(node, selectedScriptNodeIds);
|
||||
// assert
|
||||
expect(state.checked).to.equal(false);
|
||||
});
|
||||
});
|
||||
it('state is false when unselected', () => {
|
||||
// arrange
|
||||
const node = getScriptNode();
|
||||
const selectedScriptNodeIds = [ 'a', 'b', 'c' ];
|
||||
// act
|
||||
const actual = getNewCheckedState(node, selectedScriptNodeIds);
|
||||
// assert
|
||||
expect(actual).to.equal(false);
|
||||
describe('category node', () => {
|
||||
it('true when every child selected', () => {
|
||||
// arrange
|
||||
const node = {
|
||||
id: '1',
|
||||
data: { type: NodeType.Category, documentationUrls: [], isReversible: false },
|
||||
children: [
|
||||
{ id: '2',
|
||||
data: { type: NodeType.Category, documentationUrls: [], isReversible: false },
|
||||
children: [ getScriptNode('a'), getScriptNode('b') ],
|
||||
},
|
||||
{ id: '3',
|
||||
data: { type: NodeType.Category, documentationUrls: [], isReversible: false },
|
||||
children: [ getScriptNode('c') ],
|
||||
},
|
||||
],
|
||||
};
|
||||
const selectedScriptNodeIds = [ 'a', 'b', 'c' ];
|
||||
// act
|
||||
const state = getNewState(node, selectedScriptNodeIds);
|
||||
// assert
|
||||
expect(state.checked).to.equal(true);
|
||||
});
|
||||
it('false when none of the children is selected', () => {
|
||||
// arrange
|
||||
const node = {
|
||||
id: '1',
|
||||
data: { type: NodeType.Category, documentationUrls: [], isReversible: false },
|
||||
children: [
|
||||
{ id: '2',
|
||||
data: { type: NodeType.Category, documentationUrls: [], isReversible: false },
|
||||
children: [ getScriptNode('a'), getScriptNode('b') ],
|
||||
},
|
||||
{ id: '3',
|
||||
data: { type: NodeType.Category, documentationUrls: [], isReversible: false },
|
||||
children: [ getScriptNode('c') ],
|
||||
},
|
||||
],
|
||||
};
|
||||
const selectedScriptNodeIds = [ 'none', 'of', 'them', 'are', 'selected' ];
|
||||
// act
|
||||
const state = getNewState(node, selectedScriptNodeIds);
|
||||
// assert
|
||||
expect(state.checked).to.equal(false);
|
||||
});
|
||||
it('false when some of the children is selected', () => {
|
||||
// arrange
|
||||
const node = {
|
||||
id: '1',
|
||||
data: { type: NodeType.Category, documentationUrls: [], isReversible: false },
|
||||
children: [
|
||||
{
|
||||
id: '2',
|
||||
data: { type: NodeType.Category, documentationUrls: [], isReversible: false },
|
||||
children: [ getScriptNode('a'), getScriptNode('b') ],
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
data: { type: NodeType.Category, documentationUrls: [], isReversible: false },
|
||||
children: [ getScriptNode('c') ],
|
||||
},
|
||||
],
|
||||
};
|
||||
const selectedScriptNodeIds = [ 'a', 'c', 'unrelated' ];
|
||||
// act
|
||||
const state = getNewState(node, selectedScriptNodeIds);
|
||||
// assert
|
||||
expect(state.checked).to.equal(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('category node', () => {
|
||||
it('state is true when every child selected', () => {
|
||||
// arrange
|
||||
const node = {
|
||||
id: '1',
|
||||
data: { type: NodeType.Category, documentationUrls: [], isReversible: false },
|
||||
children: [
|
||||
{ id: '2',
|
||||
data: { type: NodeType.Category, documentationUrls: [], isReversible: false },
|
||||
children: [ getScriptNode('a'), getScriptNode('b') ],
|
||||
},
|
||||
{ id: '3',
|
||||
data: { type: NodeType.Category, documentationUrls: [], isReversible: false },
|
||||
children: [ getScriptNode('c') ],
|
||||
},
|
||||
],
|
||||
};
|
||||
const selectedScriptNodeIds = [ 'a', 'b', 'c' ];
|
||||
// act
|
||||
const actual = getNewCheckedState(node, selectedScriptNodeIds);
|
||||
// assert
|
||||
expect(actual).to.equal(true);
|
||||
describe('indeterminate', () => {
|
||||
describe('script node', () => {
|
||||
it('false when selected', () => {
|
||||
// arrange
|
||||
const node = getScriptNode();
|
||||
const selectedScriptNodeIds = [ 'a', 'b', node.id, 'c' ];
|
||||
// act
|
||||
const state = getNewState(node, selectedScriptNodeIds);
|
||||
// assert
|
||||
expect(state.indeterminate).to.equal(false);
|
||||
});
|
||||
it('false when not selected', () => {
|
||||
// arrange
|
||||
const node = getScriptNode();
|
||||
const selectedScriptNodeIds = [ 'a', 'b', 'c' ];
|
||||
// act
|
||||
const state = getNewState(node, selectedScriptNodeIds);
|
||||
// assert
|
||||
expect(state.indeterminate).to.equal(false);
|
||||
});
|
||||
});
|
||||
it('state is false when none of the children is selected', () => {
|
||||
// arrange
|
||||
const node = {
|
||||
id: '1',
|
||||
data: { type: NodeType.Category, documentationUrls: [], isReversible: false },
|
||||
children: [
|
||||
{ id: '2',
|
||||
data: { type: NodeType.Category, documentationUrls: [], isReversible: false },
|
||||
children: [ getScriptNode('a'), getScriptNode('b') ],
|
||||
},
|
||||
{ id: '3',
|
||||
data: { type: NodeType.Category, documentationUrls: [], isReversible: false },
|
||||
children: [ getScriptNode('c') ],
|
||||
},
|
||||
],
|
||||
};
|
||||
const selectedScriptNodeIds = [ 'none', 'of', 'them', 'are', 'selected' ];
|
||||
// act
|
||||
const actual = getNewCheckedState(node, selectedScriptNodeIds);
|
||||
// assert
|
||||
expect(actual).to.equal(false);
|
||||
});
|
||||
it('state is false when some of the children is selected', () => {
|
||||
// arrange
|
||||
const node = {
|
||||
id: '1',
|
||||
data: { type: NodeType.Category, documentationUrls: [], isReversible: false },
|
||||
children: [
|
||||
{
|
||||
id: '2',
|
||||
data: { type: NodeType.Category, documentationUrls: [], isReversible: false },
|
||||
children: [ getScriptNode('a'), getScriptNode('b') ],
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
data: { type: NodeType.Category, documentationUrls: [], isReversible: false },
|
||||
children: [ getScriptNode('c') ],
|
||||
},
|
||||
],
|
||||
};
|
||||
const selectedScriptNodeIds = [ 'a', 'c', 'unrelated' ];
|
||||
// act
|
||||
const actual = getNewCheckedState(node, selectedScriptNodeIds);
|
||||
// assert
|
||||
expect(actual).to.equal(false);
|
||||
describe('category node', () => {
|
||||
it('false when all children are selected', () => {
|
||||
// arrange
|
||||
const node = {
|
||||
id: '1',
|
||||
data: { type: NodeType.Category, documentationUrls: [], isReversible: false },
|
||||
children: [
|
||||
{ id: '2',
|
||||
data: { type: NodeType.Category, documentationUrls: [], isReversible: false },
|
||||
children: [ getScriptNode('a'), getScriptNode('b') ],
|
||||
},
|
||||
{ id: '3',
|
||||
data: { type: NodeType.Category, documentationUrls: [], isReversible: false },
|
||||
children: [ getScriptNode('c') ],
|
||||
},
|
||||
],
|
||||
};
|
||||
const selectedScriptNodeIds = [ 'a', 'b', 'c' ];
|
||||
// act
|
||||
const state = getNewState(node, selectedScriptNodeIds);
|
||||
// assert
|
||||
expect(state.indeterminate).to.equal(false);
|
||||
});
|
||||
it('true when all some are selected', () => {
|
||||
// arrange
|
||||
const node = {
|
||||
id: '1',
|
||||
data: { type: NodeType.Category, documentationUrls: [], isReversible: false },
|
||||
children: [
|
||||
{ id: '2',
|
||||
data: { type: NodeType.Category, documentationUrls: [], isReversible: false },
|
||||
children: [ getScriptNode('a'), getScriptNode('b') ],
|
||||
},
|
||||
{ id: '3',
|
||||
data: { type: NodeType.Category, documentationUrls: [], isReversible: false },
|
||||
children: [ getScriptNode('c') ],
|
||||
},
|
||||
],
|
||||
};
|
||||
const selectedScriptNodeIds = [ 'a' ];
|
||||
// act
|
||||
const state = getNewState(node, selectedScriptNodeIds);
|
||||
// assert
|
||||
expect(state.indeterminate).to.equal(true);
|
||||
});
|
||||
it('false when no children are selected', () => {
|
||||
// arrange
|
||||
const node = {
|
||||
id: '1',
|
||||
data: { type: NodeType.Category, documentationUrls: [], isReversible: false },
|
||||
children: [
|
||||
{ id: '2',
|
||||
data: { type: NodeType.Category, documentationUrls: [], isReversible: false },
|
||||
children: [ getScriptNode('a'), getScriptNode('b') ],
|
||||
},
|
||||
{ id: '3',
|
||||
data: { type: NodeType.Category, documentationUrls: [], isReversible: false },
|
||||
children: [ getScriptNode('c') ],
|
||||
},
|
||||
],
|
||||
};
|
||||
const selectedScriptNodeIds = [ 'none', 'of', 'them', 'are', 'selected' ];
|
||||
// act
|
||||
const state = getNewState(node, selectedScriptNodeIds);
|
||||
// assert
|
||||
expect(state.indeterminate).to.equal(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -108,6 +108,7 @@ function getNewNode(): ILiquorTreeNewNode {
|
||||
const base = getNode();
|
||||
const commonState = {
|
||||
checked: false,
|
||||
indeterminate: false,
|
||||
};
|
||||
return {
|
||||
id: base.id,
|
||||
|
||||
@@ -68,7 +68,7 @@ describe('ScriptReverter', () => {
|
||||
selection: [ new SelectedScript(script, true)], revert: true, expectRevert: true,
|
||||
},
|
||||
{
|
||||
name: 'keeps revert state deselected when already selected wtih non revert state',
|
||||
name: 'keeps revert state deselected when already selected with non revert state',
|
||||
selection: [ new SelectedScript(script, false)], revert: false, expectRevert: false,
|
||||
},
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user