<commit_before>/* eslint no-unused-expressions: 0 */
/* global sinon */

import { Data } from "src/index";

describe("helpers/data", () => {
  describe("createStringMap", () => {
    let sandbox;
    beforeEach(() => {
      sandbox = sinon.sandbox.create();
      sandbox.spy(Data, "getStringsFromAxes");
      sandbox.spy(Data, "getStringsFromCategories");
      sandbox.spy(Data, "getStringsFromData");
    });
    afterEach(() => {
      sandbox.restore();
    });

    const tickValues = ["one", "two", "three"];
    const categories = ["red", "green", "blue"];
    const data = [{x: "one", y: 1}, {x: "red", y: 2}, {x: "cat", y: 3}];
    it("returns a string map from strings in tickValues", () => {
      const props = {tickValues};
      const stringMap = Data.createStringMap(props, "x");
      expect(Data.getStringsFromAxes).calledWith(props, "x");
      expect(Data.getStringsFromAxes).to.have.returned(["one", "two", "three"]);
      expect(stringMap).to.eql({ one: 1, two: 2, three: 3 });
    });

    it("returns a string map from strings in categories", () => {
      const props = {categories};
      const stringMap = Data.createStringMap(props, "x");
      expect(Data.getStringsFromCategories).calledWith(props, "x");
      expect(Data.getStringsFromCategories).to.have.returned(["red", "green", "blue"]);
      expect(stringMap).to.eql({ red: 1, green: 2, blue: 3 });
    });

    it("returns a string map from strings in data", () => {
      const props = {data};
      const stringMap = Data.createStringMap(props, "x");
      expect(Data.getStringsFromData).calledWith(props, "x");
      expect(Data.getStringsFromData).to.have.returned(["one", "red", "cat"]);
      expect(stringMap).to.eql({ one: 1, red: 2, cat: 3 });
    });

    it("a unique set of values is returned from multiple sources", () => {
      const props = {tickValues, data};
      const stringMap = Data.createStringMap(props, "x");
      expect(Data.getStringsFromAxes).to.have.returned(["one", "two", "three"]);
      expect(Data.getStringsFromData).to.have.returned(["one", "red", "cat"]);
      expect(stringMap).to.eql({ one: 1, two: 2, three: 3, red: 4, cat: 5 });
    });
  });

  describe("getStringsFromData", () => {
    it("returns an array of strings from a data prop", () => {
      const props = {data: [{x: "one", y: 1}, {x: "red", y: 2}, {x: "cat", y: 3}]};
      const dataStrings = Data.getStringsFromData(props, "x");
      expect(dataStrings).to.eql(["one", "red", "cat"]);
    });

    it("returns an array of strings from array-type data", () => {
      const props = {data: [["one", 1], ["red", 2], ["cat", 3]], x: 0, y: 1};
      const dataStrings = Data.getStringsFromData(props, "x");
      expect(dataStrings).to.eql(["one", "red", "cat"]);
    });

    it("only returns strings, if data is mixed", () => {
      const props = {data: [{x: 1, y: 1}, {x: "three", y: 3}]};
      expect(Data.getStringsFromData(props, "x")).to.eql(["three"]);
    });

    it("returns an empty array when no strings are present", () => {
      const props = {data: [{x: 1, y: 1}, {x: 3, y: 3}]};
      expect(Data.getStringsFromData(props, "x")).to.eql([]);
    });

    it("returns an empty array when the data prop is undefined", () => {
      expect(Data.getStringsFromData({}, "x")).to.eql([]);
    });
  });

  describe("getStringsFromAxes", () => {
    it("returns an array of strings when tickValues is an array", () => {
      const props = {tickValues: [1, "three", 5]};
      expect(Data.getStringsFromAxes(props, "x")).to.eql(["three"]);
    });

    it("returns an array of strings when tickValues is an object", () => {
      const props = {tickValues: { x: [1, "three", 5] }};
      expect(Data.getStringsFromAxes(props, "x")).to.eql(["three"]);
    });

    it("returns an empty array when a given axis is not defined", () => {
      const props = {tickValues: { y: [1, "three", 5] }};
      expect(Data.getStringsFromAxes(props, "x")).to.eql([]);
    });

    it("returns an empty array when no strings are present", () => {
      const props = {tickValues: [1, 3, 5]};
      expect(Data.getStringsFromAxes(props, "x")).to.eql([]);
    });

    it("returns an empty array when the tickValues prop is undefined", () => {
      expect(Data.getStringsFromAxes({}, "x")).to.eql([]);
    });
  });

  describe("getStringsFromCategories", () => {
    it("returns an empty array when no strings are present", () => {
      const props = {categories: [1, 3, 5]};
      expect(Data.getStringsFromCategories(props, "x")).to.eql([]);
    });

    it("returns an empty array when the category prop is undefined", () => {
      expect(Data.getStringsFromCategories({}, "x")).to.eql([]);
    });
  });

  describe("formatData", () => {
    let sandbox;
    beforeEach(() => {
      sandbox = sinon.sandbox.create();
      sandbox.spy(Data, "cleanData");
    });

    afterEach(() => {
      sandbox.restore();
    });

    it("formats a single dataset", () => {
      const dataset = [{_x: 1, _y: 3, x: 1, y: 3}, {_x: 2, _y: 5, x: 2, y: 5}];
      const props = {data: dataset};
      const formatted = Data.formatData(dataset, props);
      expect(Data.cleanData).called.and.returned(dataset);
      expect(formatted).to.be.an.array;
      expect(formatted[0]).to.have.keys(["_x", "_y", "x", "y"]);
    });
  });

  describe("getData", () => {
    let sandbox;
    beforeEach(() => {
      sandbox = sinon.sandbox.create();
      sandbox.spy(Data, "formatData");
      sandbox.spy(Data, "generateData");
      sandbox.spy(Data, "addEventKeys");
    });

    afterEach(() => {
      sandbox.restore();
    });

    it("formats and returns the data prop", () => {
      const data = [{x: "kittens", y: 3}, {x: "cats", y: 5}];
      const props = {data, x: "x", y: "y"};
      const expectedReturn = [
        {_x: 1, x: "kittens", xName: "kittens", _y: 3, y: 3},
        {_x: 2, x: "cats", xName: "cats", _y: 5, y: 5}
      ];
      const expectedReturnWithEventKeys = [
         {_x: 1, x: "kittens", xName: "kittens", _y: 3, y: 3, eventKey: 0},
         {_x: 2, x: "cats", xName: "cats", _y: 5, y: 5, eventKey: 1}
      ];
      const returnData = Data.getData(props);
      expect(Data.formatData).calledOnce.and.returned(expectedReturn);
      expect(Data.addEventKeys).calledOnce.and.returned(expectedReturnWithEventKeys);
      expect(returnData).to.eql(expectedReturnWithEventKeys);
    });

    it("does not sort data when sort key not passed", () => {
      const data = [{x: 2, y: 2}, {x: 1, y: 3}, {x: 3, y: 1}];

      const returnData = Data.getData({data});

      expect(returnData).to.eql([
        {_x: 2, x: 2, _y: 2, y: 2, eventKey: 0},
        {_x: 1, x: 1, _y: 3, y: 3, eventKey: 1},
        {_x: 3, x: 3, _y: 1, y: 1, eventKey: 2}
      ]);
    });

    it("sorts data according to sort key", () => {
      const data = [
        {x: 1, y: 1, order: 2},
        {x: 3, y: 3, order: 1},
        {x: 2, y: 2, order: 3}
      ];

      const returnData = Data.getData({data, sortKey: "order"});

      expect(returnData).to.eql([
        {_x: 3, x: 3, _y: 3, y: 3, order: 1, eventKey: 0},
        {_x: 1, x: 1, _y: 1, y: 1, order: 2, eventKey: 1},
        {_x: 2, x: 2, _y: 2, y: 2, order: 3, eventKey: 2}
      ]);
    });

    // Ensures previous VictoryLine api for sortKey prop stays consistent
    it("sorts data according to evaluated sort key when sort key is x or y", () => {
      const data = [
        {_x: 2, x: 10, _y: 2, y: 10},
        {_x: 1, x: 20, _y: 3, y: 20},
        {_x: 3, x: 30, _y: 1, y: 30}
      ];

      const returnDataX = Data.getData({data, sortKey: "x"});

      expect(returnDataX).to.eql([
        {_x: 1, x: 20, _y: 3, y: 3, y: 20, eventKey: 0},
        {_x: 2, x: 10, _y: 2, y: 2, y: 10, eventKey: 1},
        {_x: 3, x: 30, _y: 1, y: 1, y: 30, eventKey: 2}
      ]);

      const returnDataY = Data.getData({data, sortKey: "y"});

      expect(returnDataY).to.eql([
        {_x: 3, x: 30, _y: 1, y: 30, eventKey: 0},
        {_x: 2, x: 10, _y: 2, y: 10, eventKey: 1},
        {_x: 1, x: 20, _y: 3, y: 20, eventKey: 2}
      ]);
    });

    it("generates a dataset from domain", () => {
      const generatedReturn = [{x: 0, y: 0}, {x: 10, y: 10}];
      const expectedReturn = [{_x: 0, x: 0, _y: 0, y: 0}, {_x: 10, x: 10, _y: 10, y: 10}];
      const expectedReturnWithEventKeys = [
        {_x: 0, x: 0, _y: 0, y: 0, eventKey: 0}, {_x: 10, x: 10, _y: 10, y: 10, eventKey: 1}
      ];
      const props = {x: "x", y: "y", domain: {x: [0, 10], y: [0, 10]}};
      const returnData = Data.getData(props);
      expect(Data.generateData).calledOnce.and.returned(generatedReturn);
      expect(Data.formatData).calledOnce.and.returned(expectedReturn);
      expect(Data.addEventKeys).calledOnce.and.returned(expectedReturnWithEventKeys);
      expect(returnData).to.eql(expectedReturnWithEventKeys);
    });

    it("generates a dataset from domain and samples", () => {
      const generatedReturn = [{x: 0, y: 0}, {x: 5, y: 5}, {x: 10, y: 10}];
      const expectedReturn = [
        {_x: 0, x: 0, _y: 0, y: 0}, {_x: 5, x: 5, _y: 5, y: 5}, {_x: 10, x: 10, _y: 10, y: 10}
      ];
      const expectedReturnWithEventKeys = [
        {_x: 0, x: 0, _y: 0, y: 0, eventKey: 0},
        {_x: 5, x: 5, _y: 5, y: 5, eventKey: 1},
        {_x: 10, x: 10, _y: 10, y: 10, eventKey: 2}
      ];
      const props = {x: "x", y: "y", domain: {x: [0, 10], y: [0, 10]}, samples: 2};
      const returnData = Data.getData(props);
      expect(Data.generateData).calledOnce.and.returned(generatedReturn);
      expect(Data.formatData).calledOnce.and.returned(expectedReturn);
      expect(Data.addEventKeys).calledOnce.and.returned(expectedReturnWithEventKeys);
      expect(returnData).to.eql(expectedReturnWithEventKeys);
    });
  });
});
<commit_msg>remove excess key<commit_after>/* eslint no-unused-expressions: 0 */
/* global sinon */

import { Data } from "src/index";

describe("helpers/data", () => {
  describe("createStringMap", () => {
    let sandbox;
    beforeEach(() => {
      sandbox = sinon.sandbox.create();
      sandbox.spy(Data, "getStringsFromAxes");
      sandbox.spy(Data, "getStringsFromCategories");
      sandbox.spy(Data, "getStringsFromData");
    });
    afterEach(() => {
      sandbox.restore();
    });

    const tickValues = ["one", "two", "three"];
    const categories = ["red", "green", "blue"];
    const data = [{x: "one", y: 1}, {x: "red", y: 2}, {x: "cat", y: 3}];
    it("returns a string map from strings in tickValues", () => {
      const props = {tickValues};
      const stringMap = Data.createStringMap(props, "x");
      expect(Data.getStringsFromAxes).calledWith(props, "x");
      expect(Data.getStringsFromAxes).to.have.returned(["one", "two", "three"]);
      expect(stringMap).to.eql({ one: 1, two: 2, three: 3 });
    });

    it("returns a string map from strings in categories", () => {
      const props = {categories};
      const stringMap = Data.createStringMap(props, "x");
      expect(Data.getStringsFromCategories).calledWith(props, "x");
      expect(Data.getStringsFromCategories).to.have.returned(["red", "green", "blue"]);
      expect(stringMap).to.eql({ red: 1, green: 2, blue: 3 });
    });

    it("returns a string map from strings in data", () => {
      const props = {data};
      const stringMap = Data.createStringMap(props, "x");
      expect(Data.getStringsFromData).calledWith(props, "x");
      expect(Data.getStringsFromData).to.have.returned(["one", "red", "cat"]);
      expect(stringMap).to.eql({ one: 1, red: 2, cat: 3 });
    });

    it("a unique set of values is returned from multiple sources", () => {
      const props = {tickValues, data};
      const stringMap = Data.createStringMap(props, "x");
      expect(Data.getStringsFromAxes).to.have.returned(["one", "two", "three"]);
      expect(Data.getStringsFromData).to.have.returned(["one", "red", "cat"]);
      expect(stringMap).to.eql({ one: 1, two: 2, three: 3, red: 4, cat: 5 });
    });
  });

  describe("getStringsFromData", () => {
    it("returns an array of strings from a data prop", () => {
      const props = {data: [{x: "one", y: 1}, {x: "red", y: 2}, {x: "cat", y: 3}]};
      const dataStrings = Data.getStringsFromData(props, "x");
      expect(dataStrings).to.eql(["one", "red", "cat"]);
    });

    it("returns an array of strings from array-type data", () => {
      const props = {data: [["one", 1], ["red", 2], ["cat", 3]], x: 0, y: 1};
      const dataStrings = Data.getStringsFromData(props, "x");
      expect(dataStrings).to.eql(["one", "red", "cat"]);
    });

    it("only returns strings, if data is mixed", () => {
      const props = {data: [{x: 1, y: 1}, {x: "three", y: 3}]};
      expect(Data.getStringsFromData(props, "x")).to.eql(["three"]);
    });

    it("returns an empty array when no strings are present", () => {
      const props = {data: [{x: 1, y: 1}, {x: 3, y: 3}]};
      expect(Data.getStringsFromData(props, "x")).to.eql([]);
    });

    it("returns an empty array when the data prop is undefined", () => {
      expect(Data.getStringsFromData({}, "x")).to.eql([]);
    });
  });

  describe("getStringsFromAxes", () => {
    it("returns an array of strings when tickValues is an array", () => {
      const props = {tickValues: [1, "three", 5]};
      expect(Data.getStringsFromAxes(props, "x")).to.eql(["three"]);
    });

    it("returns an array of strings when tickValues is an object", () => {
      const props = {tickValues: { x: [1, "three", 5] }};
      expect(Data.getStringsFromAxes(props, "x")).to.eql(["three"]);
    });

    it("returns an empty array when a given axis is not defined", () => {
      const props = {tickValues: { y: [1, "three", 5] }};
      expect(Data.getStringsFromAxes(props, "x")).to.eql([]);
    });

    it("returns an empty array when no strings are present", () => {
      const props = {tickValues: [1, 3, 5]};
      expect(Data.getStringsFromAxes(props, "x")).to.eql([]);
    });

    it("returns an empty array when the tickValues prop is undefined", () => {
      expect(Data.getStringsFromAxes({}, "x")).to.eql([]);
    });
  });

  describe("getStringsFromCategories", () => {
    it("returns an empty array when no strings are present", () => {
      const props = {categories: [1, 3, 5]};
      expect(Data.getStringsFromCategories(props, "x")).to.eql([]);
    });

    it("returns an empty array when the category prop is undefined", () => {
      expect(Data.getStringsFromCategories({}, "x")).to.eql([]);
    });
  });

  describe("formatData", () => {
    let sandbox;
    beforeEach(() => {
      sandbox = sinon.sandbox.create();
      sandbox.spy(Data, "cleanData");
    });

    afterEach(() => {
      sandbox.restore();
    });

    it("formats a single dataset", () => {
      const dataset = [{_x: 1, _y: 3, x: 1, y: 3}, {_x: 2, _y: 5, x: 2, y: 5}];
      const props = {data: dataset};
      const formatted = Data.formatData(dataset, props);
      expect(Data.cleanData).called.and.returned(dataset);
      expect(formatted).to.be.an.array;
      expect(formatted[0]).to.have.keys(["_x", "_y", "x", "y"]);
    });
  });

  describe("getData", () => {
    let sandbox;
    beforeEach(() => {
      sandbox = sinon.sandbox.create();
      sandbox.spy(Data, "formatData");
      sandbox.spy(Data, "generateData");
      sandbox.spy(Data, "addEventKeys");
    });

    afterEach(() => {
      sandbox.restore();
    });

    it("formats and returns the data prop", () => {
      const data = [{x: "kittens", y: 3}, {x: "cats", y: 5}];
      const props = {data, x: "x", y: "y"};
      const expectedReturn = [
        {_x: 1, x: "kittens", xName: "kittens", _y: 3, y: 3},
        {_x: 2, x: "cats", xName: "cats", _y: 5, y: 5}
      ];
      const expectedReturnWithEventKeys = [
         {_x: 1, x: "kittens", xName: "kittens", _y: 3, y: 3, eventKey: 0},
         {_x: 2, x: "cats", xName: "cats", _y: 5, y: 5, eventKey: 1}
      ];
      const returnData = Data.getData(props);
      expect(Data.formatData).calledOnce.and.returned(expectedReturn);
      expect(Data.addEventKeys).calledOnce.and.returned(expectedReturnWithEventKeys);
      expect(returnData).to.eql(expectedReturnWithEventKeys);
    });

    it("does not sort data when sort key not passed", () => {
      const data = [{x: 2, y: 2}, {x: 1, y: 3}, {x: 3, y: 1}];

      const returnData = Data.getData({data});

      expect(returnData).to.eql([
        {_x: 2, x: 2, _y: 2, y: 2, eventKey: 0},
        {_x: 1, x: 1, _y: 3, y: 3, eventKey: 1},
        {_x: 3, x: 3, _y: 1, y: 1, eventKey: 2}
      ]);
    });

    it("sorts data according to sort key", () => {
      const data = [
        {x: 1, y: 1, order: 2},
        {x: 3, y: 3, order: 1},
        {x: 2, y: 2, order: 3}
      ];

      const returnData = Data.getData({data, sortKey: "order"});

      expect(returnData).to.eql([
        {_x: 3, x: 3, _y: 3, y: 3, order: 1, eventKey: 0},
        {_x: 1, x: 1, _y: 1, y: 1, order: 2, eventKey: 1},
        {_x: 2, x: 2, _y: 2, y: 2, order: 3, eventKey: 2}
      ]);
    });

    // Ensures previous VictoryLine api for sortKey prop stays consistent
    it("sorts data according to evaluated sort key when sort key is x or y", () => {
      const data = [
        {_x: 2, x: 10, _y: 2, y: 10},
        {_x: 1, x: 20, _y: 3, y: 20},
        {_x: 3, x: 30, _y: 1, y: 30}
      ];

      const returnDataX = Data.getData({data, sortKey: "x"});

      expect(returnDataX).to.eql([
        {_x: 1, x: 20, _y: 3, y: 20, eventKey: 0},
        {_x: 2, x: 10, _y: 2, y: 10, eventKey: 1},
        {_x: 3, x: 30, _y: 1, y: 30, eventKey: 2}
      ]);

      const returnDataY = Data.getData({data, sortKey: "y"});

      expect(returnDataY).to.eql([
        {_x: 3, x: 30, _y: 1, y: 30, eventKey: 0},
        {_x: 2, x: 10, _y: 2, y: 10, eventKey: 1},
        {_x: 1, x: 20, _y: 3, y: 20, eventKey: 2}
      ]);
    });

    it("generates a dataset from domain", () => {
      const generatedReturn = [{x: 0, y: 0}, {x: 10, y: 10}];
      const expectedReturn = [{_x: 0, x: 0, _y: 0, y: 0}, {_x: 10, x: 10, _y: 10, y: 10}];
      const expectedReturnWithEventKeys = [
        {_x: 0, x: 0, _y: 0, y: 0, eventKey: 0}, {_x: 10, x: 10, _y: 10, y: 10, eventKey: 1}
      ];
      const props = {x: "x", y: "y", domain: {x: [0, 10], y: [0, 10]}};
      const returnData = Data.getData(props);
      expect(Data.generateData).calledOnce.and.returned(generatedReturn);
      expect(Data.formatData).calledOnce.and.returned(expectedReturn);
      expect(Data.addEventKeys).calledOnce.and.returned(expectedReturnWithEventKeys);
      expect(returnData).to.eql(expectedReturnWithEventKeys);
    });

    it("generates a dataset from domain and samples", () => {
      const generatedReturn = [{x: 0, y: 0}, {x: 5, y: 5}, {x: 10, y: 10}];
      const expectedReturn = [
        {_x: 0, x: 0, _y: 0, y: 0}, {_x: 5, x: 5, _y: 5, y: 5}, {_x: 10, x: 10, _y: 10, y: 10}
      ];
      const expectedReturnWithEventKeys = [
        {_x: 0, x: 0, _y: 0, y: 0, eventKey: 0},
        {_x: 5, x: 5, _y: 5, y: 5, eventKey: 1},
        {_x: 10, x: 10, _y: 10, y: 10, eventKey: 2}
      ];
      const props = {x: "x", y: "y", domain: {x: [0, 10], y: [0, 10]}, samples: 2};
      const returnData = Data.getData(props);
      expect(Data.generateData).calledOnce.and.returned(generatedReturn);
      expect(Data.formatData).calledOnce.and.returned(expectedReturn);
      expect(Data.addEventKeys).calledOnce.and.returned(expectedReturnWithEventKeys);
      expect(returnData).to.eql(expectedReturnWithEventKeys);
    });
  });
});
<|endoftext|>


<commit_before>/*
 * Copyright 2014 Takuya Asano
 * Copyright 2010-2014 Atilika Inc. and contributors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var fs = require("fs");
var expect = require("chai").expect;

var kuromoji = require("../../../src/kuromoji");
var Tokenizer = require("../../../src/Tokenizer");

var DIC_DIR = "test/resource/minimum-dic/";
var connection_costs_file = DIC_DIR + "matrix.def";
var char_def_file = DIC_DIR + "char.def";
var unk_def_file = DIC_DIR + "unk.def";
var tid_dic_file = DIC_DIR + "minimum.csv";

describe("DictionaryBuilder", function () {
    this.timeout(30000);

    var kuromoji_dic = null;  // target object of DynamicDictionaries to build

    before("Build", function (done) {
        // Build token info dictionary
        var builder = kuromoji.dictionaryBuilder();
        var tokenInfo = fs.readFileSync(tid_dic_file, "utf-8");
        tokenInfo.split("\n").map(function (line) {
            builder.addTokenInfoDictionary(line);
        });

        // Build connection costs matrix
        var cc_text = fs.readFileSync(connection_costs_file, "ascii");
        var cc_lines = cc_text.split("\n");
        cc_lines.map(function (line) {
            builder = builder.putCostMatrixLine(line);
        });

        // Build unknown dictionary
        builder = builder.charDef(fs.readFileSync(char_def_file, "utf-8"));
        var unk_text = fs.readFileSync(unk_def_file, "utf-8");
        var unk_lines = unk_text.split("\n");
        unk_lines.map(function (line) {
            builder.putUnkDefLine(line);
        });

        kuromoji_dic = builder.build();

        done();
    });

    it("Dictionary not to be null", function () {
        expect(kuromoji_dic).not.to.be.null;
    });
    it("TokenInfoDictionary not to be null", function () {
        expect(kuromoji_dic.token_info_dictionary).not.to.be.null;
    });
    it("TokenInfoDictionary", function () {
        // expect(kuromoji_dic.token_info_dictionary.getFeatures("1467000")).to.have.length.above(1);
        expect(kuromoji_dic.token_info_dictionary.dictionary.buffer).to.have.length.above(1);
    });
    it("DoubleArray not to be null", function () {
        expect(kuromoji_dic.trie).not.to.be.null;
    });
    it("ConnectionCosts not to be null", function () {
        expect(kuromoji_dic.connection_costs).not.to.be.null;
    });
    it("Tokenize simple test", function () {
        var tokenizer = new Tokenizer(kuromoji_dic);
        var path = tokenizer.tokenize("すもももももももものうち");

        var expected_tokens = [
            {
                word_type: "KNOWN",
                word_position: 1,
                surface_form: "すもも",
                pos: "名詞",
                pos_detail_1: "一般",
                pos_detail_2: "*",
                pos_detail_3: "*",
                conjugated_type: "*",
                conjugated_form: "*",
                basic_form: "すもも",
                reading: "スモモ",
                pronunciation: "スモモ"
            },
            {
                word_type: "KNOWN",
                word_position: 4,
                surface_form: "も",
                pos: "助詞",
                pos_detail_1: "係助詞",
                pos_detail_2: "*",
                pos_detail_3: "*",
                conjugated_type: "*",
                conjugated_form: "*",
                basic_form: "も",
                reading: "モ",
                pronunciation: "モ"
            },
            {
                word_type: "KNOWN",
                word_position: 5,
                surface_form: "もも",
                pos: "名詞",
                pos_detail_1: "一般",
                pos_detail_2: "*",
                pos_detail_3: "*",
                conjugated_type: "*",
                conjugated_form: "*",
                basic_form: "もも",
                reading: "モモ",
                pronunciation: "モモ" },
            {
                word_type: "KNOWN",
                word_position: 7,
                surface_form: "も",
                pos: "助詞",
                pos_detail_1: "係助詞",
                pos_detail_2: "*",
                pos_detail_3: "*",
                conjugated_type: "*",
                conjugated_form: "*",
                basic_form: "も",
                reading: "モ",
                pronunciation: "モ"
            },
            {
                word_type: "KNOWN",
                word_position: 8,
                surface_form: "もも",
                pos: "名詞",
                pos_detail_1: "一般",
                pos_detail_2: "*",
                pos_detail_3: "*",
                conjugated_type: "*",
                conjugated_form: "*",
                basic_form: "もも",
                reading: "モモ",
                pronunciation: "モモ"
            },
            {
                word_type: "KNOWN",
                word_position: 10,
                surface_form: "の",
                pos: "助詞",
                pos_detail_1: "連体化",
                pos_detail_2: "*",
                pos_detail_3: "*",
                conjugated_type: "*",
                conjugated_form: "*",
                basic_form: "の",
                reading: "ノ",
                pronunciation: "ノ"
            },
            {
                word_type: "KNOWN",
                word_position: 11,
                surface_form: "うち",
                pos: "名詞",
                pos_detail_1: "非自立",
                pos_detail_2: "副詞可能",
                pos_detail_3: "*",
                conjugated_type: "*",
                conjugated_form: "*",
                basic_form: "うち",
                reading: "ウチ",
                pronunciation: "ウチ"
            }
        ];

        expect(path).to.have.length(7);

        for (var i = 0; i < expected_tokens.length; i++) {
            var expected_token = expected_tokens[i];
            var target_token = path[i];
            for (var key in expected_token) {
                expect(target_token).to.have.property(key, expected_token[key]);
            }
        }
    });
});
<commit_msg>test: remove useless assignment<commit_after>/*
 * Copyright 2014 Takuya Asano
 * Copyright 2010-2014 Atilika Inc. and contributors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var fs = require("fs");
var expect = require("chai").expect;

var kuromoji = require("../../../src/kuromoji");
var Tokenizer = require("../../../src/Tokenizer");

var DIC_DIR = "test/resource/minimum-dic/";
var connection_costs_file = DIC_DIR + "matrix.def";
var char_def_file = DIC_DIR + "char.def";
var unk_def_file = DIC_DIR + "unk.def";
var tid_dic_file = DIC_DIR + "minimum.csv";

describe("DictionaryBuilder", function () {
    this.timeout(30000);

    var kuromoji_dic = null;  // target object of DynamicDictionaries to build

    before("Build", function (done) {
        // Build token info dictionary
        var builder = kuromoji.dictionaryBuilder();
        var tokenInfo = fs.readFileSync(tid_dic_file, "utf-8");
        tokenInfo.split("\n").map(function (line) {
            builder.addTokenInfoDictionary(line);
        });

        // Build connection costs matrix
        var cc_text = fs.readFileSync(connection_costs_file, "ascii");
        var cc_lines = cc_text.split("\n");
        cc_lines.map(function (line) {
            builder.putCostMatrixLine(line);
        });

        // Build unknown dictionary
        builder.charDef(fs.readFileSync(char_def_file, "utf-8"));
        var unk_text = fs.readFileSync(unk_def_file, "utf-8");
        var unk_lines = unk_text.split("\n");
        unk_lines.map(function (line) {
            builder.putUnkDefLine(line);
        });

        kuromoji_dic = builder.build();

        done();
    });

    it("Dictionary not to be null", function () {
        expect(kuromoji_dic).not.to.be.null;
    });
    it("TokenInfoDictionary not to be null", function () {
        expect(kuromoji_dic.token_info_dictionary).not.to.be.null;
    });
    it("TokenInfoDictionary", function () {
        // expect(kuromoji_dic.token_info_dictionary.getFeatures("1467000")).to.have.length.above(1);
        expect(kuromoji_dic.token_info_dictionary.dictionary.buffer).to.have.length.above(1);
    });
    it("DoubleArray not to be null", function () {
        expect(kuromoji_dic.trie).not.to.be.null;
    });
    it("ConnectionCosts not to be null", function () {
        expect(kuromoji_dic.connection_costs).not.to.be.null;
    });
    it("Tokenize simple test", function () {
        var tokenizer = new Tokenizer(kuromoji_dic);
        var path = tokenizer.tokenize("すもももももももものうち");

        var expected_tokens = [
            {
                word_type: "KNOWN",
                word_position: 1,
                surface_form: "すもも",
                pos: "名詞",
                pos_detail_1: "一般",
                pos_detail_2: "*",
                pos_detail_3: "*",
                conjugated_type: "*",
                conjugated_form: "*",
                basic_form: "すもも",
                reading: "スモモ",
                pronunciation: "スモモ"
            },
            {
                word_type: "KNOWN",
                word_position: 4,
                surface_form: "も",
                pos: "助詞",
                pos_detail_1: "係助詞",
                pos_detail_2: "*",
                pos_detail_3: "*",
                conjugated_type: "*",
                conjugated_form: "*",
                basic_form: "も",
                reading: "モ",
                pronunciation: "モ"
            },
            {
                word_type: "KNOWN",
                word_position: 5,
                surface_form: "もも",
                pos: "名詞",
                pos_detail_1: "一般",
                pos_detail_2: "*",
                pos_detail_3: "*",
                conjugated_type: "*",
                conjugated_form: "*",
                basic_form: "もも",
                reading: "モモ",
                pronunciation: "モモ" },
            {
                word_type: "KNOWN",
                word_position: 7,
                surface_form: "も",
                pos: "助詞",
                pos_detail_1: "係助詞",
                pos_detail_2: "*",
                pos_detail_3: "*",
                conjugated_type: "*",
                conjugated_form: "*",
                basic_form: "も",
                reading: "モ",
                pronunciation: "モ"
            },
            {
                word_type: "KNOWN",
                word_position: 8,
                surface_form: "もも",
                pos: "名詞",
                pos_detail_1: "一般",
                pos_detail_2: "*",
                pos_detail_3: "*",
                conjugated_type: "*",
                conjugated_form: "*",
                basic_form: "もも",
                reading: "モモ",
                pronunciation: "モモ"
            },
            {
                word_type: "KNOWN",
                word_position: 10,
                surface_form: "の",
                pos: "助詞",
                pos_detail_1: "連体化",
                pos_detail_2: "*",
                pos_detail_3: "*",
                conjugated_type: "*",
                conjugated_form: "*",
                basic_form: "の",
                reading: "ノ",
                pronunciation: "ノ"
            },
            {
                word_type: "KNOWN",
                word_position: 11,
                surface_form: "うち",
                pos: "名詞",
                pos_detail_1: "非自立",
                pos_detail_2: "副詞可能",
                pos_detail_3: "*",
                conjugated_type: "*",
                conjugated_form: "*",
                basic_form: "うち",
                reading: "ウチ",
                pronunciation: "ウチ"
            }
        ];

        expect(path).to.have.length(7);

        for (var i = 0; i < expected_tokens.length; i++) {
            var expected_token = expected_tokens[i];
            var target_token = path[i];
            for (var key in expected_token) {
                expect(target_token).to.have.property(key, expected_token[key]);
            }
        }
    });
});
<|endoftext|>


<commit_before>"use strict";

var env = require('../../../helpers/env'),
    setup = require("../../common/setup-base"),
    desired = require('./desired');

describe('testapp - clear -', function () {
  var driver;
  setup(this, desired).then(function (d) { driver = d; });

  it('should clear the text field', function (done) {
    driver
      .elementByTagName('textField').sendKeys("some-value").text()
        .should.become("some-value")
      .elementByTagName('textField').clear().text().should.become('')
      .nodeify(done);
  });

  it('should hide keyboard', function (done) {
    driver
      .elementByTagName('textField').sendKeys("1")
      .then(function () {
        if (!env.IOS7) {
          return driver
            .elementByTagName('slider').click()
            .should.be.rejected;
        }
      })
      .hideKeyboard()
      .elementByTagName('slider').click()
      .nodeify(done);
  });

  it('should hide keyboard using keyName', function (done) {
    driver
      .elementByTagName('textField').sendKeys("1")
      .then(function () {
        if (!env.IOS7) {
          return driver
            .elementByTagName('slider').click()
            .should.be.rejected;
        }
      })
      .hideKeyboard()
      .elementByTagName('slider').click()
      .nodeify(done);
  });

});
<commit_msg>fix hideKeyboard specs to actually test something and quarantine the default strategy test. it's not working<commit_after>"use strict";

var env = require('../../../helpers/env'),
    setup = require("../../common/setup-base"),
    desired = require('./desired');

describe('testapp - clear -', function () {
  var driver;
  setup(this, desired).then(function (d) { driver = d; });

  it('should clear the text field', function (done) {
    driver
      .elementByTagName('textField').sendKeys("some-value").text()
        .should.become("some-value")
      .elementByTagName('textField').clear().text().should.become('')
      .nodeify(done);
  });

  it('should hide keyboard using default strategy @skip-ios-all', function (done) {
    driver
      .elementByTagName('textField').sendKeys("1")
      .elementByTagName('switch').isDisplayed()
        .should.become(false)
      .hideKeyboard()
      .elementByTagName('switch').isDisplayed()
        .should.become(true)
      .nodeify(done);
  });

  it('should hide keyboard using keyName', function (done) {
    driver
      .elementByTagName('textField').sendKeys("1")
      .elementByTagName('switch').isDisplayed()
        .should.become(false)
      .hideKeyboard("Done")
      .elementByTagName('switch').isDisplayed()
        .should.become(true)
      .nodeify(done);
  });

});
<|endoftext|>


<commit_before>"use strict";

var assert = require('assert');

var calcStats = function(data) {
  return {
    count: 0
  };
};

var testEmptyStats = function() {
  var stats = calcStats([]);
  assert.equal(undefined, stats.minValue);
  assert.equal(undefined, stats.maxValue);
  assert.equal(0, stats.count);
  assert.equal(undefined, stats.average);
};

var test = function() {
  testEmptyStats();
};

test();
<commit_msg>refactor the big test case into smaller bits<commit_after>"use strict";

var assert = require('assert');

var calcStats = function(data) {
  return {
    count: 0
  };
};

var testEmptyStats = function() {
  var stats = calcStats([]);
  assert.equal(undefined, stats.minValue);
  assert.equal(undefined, stats.maxValue);
  assert.equal(0, stats.count);
  assert.equal(undefined, stats.average);
};

var testMinimum = function() {
  var emptyList = calcStats([]);
    assert.equal(undefined, emptyList.minValue);
};

var test = function() {
  testEmptyStats();

  testMinimum();
};

test();
<|endoftext|>


<commit_before>// The Post Settings Menu available in the content preview screen, as well as the post editor.

/*global window, document, $, _, Backbone, Ghost, moment */

(function () {
    "use strict";

    var parseDateFormats = ["DD MMM YY HH:mm", "DD MMM YYYY HH:mm", "DD/MM/YY HH:mm", "DD/MM/YYYY HH:mm",
            "DD-MM-YY HH:mm", "DD-MM-YYYY HH:mm", "YYYY-MM-DD HH:mm"],
        displayDateFormat = 'DD MMM YY @ HH:mm';

    Ghost.View.PostSettings = Ghost.View.extend({

        events: {
            'blur  .post-setting-slug' : 'editSlug',
            'click .post-setting-slug' : 'selectSlug',
            'blur  .post-setting-date' : 'editDate',
            'click .post-setting-static-page' : 'toggleStaticPage',
            'click .delete' : 'deletePost'
        },

        initialize: function () {
            if (this.model) {
                // These three items can be updated outside of the post settings menu, so have to be listened to.
                this.listenTo(this.model, 'change:id', this.render);
                this.listenTo(this.model, 'change:title', this.updateSlugPlaceholder);
                this.listenTo(this.model, 'change:published_at', this.updatePublishedDate);
            }
        },

        render: function () {
            var slug = this.model ? this.model.get('slug') : '',
                pubDate = this.model ? this.model.get('published_at') : 'Not Published',
                $pubDateEl = this.$('.post-setting-date'),
                $postSettingSlugEl = this.$('.post-setting-slug');

            $postSettingSlugEl.val(slug);

            // Update page status test if already a page.
            if (this.model && this.model.get('page')) {
                $('.post-setting-static-page').prop('checked', this.model.get('page'));
            }

            // Insert the published date, and make it editable if it exists.
            if (this.model && this.model.get('published_at')) {
                pubDate = moment(pubDate).format(displayDateFormat);
                $pubDateEl.attr('placeholder', '');
            } else {
                $pubDateEl.attr('placeholder', moment().format(displayDateFormat));
            }

            if (this.model && this.model.get('id')) {
                this.$('.post-setting-page').removeClass('hidden');
                this.$('.delete').removeClass('hidden');
            }

            // Apply different style for model's that aren't
            // yet persisted to the server.
            // Mostly we're hiding the delete post UI
            if (this.model.id === undefined) {
                this.$el.addClass('unsaved');
            } else {
                this.$el.removeClass('unsaved');
            }

            $pubDateEl.val(pubDate);
        },

        // Requests a new slug when the title was changed
        updateSlugPlaceholder: function () {
            var title = this.model.get('title'),
                $postSettingSlugEl = this.$('.post-setting-slug');

            // If there's a title present we want to
            // validate it against existing slugs in the db
            // and then update the placeholder value.
            if (title) {
                $.ajax({
                    url: Ghost.paths.apiRoot + '/posts/getSlug/' + encodeURIComponent(title) + '/',
                    success: function (result) {
                        $postSettingSlugEl.attr('placeholder', result);
                    }
                });
            } else {
                // If there's no title set placeholder to blank
                // and don't make an ajax request to server
                // for a proper slug (as there won't be any).
                $postSettingSlugEl.attr('placeholder', '');
                return;
            }
        },

        selectSlug: function (e) {
            e.currentTarget.select();
        },

        editSlug: _.debounce(function (e) {
            e.preventDefault();
            var self = this,
                slug = self.model.get('slug'),
                slugEl = e.currentTarget,
                newSlug = slugEl.value;

            // If the model doesn't currently
            // exist on the server (aka has no id)
            // then just update the model's value
            if (self.model.id === undefined) {
                this.model.set({
                    slug: newSlug
                });
                return;
            }

            // Ignore unchanged slugs
            if (slug === newSlug) {
                slugEl.value = slug === undefined ? '' : slug;
                return;
            }

            this.model.save({
                slug: newSlug
            }, {
                success : function (model, response, options) {
                    /*jslint unparam:true*/
                    // Repopulate slug in case it changed on the server (e.g. 'new-slug-2')
                    slugEl.value = model.get('slug');
                    Ghost.notifications.addItem({
                        type: 'success',
                        message: "Permalink successfully changed to " + model.get('slug') + '.',
                        status: 'passive'
                    });
                },
                error : function (model, xhr) {
                    /*jslint unparam:true*/
                    slugEl.value = model.previous('slug');
                    Ghost.notifications.addItem({
                        type: 'error',
                        message: Ghost.Views.Utils.getRequestErrorMessage(xhr),
                        status: 'passive'
                    });
                }
            });
        }, 500),

        updatePublishedDate: function () {
            var pubDate = this.model.get('published_at') ? moment(this.model.get('published_at'))
                    .format(displayDateFormat) : '',
                $pubDateEl = this.$('.post-setting-date');

            // Only change the date if it's different
            if (pubDate && $pubDateEl.val() !== pubDate) {
                $pubDateEl.val(pubDate);
            }
        },

        editDate: _.debounce(function (e) {
            e.preventDefault();
            var self = this,
                errMessage = '',
                pubDate = self.model.get('published_at') ? moment(self.model.get('published_at'))
                    .format(displayDateFormat) : '',
                pubDateEl = e.currentTarget,
                newPubDate = pubDateEl.value,
                pubDateMoment,
                newPubDateMoment;

            // if there is no new pub date do nothing
            if (!newPubDate) {
                return;
            }

            // Check for missing time stamp on new data
            // If no time specified, add a 12:00
            if (newPubDate && !newPubDate.slice(-5).match(/\d+:\d\d/)) {
                newPubDate += " 12:00";
            }

            newPubDateMoment = moment(newPubDate, parseDateFormats);

            // If there was a published date already set
            if (pubDate) {
                 // Check for missing time stamp on current model
                // If no time specified, add a 12:00
                if (!pubDate.slice(-5).match(/\d+:\d\d/)) {
                    pubDate += " 12:00";
                }

                pubDateMoment = moment(pubDate, parseDateFormats);

                 // Ensure the published date has changed
                if (newPubDate.length === 0 || pubDateMoment.isSame(newPubDateMoment)) {
                    // If it wasn't, reset it and return
                    pubDateEl.value = pubDateMoment.format(displayDateFormat);
                    return;
                }
            }

            // Validate new Published date
            if (!newPubDateMoment.isValid()) {
                errMessage = 'Published Date must be a valid date with format: DD MMM YY @ HH:mm (e.g. 6 Dec 14 @ 15:00)';
            }

            if (newPubDateMoment.diff(new Date(), 'h') > 0) {
                errMessage = 'Published Date cannot currently be in the future.';
            }

            if (errMessage.length) {
                // Show error message
                Ghost.notifications.addItem({
                    type: 'error',
                    message: errMessage,
                    status: 'passive'
                });

                // Reset back to original value and return
                pubDateEl.value = pubDateMoment ? pubDateMoment.format(displayDateFormat) : '';
                return;
            }

            // If the model doesn't currently
            // exist on the server (aka has no id)
            // then just update the model's value
            if (self.model.id === undefined) {
                this.model.set({
                    published_at: newPubDateMoment.toDate()
                });
                return;
            }

            // Save new 'Published' date
            this.model.save({
                published_at: newPubDateMoment.toDate()
            }, {
                success : function (model) {
                    pubDateEl.value = moment(model.get('published_at')).format(displayDateFormat);
                    Ghost.notifications.addItem({
                        type: 'success',
                        message: 'Publish date successfully changed to ' + pubDateEl.value + '.',
                        status: 'passive'
                    });
                },
                error : function (model, xhr) {
                    /*jslint unparam:true*/
                    //  Reset back to original value
                    pubDateEl.value = pubDateMoment ? pubDateMoment.format(displayDateFormat) : '';
                    Ghost.notifications.addItem({
                        type: 'error',
                        message: Ghost.Views.Utils.getRequestErrorMessage(xhr),
                        status: 'passive'
                    });
                }
            });

        }, 500),

        toggleStaticPage: _.debounce(function (e) {
            var pageEl = $(e.currentTarget),
                page = pageEl.prop('checked');

            // Don't try to save
            // if the model doesn't currently
            // exist on the server
            if (this.model.id === undefined) {
                this.model.set({
                    page: page
                });
                return;
            }

            this.model.save({
                page: page
            }, {
                success : function (model, response, options) {
                    /*jslint unparam:true*/
                    pageEl.prop('checked', page);
                    Ghost.notifications.addItem({
                        type: 'success',
                        message: "Successfully converted " + (page ? "to static page" : "to post") + '.',
                        status: 'passive'
                    });
                },
                error : function (model, xhr) {
                    /*jslint unparam:true*/
                    pageEl.prop('checked', model.previous('page'));
                    Ghost.notifications.addItem({
                        type: 'error',
                        message: Ghost.Views.Utils.getRequestErrorMessage(xhr),
                        status: 'passive'
                    });
                }
            });
        }, 500),

        deletePost: function (e) {
            e.preventDefault();
            var self = this;
            // You can't delete a post
            // that hasn't yet been saved
            if (this.model.id === undefined) {
                return;
            }
            this.addSubview(new Ghost.Views.Modal({
                model: {
                    options: {
                        close: false,
                        confirm: {
                            accept: {
                                func: function () {
                                    self.model.destroy({
                                        wait: true
                                    }).then(function () {
                                        // Redirect to content screen if deleting post from editor.
                                        if (window.location.pathname.indexOf('editor') > -1) {
                                            window.location = Ghost.paths.subdir + '/ghost/content/';
                                        }
                                        Ghost.notifications.addItem({
                                            type: 'success',
                                            message: 'Your post has been deleted.',
                                            status: 'passive'
                                        });
                                    }, function () {
                                        Ghost.notifications.addItem({
                                            type: 'error',
                                            message: 'Your post could not be deleted. Please try again.',
                                            status: 'passive'
                                        });
                                    });
                                },
                                text: "Yes"
                            },
                            reject: {
                                func: function () {
                                    return true;
                                },
                                text: "No"
                            }
                        },
                        type: "action",
                        style: ["wide", "centered"],
                        animation: 'fade'
                    },
                    content: {
                        template: 'blank',
                        title: 'Are you sure you want to delete this post?',
                        text: '
This is permanent! No backups, no restores, no magic undo button.
 We warned you, ok?
'
                    }
                }
            }));
        }

    });

}());
<commit_msg>Tweaking slug logic in post settings.<commit_after>// The Post Settings Menu available in the content preview screen, as well as the post editor.

/*global window, document, $, _, Backbone, Ghost, moment */

(function () {
    "use strict";

    var parseDateFormats = ["DD MMM YY HH:mm", "DD MMM YYYY HH:mm", "DD/MM/YY HH:mm", "DD/MM/YYYY HH:mm",
            "DD-MM-YY HH:mm", "DD-MM-YYYY HH:mm", "YYYY-MM-DD HH:mm"],
        displayDateFormat = 'DD MMM YY @ HH:mm';

    Ghost.View.PostSettings = Ghost.View.extend({

        events: {
            'blur  .post-setting-slug' : 'editSlug',
            'click .post-setting-slug' : 'selectSlug',
            'blur  .post-setting-date' : 'editDate',
            'click .post-setting-static-page' : 'toggleStaticPage',
            'click .delete' : 'deletePost'
        },

        initialize: function () {
            if (this.model) {
                // These three items can be updated outside of the post settings menu, so have to be listened to.
                this.listenTo(this.model, 'change:id', this.render);
                this.listenTo(this.model, 'change:title', this.updateSlugPlaceholder);
                this.listenTo(this.model, 'change:published_at', this.updatePublishedDate);
            }
        },

        render: function () {
            var slug = this.model ? this.model.get('slug') : '',
                pubDate = this.model ? this.model.get('published_at') : 'Not Published',
                $pubDateEl = this.$('.post-setting-date'),
                $postSettingSlugEl = this.$('.post-setting-slug');

            $postSettingSlugEl.val(slug);

            // Update page status test if already a page.
            if (this.model && this.model.get('page')) {
                $('.post-setting-static-page').prop('checked', this.model.get('page'));
            }

            // Insert the published date, and make it editable if it exists.
            if (this.model && this.model.get('published_at')) {
                pubDate = moment(pubDate).format(displayDateFormat);
                $pubDateEl.attr('placeholder', '');
            } else {
                $pubDateEl.attr('placeholder', moment().format(displayDateFormat));
            }

            if (this.model && this.model.get('id')) {
                this.$('.post-setting-page').removeClass('hidden');
                this.$('.delete').removeClass('hidden');
            }

            // Apply different style for model's that aren't
            // yet persisted to the server.
            // Mostly we're hiding the delete post UI
            if (this.model.id === undefined) {
                this.$el.addClass('unsaved');
            } else {
                this.$el.removeClass('unsaved');
            }

            $pubDateEl.val(pubDate);
        },

        // Requests a new slug when the title was changed
        updateSlugPlaceholder: function () {
            var title = this.model.get('title'),
                $postSettingSlugEl = this.$('.post-setting-slug');

            // If there's a title present we want to
            // validate it against existing slugs in the db
            // and then update the placeholder value.
            if (title) {
                $.ajax({
                    url: Ghost.paths.apiRoot + '/posts/getSlug/' + encodeURIComponent(title) + '/',
                    success: function (result) {
                        $postSettingSlugEl.attr('placeholder', result);
                    }
                });
            } else {
                // If there's no title set placeholder to blank
                // and don't make an ajax request to server
                // for a proper slug (as there won't be any).
                $postSettingSlugEl.attr('placeholder', '');
                return;
            }
        },

        selectSlug: function (e) {
            e.currentTarget.select();
        },

        editSlug: _.debounce(function (e) {
            e.preventDefault();
            var self = this,
                slug = self.model.get('slug'),
                slugEl = e.currentTarget,
                newSlug = slugEl.value,
                placeholder = slugEl.placeholder;

            newSlug = (_.isEmpty(newSlug) && placeholder) ? placeholder : newSlug;

            // If the model doesn't currently
            // exist on the server (aka has no id)
            // then just update the model's value
            if (self.model.id === undefined) {
                this.model.set({
                    slug: newSlug
                });
                return;
            }

            // Ignore unchanged slugs
            if (slug === newSlug) {
                slugEl.value = slug === undefined ? '' : slug;
                return;
            }

            this.model.save({
                slug: newSlug
            }, {
                success : function (model, response, options) {
                    /*jslint unparam:true*/
                    // Repopulate slug in case it changed on the server (e.g. 'new-slug-2')
                    slugEl.value = model.get('slug');
                    Ghost.notifications.addItem({
                        type: 'success',
                        message: "Permalink successfully changed to " + model.get('slug') + '.',
                        status: 'passive'
                    });
                },
                error : function (model, xhr) {
                    /*jslint unparam:true*/
                    slugEl.value = model.previous('slug');
                    Ghost.notifications.addItem({
                        type: 'error',
                        message: Ghost.Views.Utils.getRequestErrorMessage(xhr),
                        status: 'passive'
                    });
                }
            });
        }, 500),

        updatePublishedDate: function () {
            var pubDate = this.model.get('published_at') ? moment(this.model.get('published_at'))
                    .format(displayDateFormat) : '',
                $pubDateEl = this.$('.post-setting-date');

            // Only change the date if it's different
            if (pubDate && $pubDateEl.val() !== pubDate) {
                $pubDateEl.val(pubDate);
            }
        },

        editDate: _.debounce(function (e) {
            e.preventDefault();
            var self = this,
                errMessage = '',
                pubDate = self.model.get('published_at') ? moment(self.model.get('published_at'))
                    .format(displayDateFormat) : '',
                pubDateEl = e.currentTarget,
                newPubDate = pubDateEl.value,
                pubDateMoment,
                newPubDateMoment;

            // if there is no new pub date do nothing
            if (!newPubDate) {
                return;
            }

            // Check for missing time stamp on new data
            // If no time specified, add a 12:00
            if (newPubDate && !newPubDate.slice(-5).match(/\d+:\d\d/)) {
                newPubDate += " 12:00";
            }

            newPubDateMoment = moment(newPubDate, parseDateFormats);

            // If there was a published date already set
            if (pubDate) {
                 // Check for missing time stamp on current model
                // If no time specified, add a 12:00
                if (!pubDate.slice(-5).match(/\d+:\d\d/)) {
                    pubDate += " 12:00";
                }

                pubDateMoment = moment(pubDate, parseDateFormats);

                 // Ensure the published date has changed
                if (newPubDate.length === 0 || pubDateMoment.isSame(newPubDateMoment)) {
                    // If it wasn't, reset it and return
                    pubDateEl.value = pubDateMoment.format(displayDateFormat);
                    return;
                }
            }

            // Validate new Published date
            if (!newPubDateMoment.isValid()) {
                errMessage = 'Published Date must be a valid date with format: DD MMM YY @ HH:mm (e.g. 6 Dec 14 @ 15:00)';
            }

            if (newPubDateMoment.diff(new Date(), 'h') > 0) {
                errMessage = 'Published Date cannot currently be in the future.';
            }

            if (errMessage.length) {
                // Show error message
                Ghost.notifications.addItem({
                    type: 'error',
                    message: errMessage,
                    status: 'passive'
                });

                // Reset back to original value and return
                pubDateEl.value = pubDateMoment ? pubDateMoment.format(displayDateFormat) : '';
                return;
            }

            // If the model doesn't currently
            // exist on the server (aka has no id)
            // then just update the model's value
            if (self.model.id === undefined) {
                this.model.set({
                    published_at: newPubDateMoment.toDate()
                });
                return;
            }

            // Save new 'Published' date
            this.model.save({
                published_at: newPubDateMoment.toDate()
            }, {
                success : function (model) {
                    pubDateEl.value = moment(model.get('published_at')).format(displayDateFormat);
                    Ghost.notifications.addItem({
                        type: 'success',
                        message: 'Publish date successfully changed to ' + pubDateEl.value + '.',
                        status: 'passive'
                    });
                },
                error : function (model, xhr) {
                    /*jslint unparam:true*/
                    //  Reset back to original value
                    pubDateEl.value = pubDateMoment ? pubDateMoment.format(displayDateFormat) : '';
                    Ghost.notifications.addItem({
                        type: 'error',
                        message: Ghost.Views.Utils.getRequestErrorMessage(xhr),
                        status: 'passive'
                    });
                }
            });

        }, 500),

        toggleStaticPage: _.debounce(function (e) {
            var pageEl = $(e.currentTarget),
                page = pageEl.prop('checked');

            // Don't try to save
            // if the model doesn't currently
            // exist on the server
            if (this.model.id === undefined) {
                this.model.set({
                    page: page
                });
                return;
            }

            this.model.save({
                page: page
            }, {
                success : function (model, response, options) {
                    /*jslint unparam:true*/
                    pageEl.prop('checked', page);
                    Ghost.notifications.addItem({
                        type: 'success',
                        message: "Successfully converted " + (page ? "to static page" : "to post") + '.',
                        status: 'passive'
                    });
                },
                error : function (model, xhr) {
                    /*jslint unparam:true*/
                    pageEl.prop('checked', model.previous('page'));
                    Ghost.notifications.addItem({
                        type: 'error',
                        message: Ghost.Views.Utils.getRequestErrorMessage(xhr),
                        status: 'passive'
                    });
                }
            });
        }, 500),

        deletePost: function (e) {
            e.preventDefault();
            var self = this;
            // You can't delete a post
            // that hasn't yet been saved
            if (this.model.id === undefined) {
                return;
            }
            this.addSubview(new Ghost.Views.Modal({
                model: {
                    options: {
                        close: false,
                        confirm: {
                            accept: {
                                func: function () {
                                    self.model.destroy({
                                        wait: true
                                    }).then(function () {
                                        // Redirect to content screen if deleting post from editor.
                                        if (window.location.pathname.indexOf('editor') > -1) {
                                            window.location = Ghost.paths.subdir + '/ghost/content/';
                                        }
                                        Ghost.notifications.addItem({
                                            type: 'success',
                                            message: 'Your post has been deleted.',
                                            status: 'passive'
                                        });
                                    }, function () {
                                        Ghost.notifications.addItem({
                                            type: 'error',
                                            message: 'Your post could not be deleted. Please try again.',
                                            status: 'passive'
                                        });
                                    });
                                },
                                text: "Yes"
                            },
                            reject: {
                                func: function () {
                                    return true;
                                },
                                text: "No"
                            }
                        },
                        type: "action",
                        style: ["wide", "centered"],
                        animation: 'fade'
                    },
                    content: {
                        template: 'blank',
                        title: 'Are you sure you want to delete this post?',
                        text: '
This is permanent! No backups, no restores, no magic undo button.
 We warned you, ok?
'
                    }
                }
            }));
        }

    });

}());
<|endoftext|>


<commit_before>// Load in dependencies
var fs = require('fs'),
    exec = require('child_process').exec,
    async = require('async'),
    slug = require('slug'),
    TempFile = require('temporary/lib/file');

// Set up common variables
var expectedScreenshots = __dirname + '/expected_screenshots',
    actualScreenshots = __dirname + '/actual_screenshots',
    screenshotDiffs = __dirname + '/screenshot_diffs';

// Ensure the screenshot diff directory exists
try { fs.mkdirSync(screenshotDiffs); } catch (e) {}

// Set up unabstracted variables
// TODO: Move browsers, urls into standalone files
// TODO: See notes in https://gist.github.com/twolfson/6077989
// TODO: Optimize space via tarballing expected files?
var browsers = ['phantomjs'],
    baseUrl = 'http://localhost:8080',
    urls = [
      // '/',
      '/2012-11-17-subtle-anti-patterns',
      // '/2013-07-24-abandoned-project:-kaleidoscope', // Blog post with images
      // '/2013-07-27-develop-faster', // Blog post with tables
      // '/projects',
      // '/contact',
      // '/contact?test=success',
      // '/contact?test=fail',
      // '/404'
    ];

// For each of the URLs
async.map(urls, function (_url, cb) {
  // TODO: mocha-ify this
  // Screenshot the webpage
  var url = baseUrl + _url,
      escapedUrl = encodeURIComponent(url),
      filepath = '/' + escapedUrl + '.png',
      expectedImg = expectedScreenshots + filepath,
      actualImg = actualScreenshots + filepath,
      diffImg = screenshotDiffs + filepath;
  exec('phantomjs screenshot.js ' + url + ' ' + actualImg, {cwd: __dirname}, function processScreenshot (err, stdout, stderr) {
    // If stderr or stdout exist, log them
    if (stderr) { console.log('STDERR: ', stderr); }
    if (stdout) { console.log('STDOUT: ', stdout); }

    // If there is an error, callback with it
    if (err) { return cb(err); }

    // TODO: Emit an event instead
    // Notify the user that we have screenshotted successfully
    console.log('Successfully screenshotted ' + url);

    // If the expectedImg exists, diff the images
    if (fs.existsSync(expectedImg)) {
      // Get the sizes of the images
      async.parallel([
        function getActualSize (cb) {
          exec('identify ' + actualImg, cb);
        },
        function getExpectedSize (cb) {
          exec('identify ' + expectedImg, cb);
        }
      ], function processResults(err, results) {
        // If there was an error, callback
        if (err) { return cb(err); }

        // Process the image sizes
        var actualStdout = results[0][0],
            actualSize = actualStdout.match(/(\d+)x(\d+)/),
            actualWidth = +actualSize[1],
            actualHeight = +actualSize[2],
            expectedStdout = results[1][0],
            expectedSize = expectedStdout.match(/(\d+)x(\d+)/),
            expectedWidth = +expectedSize[1],
            expectedHeight = +expectedSize[2];

        // If the sizes are different
        if (actualWidth !== expectedWidth || actualHeight !== expectedHeight) {
          // Find the maximum dimensions
          var width = Math.max(actualWidth, expectedWidth),
              height = Math.max(actualHeight, expectedHeight);

          // Resize both images
          async.parallel([function resizeActualImage (cb) {

//  convert test/perceptual-tests/actual_screenshots/http%3A%2F%2Flocalhost%3A8080%2F2012-11-17-subtle-anti-patterns.png -bordercolor white -border 200x0 -gravity SouthEast -crop 1180x5207+0+0 tmp.png
          }], getDiff);
        } else {
        // Otherwise, get the diff
          getDiff();
        }

        // TODO: I hate this file. Very un-reusable.
        function getDiff(err) {
          // If there was an error, callback with it
          if (err) { return cb(err); }

          // Otherwise, diff the images
          var diffCmd = [
                'compare',
                '-verbose',
                '-metric RMSE',
                '-highlight-color RED',
                '-compose Src',
                actualImg,
                expectedImg,
                diffImg
              ].join(' ');
          exec(diffCmd, processDiff);
        }
      });
    } else {
    // Otherwise, save the new image as the diff
      fs.writeFileSync(diffImg, fs.readFileSync(actualImg, 'binary'),'binary');
      processDiff(null, '', 'New image created!');
    }

    function processDiff(err, stdout, stderr) {
      // If stdout exists, log it
      if (stdout) { console.log('STDOUT: ', stdout); }

      // If there is an error, callback with it
      if (err && !stderr) { return cb(err); }

      // If they don't match, create an error
      // TODO: This will become an assert
      var result = {
            url: url,
            pass: true,
            stderr: stderr
          };
      if (stderr.indexOf('all: 0 (0)') === -1) {
        result.pass = false;
      }

      // Callback with our error
      cb(null, result);
    }
  });
}, function (err, results) {
  var failedResults = results.filter(function (result) {
        return !result.pass;
      });
  if (failedResults.length > 0) {
    failedResults.forEach(function (result) {
      console.log('Failed result for ' + result.url);
      console.log(result.stderr);
    });
    process.exit(1);
  } else {
    console.log('All done!');
    process.exit(0);
  }
});<commit_msg>Successfully resizing diffs =D<commit_after>// Load in dependencies
var fs = require('fs'),
    exec = require('child_process').exec,
    async = require('async'),
    slug = require('slug'),
    TempFile = require('temporary/lib/file');

// Set up common variables
var expectedScreenshots = __dirname + '/expected_screenshots',
    actualScreenshots = __dirname + '/actual_screenshots',
    screenshotDiffs = __dirname + '/screenshot_diffs';

// Ensure the screenshot diff directory exists
try { fs.mkdirSync(screenshotDiffs); } catch (e) {}

// Set up unabstracted variables
// TODO: Move browsers, urls into standalone files
// TODO: See notes in https://gist.github.com/twolfson/6077989
// TODO: Optimize space via tarballing expected files?
var browsers = ['phantomjs'],
    baseUrl = 'http://localhost:8080',
    urls = [
      // '/',
      '/2012-11-17-subtle-anti-patterns',
      // '/2013-07-24-abandoned-project:-kaleidoscope', // Blog post with images
      // '/2013-07-27-develop-faster', // Blog post with tables
      // '/projects',
      // '/contact',
      // '/contact?test=success',
      // '/contact?test=fail',
      // '/404'
    ];

// For each of the URLs
async.map(urls, function (_url, cb) {
  // TODO: mocha-ify this
  // Screenshot the webpage
  var url = baseUrl + _url,
      escapedUrl = encodeURIComponent(url),
      filepath = '/' + escapedUrl + '.png',
      expectedImg = expectedScreenshots + filepath,
      actualImg = actualScreenshots + filepath,
      diffImg = screenshotDiffs + filepath;
  exec('phantomjs screenshot.js ' + url + ' ' + actualImg, {cwd: __dirname}, function processScreenshot (err, stdout, stderr) {
    // If stderr or stdout exist, log them
    if (stderr) { console.log('STDERR: ', stderr); }
    if (stdout) { console.log('STDOUT: ', stdout); }

    // If there is an error, callback with it
    if (err) { return cb(err); }

    // TODO: Emit an event instead
    // Notify the user that we have screenshotted successfully
    console.log('Successfully screenshotted ' + url);

    // If the expectedImg exists, diff the images
    if (fs.existsSync(expectedImg)) {
      // Get the sizes of the images
      async.parallel([
        function getActualSize (cb) {
          exec('identify ' + actualImg, cb);
        },
        function getExpectedSize (cb) {
          exec('identify ' + expectedImg, cb);
        }
      ], function processResults(err, results) {
        // If there was an error, callback
        if (err) { return cb(err); }

        // Process the image sizes
        var actualStdout = results[0][0],
            actualSize = actualStdout.match(/(\d+)x(\d+)/),
            actualWidth = +actualSize[1],
            actualHeight = +actualSize[2],
            expectedStdout = results[1][0],
            expectedSize = expectedStdout.match(/(\d+)x(\d+)/),
            expectedWidth = +expectedSize[1],
            expectedHeight = +expectedSize[2];

        // If the sizes are different
        if (actualWidth !== expectedWidth || actualHeight !== expectedHeight) {
          // Find the maximum dimensions
          var width = Math.max(actualWidth, expectedWidth),
              height = Math.max(actualHeight, expectedHeight),
              geometry = width + 'x' + height + '+0+0';

          // Resize both images
          async.parallel([
            function resizeActualImage (cb) {
              // Save the original file path and generate a temporary file
              var origFile = actualImg,
                  tmpFile = new TempFile();

              // Save over the original path
              actualImg = tmpFile.path + '.png';
              exec([
                'convert',
                origFile,

                // Fill in new space with white background
                '-bordercolor white',
                '-border ' + (width - actualWidth) +
                  'x' + (height - actualHeight),

                // Anchor image to upper-left
                '-gravity SouthEast',

                // Specify new image size
                '-crop ' + geometry,
                actualImg
              ].join(' '), cb);
            },
            function resizeExpectedImage (cb) {
              // Save the original file path and generate a temporary file
              var origFile = expectedImg,
                  tmpFile = new TempFile();

              // Save over the original path
              expectedImg = tmpFile.path + '.png';

              // Crop our file
              var cmd = [
                    'convert',
                    origFile,

                    // Fill in new space with white background
                    '-bordercolor white',
                    '-border ' + (width - expectedWidth) +
                      'x' + (height - expectedHeight),

                    // Anchor image to upper-left
                    '-gravity SouthEast',

                    // Specify new image size
                    '-crop ' + geometry,

                    // Specify the image location
                    expectedImg
                  ].join(' ');
              console.log(cmd);
              exec(cmd, cb);
            }
          ], getDiff);
        } else {
        // Otherwise, get the diff
          getDiff();
        }

        // TODO: I hate this file. Very un-reusable.
        function getDiff(err) {
          // If there was an error, callback with it
          if (err) { return cb(err); }

          // Otherwise, diff the images
          var diffCmd = [
                'compare',
                '-verbose',
                '-metric RMSE',
                '-highlight-color RED',
                '-compose Src',
                actualImg,
                expectedImg,
                diffImg
              ].join(' ');
          exec(diffCmd, processDiff);
        }
      });
    } else {
    // Otherwise, save the new image as the diff
      fs.writeFileSync(diffImg, fs.readFileSync(actualImg, 'binary'),'binary');
      processDiff(null, '', 'New image created!');
    }

    function processDiff(err, stdout, stderr) {
      // If stdout exists, log it
      if (stdout) { console.log('STDOUT: ', stdout); }

      // If there is an error, callback with it
      if (err && !stderr) { return cb(err); }

      // If they don't match, create an error
      // TODO: This will become an assert
      var result = {
            url: url,
            pass: true,
            stderr: stderr
          };
      if (stderr.indexOf('all: 0 (0)') === -1) {
        result.pass = false;
      }

      // Callback with our error
      cb(null, result);
    }
  });
}, function (err, results) {
  // If there was an error, log it and leave
  if (err) {
    console.error('ERROR: ', err);
    return process.exit(1);
  }

  // Otherwise, determine if there were any failures
  var failedResults = results.filter(function (result) {
        return !result.pass;
      });

  // If there were failures, log them and leave
  if (failedResults.length > 0) {
    failedResults.forEach(function (result) {
      console.log('Failed result for ' + result.url);
      console.log(result.stderr);
    });
    process.exit(1);
  } else {
  // Otherwise, exit gracefully
    console.log('All done!');
    process.exit(0);
  }
});<|endoftext|>


<commit_before>// ==UserScript==
// @name          GitHub Toggle Wiki Sidebar
// @version       1.0.2
// @description   A userscript that adds a button to toggle the GitHub Wiki sidebar
// @license       https://creativecommons.org/licenses/by-sa/4.0/
// @namespace     http://github.com/Mottie
// @include       https://github.com/*
// @run-at        document-idle
// @grant         GM_addStyle
// @grant         GM_getValue
// @grant         GM_setValue
// @author        Rob Garrison
// @updateURL     https://raw.githubusercontent.com/Mottie/GitHub-userscripts/master/github-toggle-wiki-sidebar.user.js
// @downloadURL   https://raw.githubusercontent.com/Mottie/GitHub-userscripts/master/github-toggle-wiki-sidebar.user.js
// ==/UserScript==
/* global GM_addStyle, GM_getValue, GM_setValue */
/* jshint unused:true, esnext:true */
(function() {
	"use strict";

	// disable click targeting of button SVG internals
	GM_addStyle(".ghtws-button > * { pointer-events: none; }");

	let targets,
		busy = false,

		// sidebar state
		isHidden = false,

		toggleIcon = "<svg class='octicon' xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'><path fill='none' stroke='currentColor' stroke-miterlimit='10' d='M.5 3.5h10v9H.5z'/><path fill='currentColor' stroke='currentColor' stroke-miterlimit='10' d='M7 7.8l1.5-1.2V9zM10.5 3.5h5v9h-5v-9zm4.3 4.3l-4.3-3V11l4.3-3.2z'/></svg>";

	function addToggle() {
		if (document.querySelector("#wiki-wrapper") && !document.querySelector(".ghtws-button")) {
			busy = true;
			let el = document.querySelector(".gh-header-actions") || document.querySelector(".gh-header-title");
			const button = document.createElement("div");
			button.className = "btn btn-sm tooltipped tooltipped-s ghtws-button";
			button.innerHTML = toggleIcon;
			button.setAttribute("aria-label", "Toggle Sidebar");
			if (el.nodeName === "H1") {
				// non-editable wiki pages
				button.style.float = "right";
				el = el.parentNode;
			}
			// editable wikis have a "header-actions" area
			// prepend button
			el.insertBefore(button, el.childNodes[0]);
			if (isHidden) {
				toggleSidebar();
			}
			busy = false;
		}
	}

	function toggleSidebar() {
		busy = true;
		const sidebar = document.querySelector("#wiki-rightbar"),
			wrapper = sidebar && sidebar.parentNode;
		if (sidebar) {
			if (isHidden) {
				sidebar.style.display = "none";
				wrapper.classList.remove("has-rightbar");
			} else {
				sidebar.style.display = "";
				wrapper.classList.add("has-rightbar");
			}
			GM_setValue("sidebar-state", isHidden);
		}
		busy = false;
	}

	function toggleEvent(event) {
		const target = event.target;
		if (target && target.classList.contains("ghtws-button")) {
			isHidden = !isHidden;
			toggleSidebar();
		}
	}

	function init() {
		busy = true;
		isHidden = GM_getValue("sidebar-state", false);
		document.querySelector("body").addEventListener("click", toggleEvent);
		addToggle();
		// busy = false from addToggle();
	}

	// DOM targets - to detect GitHub dynamic ajax page loading
	targets = document.querySelectorAll([
		"#js-repo-pjax-container",
		"#js-pjax-container"
	].join(","));

	// update TOC when content changes
	Array.prototype.forEach.call(targets, function(target) {
		new MutationObserver(function(mutations) {
			mutations.forEach(function(mutation) {
				// preform checks before adding code wrap to minimize function calls
				if (!busy && mutation.target === target) {
					addToggle();
				}
			});
		}).observe(target, {
			childList: true,
			subtree: true
		});
	});

	init();

})();
<commit_msg>Toggle-wiki-sidebar: Use pjax & fix linting<commit_after>// ==UserScript==
// @name          GitHub Toggle Wiki Sidebar
// @version       1.0.3
// @description   A userscript that adds a button to toggle the GitHub Wiki sidebar
// @license       https://creativecommons.org/licenses/by-sa/4.0/
// @namespace     https://github.com/Mottie
// @include       https://github.com/*
// @run-at        document-idle
// @grant         GM_addStyle
// @grant         GM_getValue
// @grant         GM_setValue
// @author        Rob Garrison
// @updateURL     https://raw.githubusercontent.com/Mottie/GitHub-userscripts/master/github-toggle-wiki-sidebar.user.js
// @downloadURL   https://raw.githubusercontent.com/Mottie/GitHub-userscripts/master/github-toggle-wiki-sidebar.user.js
// ==/UserScript==
(() => {
	"use strict";

	// disable click targeting of button SVG internals
	GM_addStyle(".ghtws-button > * { pointer-events: none; }");

	// sidebar state
	let isHidden = false,

		toggleIcon = "<svg class='octicon' xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'><path fill='none' stroke='currentColor' stroke-miterlimit='10' d='M.5 3.5h10v9H.5z'/><path fill='currentColor' stroke='currentColor' stroke-miterlimit='10' d='M7 7.8l1.5-1.2V9zM10.5 3.5h5v9h-5v-9zm4.3 4.3l-4.3-3V11l4.3-3.2z'/></svg>";

	function addToggle() {
		if (document.querySelector("#wiki-wrapper") && !document.querySelector(".ghtws-button")) {
			let el = document.querySelector(".gh-header-actions") || document.querySelector(".gh-header-title");
			const button = document.createElement("div");
			button.className = "btn btn-sm tooltipped tooltipped-s ghtws-button";
			button.innerHTML = toggleIcon;
			button.setAttribute("aria-label", "Toggle Sidebar");
			if (el.nodeName === "H1") {
				// non-editable wiki pages
				button.style.float = "right";
				el = el.parentNode;
			}
			// editable wikis have a "header-actions" area
			// prepend button
			el.insertBefore(button, el.childNodes[0]);
			if (isHidden) {
				toggleSidebar();
			}
		}
	}

	function toggleSidebar() {
		const sidebar = document.querySelector("#wiki-rightbar"),
			wrapper = sidebar && sidebar.parentNode;
		if (sidebar) {
			if (isHidden) {
				sidebar.style.display = "none";
				wrapper.classList.remove("has-rightbar");
			} else {
				sidebar.style.display = "";
				wrapper.classList.add("has-rightbar");
			}
			GM_setValue("sidebar-state", isHidden);
		}
	}

	function toggleEvent(event) {
		const target = event.target;
		if (target && target.classList.contains("ghtws-button")) {
			isHidden = !isHidden;
			toggleSidebar();
		}
	}

	function init() {
		isHidden = GM_getValue("sidebar-state", false);
		document.querySelector("body").addEventListener("click", toggleEvent);
		addToggle();
	}

	document.addEventListener("pjax:end", addToggle);
	init();

})();
<|endoftext|>


<commit_before>import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
import { currentURL, visit } from '@ember/test-helpers';
import { authenticateSession } from 'ember-simple-auth/test-support';

module('Acceptance | staff_admin | admin', function(hooks) {
  setupApplicationTest(hooks);

  test('is logged in', async function(assert) {
    await authenticateSession({
      uid: 'admin',
      name: 'Admin',
      role_id: 'staff_admin'
    });
    await visit('/');

    assert.dom('a#account_menu_link').hasText('ADMIN');
  });

  test('visiting homepage', async function(assert) {
    await authenticateSession({
      uid: 'admin',
      name: 'Admin',
      role_id: 'staff_admin'
    });
    await visit('/');

    assert.equal(currentURL(), '/');
    assert.dom('h2.work').hasText('DataCite');
    assert.dom('a.nav-link.active').hasText('Info');
  });

  // the following pages require authentication. Redirects to homepage otherwise
  test('visiting settings', async function(assert) {
    await authenticateSession({
      uid: 'admin',
      name: 'Admin',
      role_id: 'staff_admin'
    });
    await visit('/settings');

    assert.equal(currentURL(), '/settings');
    assert.dom('h2.work').hasText('DataCite');
    assert.dom('a.nav-link.active').hasText('Settings');
  });

  test('visiting providers', async function(assert) {
    await authenticateSession({
      uid: 'admin',
      name: 'Admin',
      role_id: 'staff_admin'
    });
    await visit('/providers');

    assert.equal(currentURL(), '/providers');
    assert.dom('h2.work').hasText('DataCite');
    assert.dom('a.nav-link.active').hasText('Providers');
  });

  test('visiting clients', async function(assert) {
    await authenticateSession({
      uid: 'admin',
      name: 'Admin',
      role_id: 'staff_admin'
    });
    await visit('/clients');

    assert.equal(currentURL(), '/clients');
    assert.dom('h2.work').hasText('DataCite');
    assert.dom('a.nav-link.active').hasText('Clients');
  });

  test('visiting prefixes', async function(assert) {
    await authenticateSession({
      uid: 'admin',
      name: 'Admin',
      role_id: 'staff_admin'
    });
    await visit('/prefixes');

    assert.equal(currentURL(), '/prefixes');
    assert.dom('h2.work').hasText('DataCite');
  });

  test('visiting prefix 10.5072', async function(assert) {
    await authenticateSession({
      uid: 'admin',
      name: 'Admin',
      role_id: 'staff_admin'
    });
    await visit('/prefixes/10.5072');

    assert.equal(currentURL(), '/prefixes/10.5072');
    assert.dom('div.alert-warning').includesText('The page was not found.');
  });

  test('visiting dois', async function(assert) {
    await authenticateSession({
      uid: 'admin',
      name: 'Admin',
      role_id: 'staff_admin'
    });
    await visit('/dois');

    assert.equal(currentURL(), '/dois');
    assert.dom('h2.work').hasText('DataCite');
    assert.dom('a.nav-link.active').hasText('DOIs');
  });

  // test('visiting specific doi', async function(assert) {
  //   await authenticateSession({
  //     uid: 'admin',
  //     name: 'Admin',
  //     role_id: 'staff_admin'
  //   });
  //   await visit('/dois');

  //   // first DOI in list
  //   await click('h3.work:first-child a');

  //   assert.dom('button#edit-doi').includesText('Update DOI (Form)');
  //   assert.dom('button#modify-doi').includesText('Update DOI (File Upload)');
  // });
});
<commit_msg>fix test<commit_after>import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
import { currentURL, visit } from '@ember/test-helpers';
import { authenticateSession } from 'ember-simple-auth/test-support';

module('Acceptance | staff_admin | admin', function(hooks) {
  setupApplicationTest(hooks);

  test('is logged in', async function(assert) {
    await authenticateSession({
      uid: 'admin',
      name: 'Admin',
      role_id: 'staff_admin'
    });
    await visit('/');

    assert.dom('a#account_menu_link').hasText('ADMIN');
  });

  test('visiting homepage', async function(assert) {
    await authenticateSession({
      uid: 'admin',
      name: 'Admin',
      role_id: 'staff_admin'
    });
    await visit('/');

    assert.equal(currentURL(), '/');
    assert.dom('h2.work').hasText('DataCite');
    assert.dom('a.nav-link.active').hasText('Info');
  });

  // the following pages require authentication. Redirects to homepage otherwise
  test('visiting settings', async function(assert) {
    await authenticateSession({
      uid: 'admin',
      name: 'Admin',
      role_id: 'staff_admin'
    });
    await visit('/settings');

    assert.equal(currentURL(), '/settings');
    assert.dom('h2.work').hasText('DataCite');
    assert.dom('a.nav-link.active').hasText('Settings');
  });

  test('visiting providers', async function(assert) {
    await authenticateSession({
      uid: 'admin',
      name: 'Admin',
      role_id: 'staff_admin'
    });
    await visit('/providers');

    assert.equal(currentURL(), '/providers');
    assert.dom('h2.work').hasText('DataCite');
    assert.dom('a.nav-link.active').hasText('Providers');
  });

  test('visiting repositories', async function(assert) {
    await authenticateSession({
      uid: 'admin',
      name: 'Admin',
      role_id: 'staff_admin'
    });
    await visit('/repositories');

    assert.equal(currentURL(), '/repositories');
    assert.dom('h2.work').hasText('DataCite');
    assert.dom('a.nav-link.active').hasText('Repositories');
  });

  test('visiting prefixes', async function(assert) {
    await authenticateSession({
      uid: 'admin',
      name: 'Admin',
      role_id: 'staff_admin'
    });
    await visit('/prefixes');

    assert.equal(currentURL(), '/prefixes');
    assert.dom('h2.work').hasText('DataCite');
  });

  test('visiting prefix 10.5072', async function(assert) {
    await authenticateSession({
      uid: 'admin',
      name: 'Admin',
      role_id: 'staff_admin'
    });
    await visit('/prefixes/10.5072');

    assert.equal(currentURL(), '/prefixes/10.5072');
    assert.dom('div.alert-warning').includesText('The page was not found.');
  });

  test('visiting dois', async function(assert) {
    await authenticateSession({
      uid: 'admin',
      name: 'Admin',
      role_id: 'staff_admin'
    });
    await visit('/dois');

    assert.equal(currentURL(), '/dois');
    assert.dom('h2.work').hasText('DataCite');
    assert.dom('a.nav-link.active').hasText('DOIs');
  });

  // test('visiting specific doi', async function(assert) {
  //   await authenticateSession({
  //     uid: 'admin',
  //     name: 'Admin',
  //     role_id: 'staff_admin'
  //   });
  //   await visit('/dois');

  //   // first DOI in list
  //   await click('h3.work:first-child a');

  //   assert.dom('button#edit-doi').includesText('Update DOI (Form)');
  //   assert.dom('button#modify-doi').includesText('Update DOI (File Upload)');
  // });
});
<|endoftext|>